]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/DEVEL/mathml_editor/src/TPushParser.cc
* code cleanup
[helm.git] / helm / DEVEL / mathml_editor / src / TPushParser.cc
index ea82cf379251858d2f9536d56369d98fe513701b..325b9aa3c129f9a9bd31500aeec01ed6850184f1 100644 (file)
@@ -1,13 +1,14 @@
 
+#include "ALogger.hh"
 #include "TPushParser.hh"
-#include "TListener.hh"
+#include "AMathMLFactory.hh"
 
-TPushParser::TPushParser(const TDictionary& d) : dictionary(d), listener(0)
+TPushParser::TPushParser(ALogger& l, const TDictionary& d) : APushParser(l), dictionary(d)
 {
   init();
 }
 
-TPushParser::TPushParser(const TDictionary& d, TListener& l) : dictionary(d), listener(&l)
+TPushParser::TPushParser(ALogger& l, AMathMLFactory& f, const TDictionary& d) : APushParser(l, f), dictionary(d)
 {
   init();
 }
@@ -68,18 +69,23 @@ 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())
     {
       // closing brace for a right-open macro (like \over)
       cursor.remove();
       advance(parent.parent());
+      frames.pop();
     }
   else
     {
@@ -254,7 +260,7 @@ TPushParser::do_space(const std::string&)
 void
 TPushParser::do_letter(const std::string& s)
 {
-  TNode parent = cursor.parent();
+  //TNode parent = cursor.parent();
   TNode elem = doc.createI(s, nextId++);
   cursor.replace(elem);
   advance(elem);
@@ -410,6 +416,11 @@ TPushParser::do_control(const std::string& name)
          {
            TNode m = doc.createC(name, nextId++);
            cursor.replace(m);
+           
+           cout << "ecco tutti i token del pattern della entry inserita" << endl;
+           for (unsigned i = 0; i < entry.pattern.size(); i++)
+             cout << entry.pattern[i].value << endl;
+           
            if (entry.leftOpen && entry.rightOpen)
              {
                assert(entry.pattern.empty());
@@ -446,8 +457,13 @@ TPushParser::do_control(const std::string& name)
                if (parent.isG())
                  {
                    frames.push(Frame(entry));
+
+                   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);
@@ -478,6 +494,515 @@ TPushParser::do_control(const std::string& name)
     }
 }
 
+void
+TPushParser::gdelete_prev()
+{
+  // if in this function, the prev of cursor does exist, also the parent and we want a graphical deleting.
+
+  assert(cursor.prev());
+  assert(cursor.parent());
+
+  TNode prev = cursor.prev();
+  if (prev.is("i") || prev.is("o") || prev.is("n"))
+    {
+      // the control below is designed to handle the case in which val have more than one unicode character
+      DOM::UCS4String ucs4val(prev.element().getAttribute("val"));
+      if ((ucs4val.length() <= 1) || prev.element().hasAttribute("name"))
+        {
+         cursor.remove();
+         prev.replace(cursor);
+
+         if (cursor.parent().isC())
+           {
+             // in this case we have removed an element of a MACRO. 
+             // we can assert that this element was a non delimited argument
+             assert(!frames.empty());
+             Frame& frame = frames.top();
+             assert(frame.pos > 0);
+
+             frame.pos--;
+           }
+       }
+      else
+        {
+         ucs4val.erase(ucs4val.length() - 1, 1);
+         prev.element().setAttribute(DOM::GdomeString("val"), DOM::GdomeString(ucs4val));
+       }
+    } // end of if (prev.is("i") || ...)
+  else if (prev.is("sp") || prev.is("sb"))
+    {
+      cursor.remove();
+      prev.append(cursor);
+      gdelete_prev();
+    } // end of if (prev.is("sp") || prev.is("sb"))
+  else if (prev.isG())
+    {
+      cursor.remove();
+      prev.append(cursor);
+      do_gdelete();
+    }
+  else if (prev.isC() && dictionary.find(prev["name"]).cls != TDictionary::UNDEFINED)
+    {
+      const TDictionary::Entry& entry = dictionary.find(prev["name"]);
+
+      // i start to remove a MACRO. The frame associated to this MACRO was 
+      // popped from the stack (i think). So, i re-push the frame in the stack,
+      // but the pos member should be set correctly
+      cout << "gdelete_prev: i have to start to delete a MACRO" << endl;
+      
+      // if the control element is leftOpen and rightOpen, the cursor should be placed after 
+      // the last child of the control element's last child
+      if (entry.rightOpen)
+        {
+         cout << "gdelte_prev(): i have to delete a control rightOpen, so i push an element in the stack" << endl;
+         Frame frame(entry);
+         frames.push(frame);
+         
+         cursor.remove();
+         prev.last().append(cursor);
+         do_gdelete();
+       }
+      else if (entry.leftOpen)
+        {
+         cout << "gdelete_prev: i have to delete a control element with leftOpen" << endl;
+         assert(prev.first());
+         assert(prev.first().isG());
+         assert(prev.first() == prev.last());
+         TNode g = prev.first();
+         g.remove();
+         prev.replace(g.first(), TNode());
+       }
+      else if (!entry.pattern.empty())
+        { 
+         // we have to start removing a MACRO which accepts arguments.
+         // a MACRO without child does not exist
+         
+         cout << "gdelete_prev: i have to remove a MACRO with argument" << endl;
+
+         assert(prev.size() >= 1);
+
+         if (prev.last().isG() && !prev.last().hasId())
+           {
+             // this means that the last child of the MACRO is a phantom group,
+             // which in turn means that it is a delimited argument
+             // so we have to ideally remove this delimiter
+             cursor.remove();
+             prev.last().append(cursor);
+             // i have to push a frame with a correct value of pos
+             Frame frame(entry);
+             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
+           {
+             // in this case, the last child of the MACRO is 
+             // an argument which is NOT delimited, so i try to 
+             // remove it
+             cout << "gdelete_prev: i try to remove the last argumet of the MACRO" << endl;
+             cursor.remove();
+             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);
+             
+             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
+    }
+  
+} // end of method
+
+void
+TPushParser::rgreplace_futher(void)
+{
+  // this function MUST only be invoked, when the cursor
+  // is the only child of a group with id. This function 
+  // replace the group with the cursor. But if the new parent
+  // is a group with id and the cursor is the only child of the 
+  // group, the new parent is replaced...and so on.
+  // r stands for recursive, g stands for graphical
+  assert(cursor.parent());
+  assert(cursor.parent().isG() && cursor.parent().hasId());
+
+  TNode parent = cursor.parent();
+
+  while (parent.isG() && parent.hasId() && (parent.first() == cursor))
+    {
+      parent.replace(cursor);
+      parent = cursor.parent();
+    }
+
+  if (parent.isC())
+    {
+      // in this case we have removed a MACRO's child. 
+      // I can assert that this MACRO accepts arguments.
+      assert(!frames.empty());
+      Frame& frame = frames.top();
+      assert(frame.pos > 0);
+      frame.pos--;
+    }
+}
+
+void
+TPushParser::do_gdelete()
+{
+  // this function operates a graphical deleting
+  
+  //if (!frames.empty())
+  //  cout << "do_gdelete: c'e' un frame aperto e il suo pos vale: " << frames.top().pos << endl;
+  
+  TNode parent = cursor.parent();
+
+  // if no parent, do nothing
+  if (parent)
+    {
+      assert(parent);
+      if (parent.isG())
+        {
+         TNode prev = cursor.prev();
+         if (prev)
+           {
+             // i try to delete the preceding element
+             gdelete_prev();
+
+             if ((parent.first() == cursor) && parent.isG() && parent.hasId())
+               rgreplace_futher();
+
+           }
+         else // no previous node is present
+           {
+             // if here, we are in a gruop whose only child is the cursor.
+             
+             if (!parent.hasId())
+               {
+                 // the parent is a phantom group
+                 assert(parent.parent());
+                 if (!parent.parent().is("math"))
+                   {
+                     TNode gfuther = parent.parent();
+
+                     // if the grand futher is a group with Id, it should be removed, 
+                     // but i don't know if it will never occur...
+                     if (gfuther.isG() && gfuther.hasId())
+                       {
+                         cursor.remove();
+                         parent.replace(cursor);
+
+                         // re-start the process
+                         do_gdelete();
+                       }
+                     else if (gfuther.isC())
+                       {
+                         // the grand futher is a control element: since the parent is a phantom group, 
+                         // the TML tree should be in a inconsistent state (once removed the parent).
+
+                         // being here means that there is a frame in the stack
+                         assert(!frames.empty());
+                         cout << "do_gdelete: i have to remove a phantom group whuch is a child of a MACRO" << endl;
+                         Frame& frame = frames.top();
+                         if (frame.entry.leftOpen && frame.entry.rightOpen)
+                           {
+                             // in this case, the cursor is in the second and last child 
+                             // of the MACRO. We can assert that the grand futher has two 
+                             // children. which are both phantom group
+                             cout << "do_gdelete: the MACRO is leftOpen and rigthOpen" << endl;
+                             assert(gfuther.size() == 2);
+                             assert((gfuther.last() == parent) && (gfuther.first().isG() && !gfuther.first().hasId()));
+                             assert(frame.pos == 0);
+                           
+                             TNode ggfuther = gfuther.parent();
+                             assert(ggfuther);
+                             cursor.remove();
+                             parent.remove();
+                             // i have to replace the gfuther with the elements of its first child
+                             gfuther.replace(gfuther.first().first(), TNode());
+                             cout << "do_gdelete: i have removed the control element, and replaced it with its first child" << endl;
+                             ggfuther.append(cursor);
+                             cout << "do_gdelete: cursor appended to the grand grand futher" << endl;
+
+                             // now we have the situation preceding the insertion of the MACRO leftOpen and rightOpen
+                             // this MACRO no longer exists.
+                             frames.pop();
+                           }
+                         else if (frame.entry.rightOpen)
+                           {
+                             // the user has inserted a MACRO rightOpen. Since the cursor is the 
+                             // only child of the MACRO, the user want to remove it. 
+                             // We can assert that cursor's parent is the only child of the MACRO
+                             cout << "do_gdelete: the MACRO is rightOpen only" << endl;
+                             assert(gfuther.size() == 1);
+                             assert(frame.pos == 0); // i think this assert has no sense
+                           
+                             cursor.remove();
+                             parent.remove();
+                             gfuther.replace(cursor);
+
+                             // now we have the situation preceding the MACRO rightOpen, so i have to pop the frame
+                             frames.pop();
+                           }
+                         else if (frame.entry.leftOpen)
+                           {
+                             // it' s an unpredicted situation
+                             cout << "it's a bad situation, maybe handlable, but unpredicted" << endl;
+                           }
+                         else if (!frame.entry.pattern.empty())
+                           {
+                             // the MACRO (the cursor's grand futher) accepts arguments.
+                             // we have to control if the cursor's uncle does exist.
+
+                             if (parent.prev())
+                               {
+                                 // in this case, we can assert that frame in the stack has 
+                                 // pos greater than 0
+                                 assert(frame.pos > 0);
+                               
+                                 // cursor's uncle does exist. we have to control 
+                                 // its nature (is it a phantom group?)
+                                 TNode uncle = parent.prev();
+                                 if (uncle.isG() && !uncle.hasId())
+                                   {
+                                     // 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);
+                                   }
+                                 else
+                                   {
+                                     // the uncle was a NOT delimited argument. So i try to 
+                                     // remove it
+                                     cursor.remove();
+                                     parent.replace(cursor);
+                                 
+                                     parent = cursor.parent(); // i update the parent (it should be the MACRO)
+                                     assert(parent.isC());
+                                 
+                                     gdelete_prev();
+
+                                   }
+                               }
+                             else
+                               {
+                                 // cursor's parent is the only child of the MACRO, which accepts arguments
+                                 // i can assert that frame.pos == 0.
+                                 // In this case i can replace the MACRO with the cursor
+                                 assert(frame.pos == 0);
+
+                                 cursor.remove();
+                                 parent.remove();
+                                 gfuther.replace(cursor);
+
+                                 frames.pop();
+                               }
+                           
+                           }
+                       }
+                     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
+                   {
+                     // nothing to do...i think
+                     assert(frames.empty());
+                   }
+               }
+             else
+               { 
+                 // the parent is a group with id and has no elements other than cursor
+                 // so we replace it with the cursor.
+                 rgreplace_futher();
+
+                 // i have to re-start the process, because it' a graphical delete
+                 do_gdelete();
+               }
+           }
+       }
+      else if (parent.isC())
+        {
+         // being here means that there is an open frame for the control element
+         // and this element is closed at either side (no leftOpen no rightOpen)
+         // and the MACRO was waiting for a non delimited argument, so 
+         // we can assert that frame.entry.pattern.size() >= 1
+         assert(!frames.empty());
+         Frame& frame = frames.top();
+
+         assert(frame.entry.pattern.size() >= 1);
+
+         cout << "do_gdelete: frames.top().pos = " << frames.top().pos << endl;
+
+         TNode prev = cursor.prev();
+
+         if (!prev)
+           {
+             // in this case we can replace the MACRO with the cursor 
+             // and pop the stack and we can assert that frame.pos == 0
+             assert(frame.pos == 0);
+             cursor.remove(); // it should not be necessary, but i'm not shure
+             parent.replace(cursor);
+             frames.pop();
+           }
+         else
+           {
+             // in this case the cursor has a preceding element 
+             // and there are differnt things based on the nature 
+             // of the prev: if it's a phantom group do something,
+             // else do something else
+             if (prev.isG() && !prev.hasId())
+               {
+                 // in this case we have to append the cursor 
+                 // 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);
+                 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
+               {
+                 // the prev is an non delimited argument, so we try to 
+                 // remove it.
+                 gdelete_prev();
+               }
+           }
+       }
+      else if (parent.is("sp") || parent.is("sb"))
+        {
+         // being here means that a prev MUST exist 
+         // and that there is only an element preceding the cursor.
+         // 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))
+           {
+             prev.remove();
+             parent.replace(cursor);
+
+             // now, cursor should be the only parent's child
+             assert(cursor.parent().size() == 1);
+
+             if (cursor.parent().isG() && cursor.parent().hasId()) rgreplace_futher();
+           }
+         else
+           {
+             assert(prev.hasId());
+             parent.replace(prev);
+             prev.parent().append(cursor);
+             // now prev should have a preceding element
+             assert(cursor.parent().size() > 1);
+           } 
+       }
+      else
+        {
+         // not handled: no control for tables, ...
+       }
+    }
+  else
+    {
+      // the cursor has no parent!!!
+      // do nothing?
+      // emit an error? and if we want to emit an error, in which way?
+    }
+
+} // end of method
+
 void
 TPushParser::process(const TToken& token)
 {
@@ -498,6 +1023,7 @@ TPushParser::process(const TToken& token)
     case TToken::ACTIVE: do_active(token.value); break;
     case TToken::COMMENT: do_comment(); break;
     case TToken::CONTROL: do_control(token.value); break;
+    case TToken::GDELETE: do_gdelete(); break;
     }
 }
 
@@ -505,124 +1031,168 @@ void
 TPushParser::push(const TToken& token)
 {
   cerr << "TPushParser::push " << token.value << " (cat: " << token.category << ")" << endl;
-  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)
+
+  if (token.category == TToken::GDELETE)
+    {
+      cout << "push: i have to process a token with category member = GDELETE" << endl;
+      process(token);
+    }
+  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 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());
-       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;
     }
 
-  if (listener) listener->callback(doc);
+  if (factory) factory->documentModified(doc);
+
+  if (frames.empty()) cout << "stack vuoto" << endl;
+  else cout << "stack non vuoto" << endl;
 }
 
 void
@@ -661,8 +1231,8 @@ TPushParser::advance(const TNode& node)
 }
 
 void
-TPushParser::setCursor(const std::string& c)
+TPushParser::setCursorHint(const std::string& c)
 {
   cursor["val"] = c;
-  if (listener) listener->callback(doc);
+  if (factory) factory->documentModified(doc);
 }