]> matita.cs.unibo.it Git - helm.git/commitdiff
Now it's possible to insert and delete control sequence with arguments
authorPaolo Marinelli <paolo.marinelli@unibo.it>
Thu, 30 Jan 2003 21:15:41 +0000 (21:15 +0000)
committerPaolo Marinelli <paolo.marinelli@unibo.it>
Thu, 30 Jan 2003 21:15:41 +0000 (21:15 +0000)
delimited by a sequence of delimiters, and to insert and delete tables.
To meet this goals, some source files have been modified.
  src/TPushLexer.*
    This class has a new method: flush. It's can be used to tell the lexer
    to send the current content of the buffer to the parser.
    It's usefull in the creation of the dictionary.
  src/TDictionary.*
    There are two new method: bool lastDelimiter(unsigned p) and
    unsigned previousParam(unsigne p). The first one is used to know if
    the delimiter at position p is the last one of a sequence.
    The second one retursn the position of the parameter preceding p.
  src/TPushParser.cc
    Now, it provides support for inserting and deleting macro with
    arguments delimetd by a sequence of delimiters, and for inserting
    and deleting tables.
  dictionary.xml
    there are three new entry, added only for testing purposes.
  xsl/tml-mmlp.xsl
    it handles the three new element, introduced in the dictionary.

helm/DEVEL/mathml_editor/dictionary.xml
helm/DEVEL/mathml_editor/src/TDictionary.cc
helm/DEVEL/mathml_editor/src/TDictionary.hh
helm/DEVEL/mathml_editor/src/TPushLexer.cc
helm/DEVEL/mathml_editor/src/TPushLexer.hh
helm/DEVEL/mathml_editor/src/TPushParser.cc
helm/DEVEL/mathml_editor/src/TTokenizer.cc
helm/DEVEL/mathml_editor/test/editor.cc
helm/DEVEL/mathml_editor/xsl/tml-mmlp.xsl

index 023bcdbe16b0cc99717f1515a72b993ae5a65ed7..4c7045d48edf00d94f10c1cc16302576e151708e 100644 (file)
   <entry name="cases"        pattern="#1" table="1"/>
 
   <!-- MACRO for testing  -->
-  <entry name="paolo"        pattern="{"/>
+  <entry name="red"        pattern="{"/>
+  <entry name="green"      pattern="#1\over"/>
+  <entry name="duedelim"   pattern="#1\over\over#2"/>
 
 </dictionary>
index 303d743d441aa3399dc8639eb17354e9284bff14..dcaf1d627562f072f8a535fe1a8f62a6edb226fb 100644 (file)
@@ -134,7 +134,7 @@ TDictionary::load(const char* uri)
          {
            if (entry.cls != MACRO)
              cerr << "WARNING: `" << name << "' table ignored for non-macro" << endl;
-           
+
            std::istringstream is(el.getAttribute("table"));
            unsigned table;
            is >> table;
@@ -166,3 +166,32 @@ TDictionary::Entry::paramDelimited(unsigned i) const
   // AND the next argument is not a parameter
   return i + 1 < pattern.size() && pattern[i + 1].category != TToken::PARAMETER;
 }
+
+bool
+TDictionary::Entry::lastDelimiter(unsigned i) const
+{
+  assert(i < pattern.size());
+  assert(pattern[i].category != TToken::PARAMETER);
+  // a token is the last delimiter if it is the last token 
+  // of the pattern or if the next token is a parameter)
+  return i + 1 == pattern.size() || pattern[i + 1].category == TToken::PARAMETER;
+}
+
+unsigned
+TDictionary::Entry::previousParam(unsigned i) const
+{
+  // this method return the position in the pattern of the 
+  // parameter placed in a position preceding i.
+  // If no preceding i parameter present, the method return
+  // pattern.size().
+  // To know the position of the last parameter, call this 
+  // method with i == pattern.size()
+  unsigned j = i - 1;
+
+  while (pattern[j].category != TToken::PARAMETER)
+    {
+      if (j) j--;
+      else return pattern.size();
+    }
+  return j;
+}
index 44c020cbe1796fd1fe77bdabc8ef419e297b8e4c..b769aaa4ed32e18d205bbc6e05d5791c6990809f 100644 (file)
@@ -36,7 +36,7 @@ public:
     { 
       cls = UNDEFINED;
       infix = prefix = postfix = 0;
-      delimiter = limits = embellishment = leftOpen = rightOpen = 0;
+      table = delimiter = limits = embellishment = leftOpen = rightOpen = 0;
     };
 
     std::vector<TToken> pattern;
