+#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();
}
}
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
{
{
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());
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);
}
}
+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)
{
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;
}
}
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
}
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);
}