]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/DEVEL/mathml_editor/src/LPushLexer.cc
ocaml 3.09 transition
[helm.git] / helm / DEVEL / mathml_editor / src / LPushLexer.cc
index 6ee43b3e9fde2d88b74612465128d9e4736e3e85..a16801bf0d03f6e533be2fce52d5ffd33823173a 100644 (file)
@@ -1,4 +1,33 @@
+/* This file is part of EdiTeX, an editor of mathematical
+ * expressions based on TeX syntax.
+ * 
+ * Copyright (C) 2002-2003 Luca Padovani <lpadovan@cs.unibo.it>,
+ *                    2003 Paolo Marinelli <pmarinel@cs.unibo.it>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * For more information, please visit the project's home page
+ * http://helm.cs.unibo.it/editex/
+ * or send an email to <lpadovan@cs.unibo.it>
+ */
 
+#include <string>
+#include <cctype>
+#include <cassert>
+
+#include "ALogger.hh"
 #include "TToken.hh"
 #include "LPushLexer.hh"
 #include "APushParser.hh"
@@ -13,6 +42,8 @@ LPushLexer::reset()
 {
   buffer.erase();
   state = ACCEPT;
+
+  displayCursor();
 }
 
 void
@@ -34,15 +65,11 @@ LPushLexer::transaction(char ch, State newState)
     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 '\t': parser.push(TToken(TToken::IGNORABLE_SPACE, ch)); break;
     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;
+    default: parser.push(TToken(TToken::OTHER, ch)); break;
     }
   state = newState;
 }
@@ -59,7 +86,12 @@ LPushLexer::push(char ch)
       else if (isalpha(ch))
        {
          buffer.push_back(ch);
-         state = LONG_IDENTIFIER;
+         state = IDENTIFIER;
+       }
+      else if (isdigit(ch))
+        {
+         buffer.push_back(ch);
+         state = NUMBER;
        }
       else transaction(ch, ACCEPT);
       break;
@@ -70,6 +102,12 @@ LPushLexer::push(char ch)
          state = MACRO;
        }
       else if (ch == -1) error();
+      else if (isdigit(ch))
+        {
+         // in this case, the previous '\' is ignored
+         buffer.push_back(ch);
+         state = NUMBER;
+       }
       else
        {
          parser.push(TToken(TToken::CONTROL, ch));
@@ -97,25 +135,27 @@ LPushLexer::push(char ch)
          buffer.erase();
          state = ACCEPT;
        }
-      else
-       {
-         parser.push(TToken(TToken::CONTROL, buffer));
-         buffer.erase();
-         if (isspace(ch)) state = IGNORE_SPACE;
-         else transaction(ch, ACCEPT);
+      else if (isspace(ch))
+          {
+           // we don't call transaction, because a white space is useful to exit from the macro,
+           // without "side effect". It's the TeX syntax.
+           parser.push(TToken(TToken::CONTROL, buffer));
+           buffer.erase();
+           state = 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))
+      else if (isdigit(ch))
         {
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
          buffer.push_back(ch);
-         state = LONG_IDENTIFIER;
+         state = NUMBER;
        }
-      else transaction(ch, ACCEPT);
+      else
+        {
+         parser.push(TToken(TToken::CONTROL, buffer));
+         buffer.erase();
+          transaction(ch, ACCEPT);
+        }
       break;
     case PARAMETER:
       if (ch == -1) error();
@@ -125,7 +165,7 @@ LPushLexer::push(char ch)
          state = ACCEPT;
        }
       break;
-    case LONG_IDENTIFIER:
+    case IDENTIFIER:
       if (ch == -1)
         {
          parser.push(TToken(TToken::LETTER, buffer));
@@ -136,30 +176,79 @@ LPushLexer::push(char ch)
         {
          buffer.push_back(ch);
        }
-      else if (isspace(ch))
+      else if (ch == '\\') state = ESCAPED_CHARACTER;
+      else if (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));
+         state = PARAMETER;
+       }
+      else
+        {
+         parser.push(TToken(TToken::LETTER, buffer));
          buffer.erase();
-         state = IGNORE_SPACE;
+         transaction(ch, ACCEPT);
        }