@@ -45,6 +45,8 @@ public:
     bool defined(void) const { return cls != UNDEFINED; };
     bool hasArguments(void) const { return !pattern.empty(); };
     bool paramDelimited(unsigned) const;
+    bool lastDelimiter(unsigned) const;
+    unsigned previousParam(unsigned) const;
 
     EntryClass cls;
     unsigned infix : 8;
index 4b24523da5e494c01ac2202bfbea438063fbf996..466ee2bd8b48c51644a4c901d16f7a178d59c15f 100644 (file)
@@ -15,6 +15,12 @@ TPushLexer::reset()
   state = ACCEPT;
 }
 
+void
+TPushLexer::flush()
+{
+  push(-1);
+}
+
 void
 TPushLexer::transaction(char ch, State newState)
 {
@@ -50,6 +56,7 @@ TPushLexer::push(char ch)
       if (ch == '\\') state = ESCAPE;
       else if (ch == '#') state = PARAMETER;
       else if (ch == '\b') parser.push(TToken(TToken::GDELETE));
+      else if (ch == -1) ;
       else transaction(ch, ACCEPT);
       break;
     case ESCAPE:
@@ -62,6 +69,7 @@ TPushLexer::push(char ch)
         {
          state = ACCEPT;
        }
+      else if (ch == -1) error();
       else
        {
          parser.push(TToken(TToken::CONTROL, ch));
@@ -88,6 +96,12 @@ TPushLexer::push(char ch)
        }
       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));
@@ -101,11 +115,16 @@ TPushLexer::push(char ch)
       else if (ch == '#') state = PARAMETER;
       else if (isspace(ch)) ;
       else if (ch == '\b') parser.push(TToken(TToken::GDELETE));
+      else if (ch == -1) state = ACCEPT;
       else transaction(ch, ACCEPT);
       break;
     case PARAMETER:
-      parser.push(TToken(TToken::PARAMETER, ch));
-      state = ACCEPT;
+      if (ch == -1) error();
+      else
+        {
+         parser.push(TToken(TToken::PARAMETER, ch));
+         state = ACCEPT;
+       }
       break;
     default:
       assert(0);
index ff61561ec174e4d33c96bf16261caae5c20d02db..6fd212a3de319e19f102f4f5b13722a0cf2a0e23 100644 (file)
@@ -14,6 +14,7 @@ public:
 
   virtual void push(char);
   virtual void reset(void);
+  virtual void flush(void);
   virtual bool error(void) const;
 
 private:
index a063668e0ae31dd03e44f2719733276aa52cda7a..d3dd893d73c494ad8b6648fd4ae74242b557349f 100644 (file)
@@ -68,12 +68,16 @@ TPushParser::do_end()
     }
   else if (parent && parent.isG() && parent.parent() && parent.parent().is("cell"))
     {
+      assert(!frames.empty());
       // closing brace for a structure in which & or \cr have been used
       TNode row = parent.parent().parent();
       assert(row && row.is("row"));
       TNode table = row.parent();
       assert(table);
       advance(table);
+
+      // now we have to pop the associated frame in the stack
+      frames.pop();
     }
   else if (parent && parent.isG() && !parent.hasId() && parent.parent())
     {
@@ -452,9 +456,13 @@ TPushParser::do_control(const std::string& name)
                if (parent.isG())
                  {
                    frames.push(Frame(entry));
-                   cout << "do_control: valore di pos del frame inserito " << frames.top().pos << endl;
+
+                   if (entry.table)
+                     cout << "do_control: we have a table" << endl;
+                   
                    if (entry.paramDelimited(0))
                      {
+                       cout << "do_control: it'a MACRO with delimited first argument" << endl;
                        TNode g = doc.createG();
                        m.append(g);
                        g.append(cursor);
@@ -532,7 +540,7 @@ TPushParser::gdelete_prev()
       prev.append(cursor);
       do_gdelete();
     }
-  else if (prev.isC())
+  else if (prev.isC() && dictionary.find(prev["name"]).cls != TDictionary::UNDEFINED)
     {
       const TDictionary::Entry& entry = dictionary.find(prev["name"]);
 
@@ -581,8 +589,11 @@ TPushParser::gdelete_prev()
              prev.last().append(cursor);
              // i have to push a frame with a correct value of pos
              Frame frame(entry);
-             frame.pos = entry.pattern.size() - 2;
+             assert(entry.previousParam(entry.pattern.size()) != entry.pattern.size());
+             unsigned sequence_length = entry.pattern.size() - entry.previousParam(entry.pattern.size()) - 1;
+             frame.pos = entry.pattern.size() - sequence_length - 1;
              frames.push(frame);
+             cout << "gdelete_prev: i have inserted a frame, it's pos is: " << frames.top().pos << endl;
            }
          else
            {
@@ -591,17 +602,32 @@ TPushParser::gdelete_prev()
              // remove it
              cout << "gdelete_prev: i try to remove the last argumet of the MACRO" << endl;
              cursor.remove();
-             prev.append(cursor); // now prev is the cursor's parent
+             if (entry.table == 1 && prev.last().is("row"))
+               {
+                 // in this case should be appended to the group associated to 
+                 // the last cell of the last row of the table
+                 assert(prev.last().last().is("cell") && prev.last().last().first().isG());
+                 prev.last().last().first().append(cursor);
+               }
+             else prev.append(cursor);
 
              Frame frame(entry);
              frame.pos = entry.pattern.size();
              frames.push(frame);
              
-             gdelete_prev();
+             if (cursor.prev()) gdelete_prev();
+             else do_gdelete();
 
            }
        }
     }
+  else if (dictionary.find(prev["name"]).cls == TDictionary::UNDEFINED)
+    {
+      // The user wants to delete an undefined element.
+      // I suppose that he (or she) wants to delete it all
+      cursor.remove();
+      prev.replace(cursor);
+    }
   else 
     {
       // not handled
@@ -758,14 +784,20 @@ TPushParser::do_gdelete()
                                  TNode uncle = parent.prev();
                                  if (uncle.isG() && !uncle.hasId())
                                    {
-                                     // the cursor's parent is a phantom group, so it was a 
-                                     // delimited argument of the MACRO and the corrisponding 
-                                     // delimeter is inserted. So, the action of deleting means
-                                     // removing this delimeter
+                                     // the cursor's uncle is a phantom group, so it was a 
+                                     // delimited argument of the MACRO and the corrisponding sequence of 
+                                     // delimeters is inserted. So, the action of deleting means
+                                     // removing this sequence
+                                     assert(frame.pos > 1);
+                                     unsigned sequence_length = frame.pos - frame.entry.previousParam(frame.pos) - 1;
+                                     assert(frame.entry.previousParam(frame.pos) != frame.entry.pattern.size());
+                                     assert(sequence_length);
+                                     // sequence_length is the length of the delimiters sequence which separates
+                                     // the current parameter and the previous parameter
+                                     frame.pos = frame.pos - sequence_length - 1;
                                      cursor.remove();
                                      parent.remove();
                                      uncle.append(cursor);
-                                     frame.pos -= 2;
                                    }
                                  else
                                    {
@@ -797,6 +829,65 @@ TPushParser::do_gdelete()
                            
                            }
                        }
