]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/DEVEL/mathml_editor/src/LPushLexer.cc
Bug fixed. In the previous version, all right open macros and all delimited arguments
[helm.git] / helm / DEVEL / mathml_editor / src / LPushLexer.cc
diff --git a/helm/DEVEL/mathml_editor/src/LPushLexer.cc b/helm/DEVEL/mathml_editor/src/LPushLexer.cc
new file mode 100644 (file)
index 0000000..6ee43b3
--- /dev/null
@@ -0,0 +1,229 @@
+
+#include "TToken.hh"
+#include "LPushLexer.hh"
+#include "APushParser.hh"
+
+LPushLexer::LPushLexer(ALogger& l, APushParser& p) : APushLexer(l, p)
+{
+  state = ACCEPT;
+}
+
+void
+LPushLexer::reset()
+{
+  buffer.erase();
+  state = ACCEPT;
+}
+
+void
+LPushLexer::flush()
+{
+  push(-1);
+}
+
+void
+LPushLexer::transaction(char ch, State newState)
+{
+  switch (ch)
+    {
+    case '{': parser.push(TToken(TToken::BEGIN)); break;
+    case '}': parser.push(TToken(TToken::END)); break;
+    case '$': parser.push(TToken(TToken::SHIFT)); break;
+    case '&': parser.push(TToken(TToken::ALIGN)); break;
+    case '\n':
+    case '\r': parser.push(TToken(TToken::EOL, ch)); break;
+    case '^': parser.push(TToken(TToken::SUPERSCRIPT)); break;
+    case '_': parser.push(TToken(TToken::SUBSCRIPT)); break;
+    case '\t':
+    case ' ': parser.push(TToken(TToken::SPACE, ch)); break;
+    case '~': parser.push(TToken(TToken::ACTIVE, ch)); break;
+    case '%': parser.push(TToken(TToken::COMMENT)); break;     
+    default:
+      if (isalpha(ch)) parser.push(TToken(TToken::LETTER, ch));
+      else if (isdigit(ch)) parser.push(TToken(TToken::DIGIT, ch));
+      else parser.push(TToken(TToken::OTHER, ch));
+      break;
+    }
+  state = newState;
+}
+
+void
+LPushLexer::push(char ch)
+{
+  switch (state)
+    {
+    case ACCEPT:
+      if (ch == '\\') state = ESCAPE;
+      else if (ch == '#') state = PARAMETER;
+      else if (ch == -1) ;
+      else if (isalpha(ch))
+       {
+         buffer.push_back(ch);
+         state = LONG_IDENTIFIER;
+       }
+      else transaction(ch, ACCEPT);
+      break;
+    case ESCAPE:
+      if (isalpha(ch))
+       {
+         buffer.push_back(ch);
+         state = MACRO;
+       }
+      else if (ch == -1) error();
+      else
+       {
+         parser.push(TToken(TToken::CONTROL, ch));
+         state = ACCEPT;
+       }
+      break;
+    case MACRO:
+      if (ch == '\\')
+       {
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
+         state = ESCAPE;
+       }
+      else if (ch == '#')
+       {
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
+         state = PARAMETER;
+       }
+      else if (isalpha(ch))
+       buffer.push_back(ch);
+      else if (ch == -1)
+        {
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
+         state = ACCEPT;
+       }
+      else
+       {
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
+         if (isspace(ch)) state = IGNORE_SPACE;
+         else transaction(ch, ACCEPT);
+       }
+      break;
+    case IGNORE_SPACE:
+      if (ch == '\\') state = ESCAPE;
+      else if (ch == '#') state = PARAMETER;
+      else if (isspace(ch)) ;
+      else if (ch == -1) state = ACCEPT;
+      else if (isalpha(ch))
+        {
+         buffer.push_back(ch);
+         state = LONG_IDENTIFIER;
+       }
+      else transaction(ch, ACCEPT);
+      break;
+    case PARAMETER:
+      if (ch == -1) error();
+      else
+        {
+         parser.push(TToken(TToken::PARAMETER, ch));
+         state = ACCEPT;
+       }
+      break;
+    case LONG_IDENTIFIER:
+      if (ch == -1)
+        {
+         parser.push(TToken(TToken::LETTER, buffer));
+         buffer.erase();
+         state = ACCEPT;
+       }
+      else if (isalpha(ch) || isdigit(ch))
+        {
+         buffer.push_back(ch);
+       }
+      else if (isspace(ch))
+        {
+         parser.push(TToken(TToken::LETTER, buffer));
+
+         // the parser ignores spaces. But in this case, the space 
+         // is a significant. So, we transform this space in the MACRO 
+         // \; which will not be ignored. 
+         // This is not a good solution. Having a special token, that will be 
+         // interpreted as "function application" is a better one.
+         buffer.erase();
+         buffer = ";";
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
+         state = IGNORE_SPACE;
+       }
+      else if (ch == '\\')
+        {
+         parser.push(TToken(TToken::LETTER, buffer));
+         buffer.erase();
+         state = ESCAPE;
+       }
+      else
+        {
+         parser.push(TToken(TToken::LETTER, buffer));
+         buffer.erase();
+         transaction(ch, ACCEPT);
+       }
+      break;
+    default:
+      assert(0);
+      break;
+    }
+
+  switch (state)
+    {
+    case ESCAPE: parser.setCursorHint("\\"); break;
+    case MACRO: parser.setCursorHint("\\" + buffer); break;
+    case PARAMETER: parser.setCursorHint("#"); break;
+    case LONG_IDENTIFIER: parser.setCursorHint(buffer); break;
+    default: parser.setCursorHint(""); break;
+    }
+}
+
+void
+LPushLexer::drop(bool alt)
+{
+  std::string restore = "";
+
+  switch (state)
+    {
+    case ACCEPT:
+    case IGNORE_SPACE:
+      restore = parser.drop();
+      if (restore.length() > 0 && restore[0] == '\\')
+       {
+         buffer = std::string(restore, 1, restore.length() - 1);
+         state = (buffer.length() > 0) ? MACRO : ESCAPE;
+       }
+      break;
+    case ESCAPE:
+      state = ACCEPT;
+      break;
+    case MACRO:
+      if (alt) buffer.erase();
+      else buffer.erase(buffer.length() - 1, 1);
+      if (buffer.length() == 0) state = ESCAPE;
+      break;
+    case LONG_IDENTIFIER:
+      buffer.erase(buffer.length() - 1, 1);
+      if (buffer.length() == 0) state = ACCEPT;
+      break;
+    case PARAMETER:
+    default:
+      assert(0);
+      break;
+    }
+
+  switch (state)
+    {
+    case ESCAPE: parser.setCursorHint("\\"); break;
+    case MACRO: parser.setCursorHint("\\" + buffer); break;
+    case PARAMETER: parser.setCursorHint("#"); break;
+    default: parser.setCursorHint(""); break;
+    }
+}
+
+bool
+LPushLexer::error() const
+{
+  return false;
+}