-      else if (ch == '\\')
+      break;
+    case ESCAPED_CHARACTER:
+      if ((ch == '-') || (ch == '_') || (ch == '/'))
         {
+         buffer.push_back(ch);
+         state = IDENTIFIER;
+       }
+      else if (isalpha(ch))
+       {
+         parser.push(TToken(TToken::LETTER, buffer));
+         buffer.erase();
+         buffer.push_back(ch);
+         state = MACRO;
+       }
+      else if (ch == -1) error();
+      else if (isdigit(ch))
+        {
+         parser.push(TToken(TToken::LETTER, buffer));
+         buffer.erase();
+         buffer.push_back(ch);
+         state = NUMBER;
+       }
+      else
+       {
          parser.push(TToken(TToken::LETTER, buffer));
          buffer.erase();
+         parser.push(TToken(TToken::CONTROL, ch));
+         state = ACCEPT;
+       }
+      break;
+    case NUMBER:
+      if (isdigit(ch)) buffer.push_back(ch);
+      else if (isalpha(ch))
+        {
+         parser.push(TToken(TToken::DIGIT, buffer));
+         buffer.erase();
+         buffer.push_back(ch);
+         state = IDENTIFIER;
+       }
+      else if (ch == -1)
+        {
+         parser.push(TToken(TToken::DIGIT, buffer));
+         buffer.erase();
+         state = ACCEPT;
+       }
+      else if (ch == '\\')
+        {
+         parser.push(TToken(TToken::DIGIT, buffer));
+         buffer.erase();
          state = ESCAPE;
        }
+      else if (ch == '#')
+        {
+         parser.push(TToken(TToken::DIGIT, buffer));
+         buffer.erase();
+         state = PARAMETER;
+       }
       else
         {
-         parser.push(TToken(TToken::LETTER, buffer));
+         parser.push(TToken(TToken::DIGIT, buffer));
          buffer.erase();
          transaction(ch, ACCEPT);
        }
@@ -169,14 +258,8 @@ LPushLexer::push(char ch)
       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;
-    }
+  displayCursor();
+
 }
 
 void
@@ -187,13 +270,56 @@ LPushLexer::drop(bool alt)
   switch (state)
     {
     case ACCEPT:
-    case IGNORE_SPACE:
-      restore = parser.drop();
-      if (restore.length() > 0 && restore[0] == '\\')
+      {
+        restore = parser.drop(alt);
+        long bs_pos = restore.find('\\');
+        if ((restore.length() > 0) && (bs_pos != std::string::npos))
+          {
+           // in this case we have to control the blackslash's position
+           if (bs_pos == 0)
+             {
+               //logger.debug(restore);
+               buffer = std::string(restore, 1, restore.length() - 1);
+               state = (buffer.length() > 0) ? MACRO : ESCAPE;
+             }
+           else
+             {
+               assert(bs_pos == restore.length() - 1);
+               buffer = std::string(restore, 0, bs_pos);
+               state = ESCAPED_CHARACTER;
+             }
+         }
+        else if (restore.length() > 0 && isdigit(restore[0]))
+          {
+           buffer = restore;
+           state = NUMBER;
+         }
+        else if (restore.length() > 0 && isalpha(restore[0]))
+          {
+           buffer = restore;
+           state = IDENTIFIER;
+         }
+      }
+      break;
+/*      if (restore.length() > 0 && restore[0] == '\\')
        {
+         logger.debug(restore);
          buffer = std::string(restore, 1, restore.length() - 1);
          state = (buffer.length() > 0) ? MACRO : ESCAPE;
        }
+      else if (restore.length() > 0 && isdigit(restore[0]))
+        {
+         buffer = restore;
+         state = NUMBER;
+       }
+      else if (restore.length() > 0 && isalpha(restore[0]))
+        {
+         buffer = restore;
+         state = IDENTIFIER;
+       }
+      break;*/
+    case ESCAPED_CHARACTER:
+      state = IDENTIFIER;
       break;
     case ESCAPE:
       state = ACCEPT;
@@ -203,21 +329,48 @@ LPushLexer::drop(bool alt)
       else buffer.erase(buffer.length() - 1, 1);
       if (buffer.length() == 0) state = ESCAPE;
       break;
-    case LONG_IDENTIFIER:
-      buffer.erase(buffer.length() - 1, 1);
+    case IDENTIFIER:
+      switch (buffer[buffer.length() - 1])
+       {
+       case '-':
+       case '_':
+         buffer.erase(buffer.length() - 1, 1);
+         if (alt) state = ESCAPED_CHARACTER;
+         break;
+       default:
+          if (alt) buffer.erase(); 
+          else buffer.erase(buffer.length() - 1, 1);
+          if (buffer.length() == 0) state = ACCEPT;
+          break;
+       }
+      break;
+    case NUMBER:
+      if (alt) buffer.erase();
+      else buffer.erase(buffer.length() - 1, 1);
       if (buffer.length() == 0) state = ACCEPT;
       break;
     case PARAMETER:
     default:
-      assert(0);
+      //assert(0);
+      error();
       break;
     }
 
+  displayCursor();
+
+}
+
+void
+LPushLexer::displayCursor()
+{
   switch (state)
     {
     case ESCAPE: parser.setCursorHint("\\"); break;
+    case ESCAPED_CHARACTER: parser.setCursorHint(buffer + "\\"); break;
     case MACRO: parser.setCursorHint("\\" + buffer); break;
     case PARAMETER: parser.setCursorHint("#"); break;
+    case IDENTIFIER: parser.setCursorHint(buffer); break;
+    case NUMBER: parser.setCursorHint(buffer); break;
     default: parser.setCursorHint(""); break;
     }
 }