+                     else if (gfuther.is("cell"))
+                       {
+                         // being here means that there is a frame in the stack 
+                         // associated to the "table"
+                         cout << "do_gdelete: i have to delete a cell" << endl;
+                         assert(!frames.empty());
+                         assert(frames.top().pos == 1);
+                         assert(frames.top().entry.table == 1);
+                         // a cell MUST be child of row element, which in turn MUST be child of an element 
+                         // havin attribute table.
+                         assert(gfuther.parent() && gfuther.parent().is("row") && gfuther.parent().parent());
+                         TNode row = gfuther.parent();
+
+                         // in this case the cell has no element, so the user wants to delete this cell.
+                         TNode prev_cell = gfuther.prev();
+                         
+                         cursor.remove();
+                         parent.remove();
+                         gfuther.remove();
+                         // now the cell no longer exists
+                         
+                         if (!prev_cell)
+                           {
+                             // i this case, the cell is the only cell in the row.
+                             // So, i assume that the user wants to delete the entire row.
+                             TNode table = row.parent();
+                             TNode prev_row = row.prev();
+                             row.remove();
+                             if (!prev_row)
+                               {
+                                 // the row was the only child of the table. 
+                                 // I think have to delete the entire table
+                                 assert(table.parent());
+                                 TNode parent_table = table.parent();
+                                 table.remove();
+                                 frames.pop();
+                                 parent_table.append(cursor);
+                               }
+                             else
+                               {
+                                 // there are other rows (one at least)
+                                 assert(prev_row.is("row"));
+                                 assert(prev_row.last());
+                                 TNode last_cell = prev_row.last();
+                                 assert(last_cell.is("cell"));
+                                 assert(last_cell.size() == 1);
+                                 assert(last_cell.first().isG() && !last_cell.first().hasId());
+                                 last_cell.first().append(cursor);
+                               }
+                           }
+                         else
+                           {
+                             // being here means that there is a previous cell,
+                             // so we append the cursor to group.
+                             assert(prev_cell.size() == 1);
+                             assert(prev_cell.first().isG() && !prev_cell.first().hasId());
+                             prev_cell.first().append(cursor);
+                           }
+                       }
                    }
                  else // the grand futher is math
                    {
@@ -848,12 +939,16 @@ TPushParser::do_gdelete()
              if (prev.isG() && !prev.hasId())
                {
                  // in this case we have to append the cursor 
-                 // to the prev and decrement frame.pos of two units
-                 // because the prev is a delimited argument and the 
-                 // delimiter is inserted. So we ideally remove this delimiter
+                 // to the prev and decrement frame.pos of the length of 
+                 // delimiters sequence that delimitates the preceding argument.
+                 // So we ideally remove this sequence
+                 assert(frame.pos > 1);
                  cursor.remove();
                  prev.append(cursor);
-                 frame.pos -=2;
+                 assert(frame.entry.previousParam(frame.pos) != frame.entry.pattern.size());
+                 unsigned sequence_length = frame.pos - frame.entry.previousParam(frame.pos) - 1;
+                 assert(sequence_length);
+                 frame.pos = frame.pos - sequence_length - 1;
                }
              else
                {
@@ -867,14 +962,14 @@ TPushParser::do_gdelete()
         {
          // being here means that a prev MUST exist 
          // and that there is only an element preceding the cursor.
-         // A sp's (or sb's) MUST NOT be a MACRO
+         // The sp's (or sb's) parent MUST NOT be a MACRO
 
          assert(parent.size() == 2);
          assert(parent.parent() && !parent.parent().isC());
          
          TNode prev = cursor.prev();
          cursor.remove();
-         if (prev.isG() && !prev.hasId() && (prev.size() == 0))
+         if (prev.isG() /*&& !prev.hasId()*/ && (prev.size() == 0))
            {
              prev.remove();
              parent.replace(cursor);
@@ -900,7 +995,7 @@ TPushParser::do_gdelete()
     }
   else
     {
-      // the cursro has no parent!!!
+      // the cursor has no parent!!!
       // do nothing?
       // emit an error? and if we want to emit an error, in which way?
     }
@@ -941,132 +1036,160 @@ TPushParser::push(const TToken& token)
       cout << "push: i have to process a token with category member = GDELETE" << endl;
       process(token);
     }
-  else
+  else if ((doc.root().first() && doc.root().first().is("math")) || token.category == TToken::SHIFT)
     {
 
-  TNode parent = cursor.parent();
-  // If the cursor has no parent then it is detached from the editing
-  // tree, which means this token will be ignored
-
-  if (parent)
-    // If the parent is a phantom group and the grand-parent is a
-    // control sequence, there are two cases:
-    // a. we are parsing a delimited argument of a entry
-    // b. we are parsing a side of a right- or left-open entry
-    if (parent.isG() && !parent.hasId() && parent.parent().isC())
-      {
-       // There must be an open frame, for the grand-parent is a control sequence
-       assert(!frames.empty());
-       Frame& frame = frames.top();
-       if (!frame.entry.pattern.empty())
-         {
-           // The entry pattern is not empty. By our conventions this means
-           // the entry cannot be open at either end, hence we are parsing
-           // a delimited argument
-           assert(frame.pos + 1 < frame.entry.pattern.size());
-           assert(frame.entry.pattern[frame.pos + 1].category != TToken::PARAMETER);
-           if (frame.entry.pattern[frame.pos + 1] == token)
+      TNode parent = cursor.parent();
+      // If the cursor has no parent then it is detached from the editing
+      // tree, which means this token will be ignored
+
+      if (parent)
+        // If the parent is a phantom group and the grand-parent is a
+        // control sequence, there are two cases:
+        // a. we are parsing a delimited argument of a entry
+        // b. we are parsing a side of a right- or left-open entry
+        if (parent.isG() && !parent.hasId() && parent.parent().isC())
+          {
+           // There must be an open frame, for the grand-parent is a control sequence
+           assert(!frames.empty());
+           Frame& frame = frames.top();
+           if (!frame.entry.pattern.empty())
              {
-               // The token matches with the delimiter of the argument.
-               cursor.remove();
-
-               // If the phantom group has just one child, it is not necessary
-               // and can be removed. However, this would complicate
-               // all the code that follows, so given it is a rare case we
-               // leave it alone
-               // if (parent.size() == 1) parent.replace(parent[0]);
-
-               // Eat both the argument and its delimiter
-               frame.pos += 2;
-               if (frame.pos == frame.entry.pattern.size())
-                 {
-                   // This token has completed the entry
-                   advance(parent.parent());
-                 }
-               else if (frame.entry.paramDelimited(frame.pos))
-                 {
-                   // For the next is a delimited argument we have to place
-                   // a suitable phantom group with the cursor inside
-                   TNode g = doc.createG();
-                   parent.parent().append(g);
-                   g.append(cursor);
-                 }
-               else
-                 parent.parent().append(cursor);
+               // The entry pattern is not empty. By our conventions this means
+               // the entry cannot be open at either end, hence we are parsing
+               // a delimited argument
+               assert(frame.pos + 1 < frame.entry.pattern.size());
+               assert(frame.entry.pattern[frame.pos + 1].category != TToken::PARAMETER);
+               if (frame.entry.pattern[frame.pos + 1] == token)
+                 {
+                   // The token matches with a delimiter of the argument, 
+                   // so we increment the frame.pos
+                   frame.pos++;
+
+                   if (frame.entry.lastDelimiter(frame.pos))
+                     {
+                       // this delimiter is the last one for the argumet, 
+                       // so the argument is completed
+                       cursor.remove();
+                       frame.pos++;
+
+                       if (frame.pos == frame.entry.pattern.size())
+                         {
+                           // This token has completed the entry
+                           frames.pop();
+                           advance(parent.parent());
+                         }
+                       else if (frame.entry.paramDelimited(frame.pos))
+                         {
+                           // For the next is a delimited argument we have to place
+                           // a suitable phantom group with the cursor inside
+                           TNode g = doc.createG();
+                           parent.parent().append(g);
+                           g.append(cursor);
+                         }
+                       else
+                         parent.parent().append(cursor);
+                     }
+                 }
+               else
+                 {
+                   // Delimiter mismatch.
+                   if (frame.entry.pattern[frame.pos].category != TToken::PARAMETER)
+                     {
+                       // in this case, there is a sequence of delimiters that delimitates
+                       // the argument, and the user correctly inserted a portion of this 
+                       // sequence, but has inserted a wrong delimiter.
+                       // Here, there are some possibilities:
+                       //   - ignore the token, and wait for the correct delimiter
+                       //   - ignore the token, wait for the correct delimiter and emit an error
+                       // If we want to emit an error, we shlould implement a class, that handle 
+                       // the error.
+                       // At the moment, the error is printed to screen
+                       cout << "push: it's not the correct delimiter...you have to type " << frame.entry.pattern[frame.pos + 1].value << endl;
+                     }
+                   else
+                     {
+                       // in this case, the sequence of delimiters is composed of one 
+                       // delimiter. It means that we have to process the token
+                       process(token);
+                     }
+                 }
              }
            else
              {
-               // Delimiter mismatch. Since we are parsing a delimited
-               // argument we just process the token
-               process(token);
+               // The entry pattern is empty, hence we are parsing a right-open
+               // entry. What happens if we actually are in the left side?
+               // This could happen only when re-editing an entered expression
+               // We'll see...
+               assert(frame.entry.rightOpen);
+               process(token);
              }
-         }
-       else
-         {
-           // The entry pattern is empty, hence we are parsing a right-open
-           // entry. What happens if we actually are in the left side?
-           // This could happen only when re-editing an entered expression
-           // We'll see...
-           assert(frame.entry.rightOpen);
-           process(token);
-         }
-      }
-    else if (parent.isC())
-      {
-       // We are parsing a non-delimited argument entry
-       // or a fixed token
-       Frame& frame = frames.top();
-       assert(frame.pos < frame.entry.pattern.size());
-
-       cout << "push: il valore di pos del frame inserito prima e': " << frame.pos <<  endl;
-       if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER)
-         {
-           // As by the TeX parsing rules of undelimited parameters,
-           // empty spaces are ignored
-           if (token.category != TToken::SPACE)
+          }
+        else if (parent.isC())
+          {
+           // We are parsing a non-delimited argument entry
+           // or a fixed token
+           Frame& frame = frames.top();
+           assert(frame.pos < frame.entry.pattern.size());
+
+           cout << "push: there is a frame with pos " << frame.pos <<  endl;
+           if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER)
              {
-               // We need to increase the frame position here, becase inside
-               // process the function advance will be called. At that point
-               // it will be important for the parser to know that the entry
-               // has been completed in order to place the cursor correctly
-               // in the next position
-               frame.pos++;
-               process(token);
+               // As by the TeX parsing rules of undelimited parameters,
+               // empty spaces are ignored
+               if (token.category != TToken::SPACE)
+                 {
+                   // We need to increase the frame position here, becase inside
+                   // process the function advance will be called. At that point
+                   // it will be important for the parser to know that the entry
+                   // has been completed in order to place the cursor correctly
+                   // in the next position
+                   frame.pos++;
+                   process(token);
+                 }
              }
-         }
-       else if (frame.entry.pattern[frame.pos] == token)
-         {
-           // The token has been accepted
-           frame.pos++;
-           if (frame.pos < frame.entry.pattern.size() &&
-               frame.entry.paramDelimited(frame.pos))
+           else if (frame.entry.pattern[frame.pos] == token)
              {
-               // If the next is a delimited argument we have to place
-               // the phantom group with the cursor inside
-               TNode g = doc.createG();
-               cursor.replace(g);
-               g.append(cursor);
+               // The token has been accepted
+               frame.pos++;
+               if (frame.pos < frame.entry.pattern.size() &&
+                   frame.entry.paramDelimited(frame.pos))
+                 {
+                   // If the next is a delimited argument we have to place
+                   // the phantom group with the cursor inside
+                   TNode g = doc.createG();
+                   cursor.replace(g);
+                   g.append(cursor);
+                 }
+               else
+                 advance(parent);
              }
            else
-             advance(parent);
-         }
-       else
-         {
-           // There is a mismatch. Emit an error and ignore the token?
-           cerr << "ERROR: token ignored: " << token.value << " (cat: " << token.category << ")" << endl;
-         }
+             {
+               // There is a mismatch. Emit an error and ignore the token?
+               cerr << "ERROR: token ignored: " << token.value << " (cat: " << token.category << ")" << endl;
+             }
 
-      }
-    else
-      process(token);
+          }
+        else
+          process(token);
+      else
+        {
+          cout << "ignored token" << endl;
+        }
+      
+      if (listener) listener->callback(doc); //it shoul be repristened if you remove the comment in the else above
+
+    } // this end corresponds to the if ((doc.root().first() && doc.root().first().is("math")) || token.category == TToken::SHIFT)
   else
     {
-      cout << "ignored token" << endl;
+      // there is no math element
+      // In this case, i think we have to emit an error
+      cout << "push: ignored token...you have to enter in math mode...insert $" << endl;
     }
 
-  } // this end corresponds to the else of the if (token.category == GDELETE)
 
-  if (listener) listener->callback(doc);
+  //if (listener) listener->callback(doc);
 
   if (frames.empty()) cout << "stack vuoto" << endl;
   else cout << "stack non vuoto" << endl;
index cf74c1d4f2237e52601990fb4d6ee9e6c01e928d..93cadefd7efba5ec1cd6db38e1eb529393c5c0f5 100644 (file)
@@ -14,7 +14,8 @@ TTokenizer::tokenize(const std::string& s)
        p != s.end();
        p++)
     lexer.push(*p);
-  //lexer.push('\n');
+  
+  lexer.flush();
 
   std::vector<TToken> res;
   res.reserve(tokens.size());
index 8ee408a3db41777c1a0c9aa080c5175bf35d7f7e..e12700e3a89662439e5e24db88e698852fb96f90 100644 (file)
@@ -84,6 +84,7 @@ public:
        if (result)
          dirtyId.push_back(std::make_pair(DOM::GdomeString("id"),
                                           DOM::GdomeString("'" + std::string(dirty["id"]) + "'")));
+
        DOM::Document res = style.apply(doc.document(), dirtyId);
        assert(res);
        style.save(doc.document(), stdout);
index 69de8c52e38531b7d96f4bd4b48946b620530066..034c5073a1920e147d3b20f8f75573fa191279ae 100644 (file)
     </m:mrow>
   </xsl:template>
 
+  <xsl:template match="tml:c[@name='red']">
+<!-- red  -->
+    <m:mstyle mathcolor="red">
+      <xsl:if test="@id">
+        <xsl:attribute name="xref">
+         <xsl:value-of select="@id"/>
+       </xsl:attribute>
+       <xsl:apply-templates/>
+      </xsl:if>
+    </m:mstyle>
+  </xsl:template>
+
+  <xsl:template match="tml:c[@name='green']">
+<!-- green  -->
+    <m:mstyle mathcolor="green">
+      <xsl:if test="@id">
+        <xsl:attribute name="xref">
+         <xsl:value-of select="@id"/>
+       </xsl:attribute>
+       <xsl:apply-templates/>
+      </xsl:if>
+    </m:mstyle>
+  </xsl:template>
+
+  <xsl:template match="tml:c[@name='duedelim']">
+<!-- duedelim  -->
+    <m:mfrac>
+      <xsl:if test="@id">
+        <xsl:attribute name="xref">
+          <xsl:value-of select="@id"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:apply-templates select="*[1]"/>
+      <xsl:apply-templates select="*[2]"/>
+    </m:mfrac>
+  </xsl:template>
+
 </xsl:stylesheet>