assert(table);
advance(row);
}
- else if (parent && parent.isG() && !parent.hasId() && parent.parent())
+ else if (parent && parent.isG() && !parent.hasId() && parent.parent() && !parent.parent().is("math"))
{
// closing brace for a right-open macro (like \over)
// It's not sure that we want to exit from a phantom group with a
{
// In this case, there is a redundant '}', so I think we can ignore it and
// emit an error
- logger.error("There so no corresponding'{'");
+ logger.warning("There is so no corresponding'{'");
//assert(0);
}
}
// I don't think so, if user types
// $12+{a-b\over2a+b$
// because the group is not closed with a '}'
- logger.error("ERROR: math shift");
+ logger.error("parser: math shift");
}
}
else
{
// is it an error?
- logger.error("you have to type one identifier before the ''");
+ logger.error("parser: you have to type one identifier before the ''");
}
}
else
do_apostrophe();
break;
default:
- cout << "TPushParser::do_other " << s << endl;
- cout << "DOCUMENT: " << static_cast<GdomeNode*>(cursor.element().get_ownerDocument()) << endl;
+ /*cout << "TPushParser::do_other " << s << endl;
+ cout << "DOCUMENT: " << static_cast<GdomeNode*>(cursor.element().get_ownerDocument()) << endl;*/
TNode elem = doc.createT("o", s, nextId++);
cursor.replace(elem);
advance(elem);
TNode m = doc.createC(name, nextId++);
cursor.replace(m);
- logger.debug("do_control: i have pushed a frame in the stack. Here is the pattern of the associated MACRO");
- for (unsigned i = 0; i < entry.pattern.size(); i++)
- logger.debug(entry.pattern[i].value);
-
if (entry.leftOpen && entry.rightOpen)
{
assert(entry.pattern.empty());
else
{
// error, but we could handle this very easily
- logger.error("error, but we could handle this easily");
+ logger.error(" parser:but we could handle this easily");
}
}
else advance(m);
break;
case TDictionary::UNDEFINED:
{
- logger.error("ERROR: using undefined macro ` + name '");
+ logger.error("parser: using undefined macro " + name);
TNode m = doc.createC(name, nextId++);
cursor.replace(m);
advance(m);
assert(cursor.parent());
TNode prev = cursor.prev();
assert(prev.is("i") || prev.is("o") || prev.is("n"));
-
- logger.debug("gdelete_prev_token: start");
// 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"))
{
- logger.debug("gdelete_prev_token: i have removed an element");
cursor.remove();
prev.replace(cursor);
assert(frame.pos > 0);
frame.pos--;
- logger.debug("gdelete_prev_token: it was a MACRO's child so i have decremented the member pos of the associated frame");
}
}
else
prev.element().setAttribute(DOM::GdomeString("val"), DOM::GdomeString(ucs4val));
}
- logger.debug("gdelete_prev_token: bye...");
}
void
TPushParser::gdelete_prev_script()
{
- logger.debug("gdelete_prev_script: start...");
- // this method delete a sp or an sb preceding the cursor
+ // this method delete an sp or an sb preceding the cursor
assert(cursor.prev());
assert(cursor.parent());
TNode prev = cursor.prev();
assert(prev.is("sp") || prev.is("sb"));
cursor.remove();
prev.append(cursor);
- // i can invoke the gdelet_prev, because a sp (sb) MUST have two child
+ // i can invoke the gdelet_prev, because a sp (sb) MUST have two children
gdelete_prev();
- logger.debug("gdelete_prev_script: bye...");
}
void
TPushParser::gdelete_prev_group()
{
- logger.debug("gdelete_prev_group: start");
assert(cursor.prev() && cursor.prev().isG());
TNode prev = cursor.prev();
cursor.remove();
prev.append(cursor);
- logger.debug("gdelete_prev_group: i have to call the do_gdelete()");
- // a group can have no child, so the gdelete_prev is not appropriate
+ // a group may have no children, so the gdelete_prev is not appropriate
// so this method is not equivalent to the one above
do_gdelete();
-
- logger.debug("gdelete_prev_group: do_gdelete terminated");
- logger.debug("gdelete_prev_group: bye...");
}
void
TPushParser::gdelete_prev_macro()
{
- logger.debug("gdelete_prev_macro: start");
assert(cursor.parent());
assert(cursor.prev());
TNode prev = cursor.prev();
if (!entry.defined())
{
- // I assume tha the user want to completely delete the undefined macro
- logger.debug("gdelete_prev_macro: i have to remove an undefined macro");
+ // We can assume tha the user want to completely delete the undefined macro
cursor.remove();
prev.replace(cursor);
}
else
- {
- logger.debug("gdelete_prev_macro: i have to start to delete a defined MACRO");
-
- // i start to remove a MACRO. Different actions must be taken, based on the nature
- // of the MACRO. In some case, we can't remove the MACRO immediately, in other
- // case it's correct. In the first case, we have to update the stack, pushing
- // a frame in the stack with a correct value of pos, in the
- // second one, we do not have to push a frame in the stack
+ {
+ // we start to remove a MACRO. Different actions must be taken, based on the nature
+ // of the MACRO. In some cases, we can't remove the MACRO immediately, in other
+ // cases it's correct. In the first set of cases, we have to update the stack, pushing
+ // a frame in it with a correct value of pos, in the
+ // second one, we must not push a frame in the stack
if (entry.rightOpen)
{
- // if the control element is ightOpen, the cursor should be placed after
- // the last child of the control element's last child, and try to remove something
+ // In this fragment of code we also handle the leftOpen && rightOpen MACRO.
+ // if the control element is rightOpen, the cursor should be placed after
+ // the last child of the control element's last child, and than, we try to remove something.
// A frame MUST be pushed in the stack, because we dont' know if the following actions
- // will remove the MACRO.
- logger.debug("gdelte_prev_macro: i have to delete a control rightOpen, so i push an element in the stack");
-
+ // will completely remove the MACRO.
frames.push(Frame(entry));
- logger.debug("gdelete_prev_macro: i control the values of the pushed frame");
- logger.debug("gdelete_prev_macro: rightOpen");
- cout << frames.top().entry.rightOpen << endl;
- logger.debug("gdelete_prev_macro: leftOpen");
- cout << frames.top().entry.leftOpen << endl;
- logger.debug("gdelete_prev_macro: pattern.empty()");
- cout << frames.top().entry.pattern.empty() << endl;
-
// Since the MACRO is rightOpen, the last child of the MACRO must be a phantom group
assert(prev.last().isG() && !prev.last().hasId());
cursor.remove();
prev.last().append(cursor);
- // the gdelete_prev is not appropriate, because the last child of the MACRO could have no child
- logger.debug("gdelete_prev_macro: i have to call do_gdelete_phantom_group");
+ // the gdelete_prev is not appropriate, because the last child of the MACRO may have no children
do_gdelete_phantom_group();
-
- if (!frames.empty())
- {
- logger.debug("gdelete_prev_macro: after the do_gdelete_phantom_group, the frame in the stack has to be rightOpen");
- cout << frames.top().entry.rightOpen << endl;
- logger.debug("gdelte_prev_macro: after the do_gdelete_phantom_group, the top element's pattern MUST be empty");
- cout << frames.top().entry.pattern.empty() << endl;
- }
- else
- logger.debug("gdelete_prev_macro: the do_gdelete_phantom_group has removed all frames in the stack");
-
}
else if (entry.leftOpen)
{
- logger.debug("gdelete_prev_macro: i have to delete a control element with leftOpen");
// the leftOpen MACRO MUST have one and only one child, which MUST be a phantom group
// In this case, we do not have to push a frame in the stack, because we remove the
// MACRO immediately, substituting it with the content of the phantom group.
- // At the moment, i don't remove the last child of the phantom group, but
+ // At the moment, we don't remove the last child of the phantom group, but
// i don't know if it's the correct behavior of the graphical deleting.
- // To delete it, just remove the comment of the last instruction
+ // To delete it, just remove the comment of the last instruction of this block
+ // of code.
assert(prev.first());
assert(prev.first().isG());
assert(prev.first() == prev.last());
}
else if (!entry.pattern.empty())
{
- // we have to start removing a MACRO which accepts arguments.
- // a MACRO without child does not exist
-
- logger.debug("gdelete_prev_macro: i have to remove a MACRO with argument");
+ // we have to start to remove a MACRO which accepts arguments.
+ // If the MACRO accepts arguments, the MACRO has one or more children
assert(prev.size() >= 1);
- // Differnt actions should be taken, based on the nature of the last child
+ // Differnt actions must be taken, based on the nature of the last child
// of the MACRO. We have to distinguish the case in which it's a delimited argument
// frome the one in which it's a not delimited argument.
if (prev.last().isG() && !prev.last().hasId())
{
// the last argument of the MACRO is a delimited argumet. We ideally remove
// the sequence of delimiters
- logger.debug("gdelete_prev_macro: the last argument of the MACRO is delimited");
cursor.remove();
prev.last().append(cursor);
- // i have to push a frame with a correct value of pos
+ // we have to push a frame with a correct value of pos
assert(entry.previousParam(entry.pattern.size()) != entry.pattern.size());
+
unsigned sequence_length = entry.pattern.size() - entry.previousParam(entry.pattern.size()) - 1;
unsigned p = entry.pattern.size() - sequence_length - 1;
+ // now, p is the correct value of pos, and we can push the frame.
frames.push(Frame(entry, p));
- logger.debug("gdelete_prev_macro: i have inserted a frame, it's pos is: ");
- cout << frames.top().pos << endl;
-
}
else
{
// in this case, the last child of the MACRO is not a delimited argument, so we try
// to remove it, but we have to take differnt actions if the MACRO is a table with rows or not.
- logger.debug("gdelete_prev_macro: the last argumet of the MACRO is not delimited, so itry to remove it");
cursor.remove();
if (entry.table == 1 && prev.last().is("row"))
{
// in this case the cursor should be appended to the group associated to
// the last cell of the last row of the table
- logger.debug("gdelete_prev_macro: but it is a table with rows, so i append the cursor at the end of the table");
assert(prev.last().last().is("cell") && prev.last().last().first().isG());
prev.last().last().first().append(cursor);
}
else
{
- logger.debug("gdelete_prev_macro: i append the cursor to the MACRO");
prev.append(cursor);
}
+ // we push a frame in the stack with a correct value of member pos.
+ // This correct value is the size of the pattern, because we have to START to delete
+ // a MACRO. It means that all of the MACRO's arguments have been inserted.
frames.push(Frame(entry, entry.pattern.size()));
- logger.debug("gdelete_prev_macro: i've pushed a frame in the stack, and it's value of pos is ");
- cout << frames.top().pos << endl;
-
if (cursor.prev())
{
- logger.debug("gdelete_prev_macro: i invoke the gdelete_prev");
+ // in this case we try to remove the last child of the MACRO.
gdelete_prev();
}
else
{
- logger.debug("gdelete_prev_macro: i invoke the do_gdelete");
+ // this block of code will never be executed, because the MACRO accepts arguments,
+ // so a MACRO's child MUST exist. But, we can handle this case, emitting a warning
+ logger.warning("Parser: the TML tree is in a strange state, but a good state will be generated");
do_gdelete();
}
} // end of the else of the if (prev.last().isG() && !prev.last().hasId())
} // end of if (!entry.pattern.empty())
else
{
- // if we are here, the MACRO preceding the cursor, is not rightOpen, nor leftOpen,
- // and has no pattern. It means that it has no childs.
+ // if we are here, the MACRO preceding the cursor, is !(rightOpen ||leftOpen),
+ // and has no pattern. It means that it has no children.
// We can replace it with the cursor
- logger.debug("gdelete_prev_macro: the MACRO is empty, i remove it");
assert(prev.size() == 0);
cursor.remove();
prev.replace(cursor);
}
} // end of defined MACRO
- logger.debug("gdelete_prev_macro: bye...");
}
void
{
// if in this function, the prev of cursor does exist, also the parent and we want a graphical deleting.
- logger.debug("gdelete_prev: start...");
-
assert(cursor.prev());
assert(cursor.parent());
}
else if (prev.isC())
{
- // here we also treat the case in which the MACRO is a table
+ // here, we also treat the case in which the MACRO is a table
gdelete_prev_macro();
}
else
// not handled. Future cases...
}
- logger.debug("gdelete_prev: bye...");
} // end of method
void
-TPushParser::rgreplace_futher(void)
+TPushParser::rgreplace_father(void)
{
- // this function MUST only be invoked, when the cursor
+ // this method 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
+ // replaces 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
+ // r stands for recursive, g stands for graphical.
assert(cursor.parent());
assert(cursor.parent().isG() && cursor.parent().hasId());
if (parent.isC())
{
// in this case we have removed a MACRO's child.
+ // So, we have to update the member pos of the frame in the stack
// I can assert that this MACRO accepts arguments.
assert(!frames.empty());
Frame& frame = frames.top();
void
TPushParser::do_gdelete_script()
{
- // If we are here, the cursor is child of a script and
- // means that a prev MUST exist and that there is only an
+ // If we are here, the cursor is child of a script (sp or sb) and
+ // this means that a prev MUST exist and that there is one and only one
// element preceding the cursor. The sp's (or sb's) parent
// MUST NOT be a MACRO.
// The element preceding the cursor is the base of the script.
- logger.debug("do_gdelete_script: start...");
-
assert(cursor.parent() && (cursor.parent().isSp() || cursor.parent().isSb()));
TNode parent = cursor.parent();
cursor.remove();
if (prev.isG() /*&& !prev.hasId()*/ && (prev.size() == 0))
{
- // in this case, the script's base is a group with no elements, so i think
- // we have to remove the entire MACRO, replacing it with the cursor
+ // in this case, the script's base is a group with no elements, so
+ // we have to remove the entire MACRO, replacing it with the cursor.
+ // This situation occurs when the user type something like this
+ // $....{}^
+ // or this
+ // $^
+ // or this
+ // $...{^
prev.remove();
parent.replace(cursor);
// if the new parent is a group with Id and the cursor is the only
- // element of this group, we have to remove it. This controls are made
- // in the method rgreplace_futher().
- if (cursor.parent().isG() && cursor.parent().hasId()) rgreplace_futher();
+ // element of this group, we have to remove the group. This controls are made
+ // in the method rgreplace_father().
+ if (cursor.parent().isG() && cursor.parent().hasId()) rgreplace_father();
}
else
{
// in this case, the prev has to replace the script,
- // and the curosor has to be placed after the prev.
+ // and the cursor has to be placed after the prev.
assert(prev.hasId());
parent.replace(prev);
prev.parent().append(cursor);
- // now prev should have a preceding element
+ // now prev have a preceding element
assert(cursor.parent().size() > 1);
}
- logger.debug("do_gdelete_script: bye...");
-
} // end of method do_gdelet_script
void
// If we are here, the cursor is a child of a MACRO and this 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
+ // and the MACRO is waiting for a not delimited argument, so
// we can assert that frame.entry.pattern.size() >= 1
assert(cursor.parent() && cursor.parent().isC());
TNode parent = cursor.parent();
// we have to take different actions, based on if a preceding element exists
// or not
- logger.debug("do_gdelete_macro:");
TNode prev = cursor.prev();
if (!prev)
{
// in this case, a prev does not exist, so the actions of deleting means
// that we have to remove the MACRO. So we have to pop the stack.
// Being here also means that the MACRO is waiting for the first argument
- // (which is not delimited)
+ // (which is not delimited), but we don't mind about it.
assert(frame.pos == 0);
parent.replace(cursor);
frames.pop();
// if the new parent is a group with Id, and has no elements other than the
- // cursor, we could remove it...but i'm not sure
+ // cursor, we can remove it, because it' a graphical deleting
if (cursor.parent() && cursor.parent().isG() && cursor.parent().hasId())
- rgreplace_futher();
+ rgreplace_father();
else if (cursor.parent().isC())
{
// We have assumed that a MACRO cannot be a MACRO's child.
// At the moment, this assumption is valid, but in a future
- // it could be false.
+ // it might be false.
assert(!frames.empty());
Frame& frame = frames.top();
assert(frame.pos > 0);
}
else
{
- // we have to control if prev is a delimited argument or not.
+ // a prev does exist, we have to control if it's a delimited argument or not.
if (prev.isG() && !prev.hasId())
{
// in this case, prev is a delimited argument, so we have
// to ideally remove the sequence of delimiters
Frame& frame = frames.top();
assert(frame.pos > 1);
- logger.debug("do_gdelete_macro: the pos of the frame is: ");
- cout << frame.pos << endl;
- logger.debug("do_gdelete_macro: the pattern size of the entry is");
- cout << frame.entry.pattern.size() << endl;
- logger.debug("do_gdelete_macro: the prev param is at");
- cout << frame.entry.previousParam(frame.pos) << endl;
cursor.remove();
prev.append(cursor);
assert(frame.entry.previousParam(frame.pos) != frame.entry.pattern.size());
+
+ // these 3 lines of code update the member pos.
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 not a delimited argument, so we have to try to remove it.
- // I told "try" because the prev can be a group or something that
+ // We "try", because the prev might be a something that
// a simple delete cannot remove completely
gdelete_prev();
}
}
- logger.debug("do_gdelete_macro: bye...");
}
void
TNode prev = cursor.prev();
if (prev)
{
- // the cursor has a preceding element, so we try to remoev it
+ // the cursor has a preceding element, so we try to remove it
gdelete_prev();
// We control if the group has to be removed, because the cursor
- // could be the only element of the group.
+ // might be the only element of the group.
if ((parent.first() == cursor) && parent.isG() && parent.hasId())
- rgreplace_futher();
+ rgreplace_father();
}
else
{
// the cursor has no preceding elements, so we have to remove the
// group.
- rgreplace_futher();
+ rgreplace_father();
- // i have to re-start the process, because it' a graphical delete
+ // we have to re-start the process, because it' a graphical delete
do_gdelete();
}
- logger.debug("do_gdelete_groupId: bye...");
-
} // end of method do_gdelete_groupId()
void
{
// if we are here, the cursor MUST be a child of a
// phantom group.
- logger.debug("do_gdelete_phantom_group: start");
assert(cursor.parent() && cursor.parent().isG() && !cursor.parent().hasId());
TNode parent = cursor.parent();
if (prev)
{
// the cursor has a preceding element, so we try to remove it
- logger.debug("do_gdelete_phantom_group: i have to call the gdelete_prev()");
gdelete_prev();
- logger.debug("do_gdelete_phantom_group: gdelete_prev terminated");
if (parent.size() == 1 && parent.parent().isSp())
{
- logger.debug("do_gdelete_phantom_group: i have to remove a phantom group which is a child of a sp");
// in this case the gdelete_prev has removed the only element preceding the cursor.
- // If the phantom group is a sp's child, it means that the user has removed all \' in the
- // phantom group. I think, we can remove the phamtom group and the sp element.
+ // If the phantom group is an sp's child, it means that the user has removed all \' in the
+ // phantom group.
+ // We can remove the phamtom group and the sp element. But we also can only remove the
+ // phantom group, giving to the user the possibility of inserting an exponent.
+ // At the moment, we remove the sp element (and the phantom group), because it may be the correct
+ // behavior of a graphical deleting.
cursor.remove();
parent.replace(cursor);
- // now we have a sp element with two children: the first child (we don't know nothing about it)
+ // now we have an sp element with two children: the first child (we don't know nothing about it)
// and the cursror.
assert(cursor.parent().size() == 2);
- // to delete the script we can invoke the do_gdelete_script(), which will do all controls we need
+ // to delete the script we can invoke the do_gdelete_script(), which will do all controls we need.
+ // To give the possibility of insering an exponent
do_gdelete_script();
}
else if (parent.parent().isSp())
{
// in this case we have to place the cursor after the sp element
- logger.debug("do_gdelete_phantom_group: the sequence of \' is not terminated, so i place the cursor after the sp element");
cursor.remove();
assert(parent.parent().parent());
parent.parent().parent().append(cursor);
{
// in this case the cursor is the only element of the phantom group,
// so we have to remove it. But, a phantom group has a special role,
- // so we have to control the grand futher of the cursor.
- TNode gfuther = parent.parent();
- if (!gfuther)
+ // so we have to control the grand father of the cursor.
+ TNode gfather = parent.parent();
+ if (!gfather)
{
// If here, the TML tree is in an inconsistent state
logger.error("do_gdelete_phantom: TML tree in a inconsistent state");
}
- else if (gfuther.isC())
+ else if (gfather.isC())
{
// in this case the phantom group is child of a MACRO.
// We have to control the nature of this MACRO.
- logger.debug("do_gdelete_phantom_group: i have to remove a phantom group which is a child of a MACRO");
assert(!frames.empty());
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
- logger.debug("do_gdelete_phantom_group: the MACRO is leftOpen and rigthOpen");
- assert(gfuther.size() == 2);
- assert((gfuther.last() == parent) && (gfuther.first().isG() && !gfuther.first().hasId()));
+ // in this case, the cursor'parent is in the second and last child
+ // of the MACRO. We can assert that the grand father has two
+ // children, which are both phantom group
+ assert(gfather.size() == 2);
+ assert((gfather.last() == parent) && (gfather.first().isG() && !gfather.first().hasId()));
assert(frame.pos == 0);
- TNode ggfuther = gfuther.parent();
- assert(ggfuther);
+ TNode ggfather = gfather.parent();
+ assert(ggfather);
cursor.remove();
parent.remove();
- // i have to replace the gfuther with the elements of its first child
- gfuther.replace(gfuther.first().first(), TNode());
- logger.debug("do_gdelete_phantom_group: i have removed the control element, and replaced it with its first child");
- ggfuther.append(cursor);
- logger.debug("do_gdelete_phantom_group: cursor appended to the grand grand futher");
- // now we have the situation preceding the insertion of the MACRO leftOpen and rightOpen
+ // i have to replace the gfather with the elements of its first child
+ gfather.replace(gfather.first().first(), TNode());
+ ggfather.append(cursor);
+ // now we have the situation preceding the insertion of the leftOpen and rightOpen MACRO.
// 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.
+ // the user has inserted a rightOpen MACRO, and now, this MACRO has no children (excluding the
+ // phantom group), so we remove the MACRO.
// We can assert that cursor's parent is the only child of the MACRO
- logger.debug("do_gdelete_phantom_group: the MACRO is rightOpen only");
- assert(gfuther.size() == 1);
+ assert(gfather.size() == 1);
assert(frame.pos == 0);
cursor.remove();
parent.remove();
- gfuther.replace(cursor);
+ gfather.replace(cursor);
- // now we have the situation preceding the MACRO rightOpen, so i have to pop the frame
+ // now we have the situation preceding the rightOpen MACRO, so we have to pop the frame
frames.pop();
}
else if (frame.entry.leftOpen)
{
- // i think this situation will never occur
- // but it can be recovered in some way
+ // this situation will never occur.
logger.error("the parser has generated a wrong TML tree");
}
else if (!frame.entry.pattern.empty())
// the cursor is, rappresents a delimited argument
// We have to control if the cursor's parent has a preceding element,
// or not.
- logger.debug("do_gdelete_phantom_group: the MACRO accepts arguments");
- logger.debug("do_gdelete_phantom_group: entry pattern has size:");
- cout << frame.entry.pattern.size() << endl;
TNode uncle = parent.prev();
if (!uncle)
{
assert(frame.pos == 0);
cursor.remove();
parent.remove();
- gfuther.replace(cursor);
+ gfather.replace(cursor);
frames.pop();
}
else
if (uncle.isG() && !uncle.hasId())
{
// the uncle is a delimited argument. So we have to ideally
- // remove the sequrnce of delimiters.
+ // remove the sequence of delimiters.
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());
parent = cursor.parent(); // i update the parent (it should be the MACRO)
assert(parent.isC());
- // now i try to remove the uncle (now it' the preceding element)
+ // now we try to remove the uncle (now it' the preceding element)
gdelete_prev();
}
} // this is the else's end, that handles the case in which an uncle exists
else
{
// the entry has no arguments, is not rightOpen and is not leftOpen.
- logger.warning("do_gdelete_phantom_group: TML tree in a strange state");
- if (gfuther.size() == 1)
+ logger.warning("parser: TML tree in a strange state, but we try to recover from it");
+ if (gfather.size() == 1)
{
cursor.remove();
parent.remove();
- gfuther.replace(cursor);
+ gfather.replace(cursor);
}
else
{
- logger.debug("do_gdelete_phantom_group: TML tree in a very strange state");
+ logger.warning("parser: TML tree in a very strange state, but we try to recover from it");
cursor.remove();
- gfuther.replace(cursor);
+ gfather.replace(cursor);
}
}
- } // end of if (gfuther.isC())
- else if (gfuther.is("cell"))
+ } // end of if (gfather.isC())
+ else if (gfather.is("cell"))
{
- // we have to handle the case where cursor'grand futher is a cell element.
- // The tables are control sequece, so there is a frame in the stack
+ // A table is a control sequence, so there is a frame in the stack
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();
+ // a cell MUST be a row's child, which in turn is a table's child
+ assert(gfather.parent() && gfather.parent().is("row") && gfather.parent().parent());
+ TNode row = gfather.parent();
// in this case the cell has no element, so the user wants to delete this cell.
- TNode prev_cell = gfuther.prev();
+ TNode prev_cell = gfather.prev();
cursor.remove();
parent.remove();
- gfuther.remove();
+ gfather.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.
+ // in this case, the cell is the only cell in the row.
+ // So, we 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
+ // so we have to delete the entire table
assert(table.parent());
TNode parent_table = table.parent();
table.remove();
}
else
{
- // there are other rows (one at least)
+ // there are other rows (one or more)
assert(prev_row.is("row"));
assert(prev_row.last());
TNode last_cell = prev_row.last();
assert(prev_cell.first().isG() && !prev_cell.first().hasId());
prev_cell.first().append(cursor);
}
- } // end of if (gfuther.is("cell"))
- else if (gfuther.isSp())
+ } // end of if (gfather.is("cell"))
+ else if (gfather.isSp())
{
- // in this case, the user pushed a \'. So this phantom group
+ // in this case, the user typed a \'. So this phantom group
// contained a sequence of \'.
// Maybe in this part will never be used, because, if we delete last \' in the
// phantom group, we remove the phantom group also
//
- // In any case, if we are here we have two choice:
- // delete the phantom group;
- // delete the superscript.
+ // In any case, if we are here we have two possibilities:
+ // we can delete the phantom group;
+ // we can delete the superscript.
+ // At the moment we implement the first solution. To implement the second one, just remove
+ // delete the line code after the logger.warning and remove comment from the remaining lines
+ logger.warning("parser: TML tree in a strange state, we try to recover from it");
+ parent.replace(cursor);
+
+ //cursor.remove();
+ //parent.remove();
+ //gfather.replace(cursor);
+ }
+ else if (gfather.is("math"))
+ {
+ // in this case we ignore the user's will of deleting
+ // but we can decide to remove the math mode.
+ logger.info("Parser: nothing to delete");
}
else
{
- // cursor' grand futher is undefined
- logger.error("do_gdelete_phantom_group: TML tree in a unknown state");
+ // cursor' grand father is undefined
+ logger.error("parser: TML tree is in a unknown state");
}
} // end of the else of the if (prev)
- if (!frames.empty())
- {
- logger.debug("do_gdelete_phantom_group: the stack is not empty");
- logger.debug("do_gdelte_phanto_group: is the top element rightOpen?");
- cout << frames.top().entry.rightOpen << endl;
- logger.debug("do_gdelte_phanto_group: is the top element'pattern empty?");
- cout << frames.top().entry.pattern.empty() << endl;
- }
- logger.debug("do_gdelete_phantom_group: bye...");
}
void
TPushParser::do_gdelete()
{
- logger.debug("do_gdelete: start");
// we have to handle the case in wich the cursor has a parent or not
if (!cursor.parent())
{
TNode parent = cursor.parent();
if (parent.is("math"))
{
- // we ca do two thing...remove the math mode (it implies controlling the display attribute), do nothing
+ // we ca do two thing...we can remove the math mode (it implies controlling the display attribute), we can do nothing
// At the moment, the user's will of deleting is simply ignored
logger.error("TML tree not well structured");
}
else if (parent.isG())
{
// the cursor's parent is a group. We have to control if it's a phantom group or not
- logger.debug("do_gdelete: the cursor's parent is a group");
if (parent.hasId())
{
- logger.debug("do_gdelete: which has Id");
do_gdelete_groupId();
}
else
{
- logger.debug("do_gdelete: which is a phantom group");
do_gdelete_phantom_group();
}
} // end of parent is group
else if (parent.isC())
{
- cout << "the cursor's parent is a MACRO" << endl;
do_gdelete_macro();
} // end of parent is a MACRO
else if (parent.isSp() || parent.isSb())
{
- cout << "the cursor's parent is a script" << endl;
do_gdelete_script();
} // end of parent is sp or sb
} // end of the else which consider the case in which parent exists
- if (!cursor.parent())
- logger.debug("do_gdelete: the cursro has no parent -> paolo is stupid");
-
- if (!frames.empty())
- {
- logger.debug("do_gdelete: the stack is not empty");
- logger.debug("do_gdelete: is the top element rightOpen?");
- cout << frames.top().entry.rightOpen << endl;
- logger.debug("do_gdelete: is the top element'pattern empty");
- cout << frames.top().entry.pattern.empty() << endl;
- }
- logger.debug("do_gdelete: bye...");
-
} // end of method do_gdelete
-/*
-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 which is a child of a MACRO" << endl;
- Frame& frame = frames.top();
- cout << frame.entry.leftOpen << frame.entry.rightOpen << endl;
- 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
- cout << "this is the assert that fails" << endl;
- 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)
{
void
TPushParser::push(const TToken& token)
{
- logger.debug("TPushParser::push " + token.value + " (cat: ");
- cout << token.category << ")" << endl;
-
if (token.category == TToken::GDELETE)
{
- logger.debug("push: i have to process a token with category member = GDELETE");
process(token);
}
else
{
- logger.debug("push: i get the cursor's parent");
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.isG() && !parent.hasId() && parent.parent().isC())
{
// There must be an open frame, for the grand-parent is a control sequence
- logger.debug("push: cursor'parent is a phantom group, and this group has a MACRO as parent");
- logger.debug("push: i assert that !frames.empty()");
assert(!frames.empty());
- logger.debug("push: this assert is OK");
- logger.debug("push: now i take the top element of the stack");
Frame& frame = frames.top();
- logger.debug("push: now i've got the top element");
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
- logger.debug("push: the frame.entry accepts arguments");
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 (frame.pos == frame.entry.pattern.size())
{
// This token has completed the entry
- frames.pop();
- advance(parent.parent());
+ advance(parent);
}
else if (frame.entry.paramDelimited(frame.pos))
{
{
// 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.
+ // sequence, but now 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;
+ // At the moment, we implement the second possibily
+ logger.error("parser: it's not the correct delimiter...you have to type " + frame.entry.pattern[frame.pos + 1].value);
}
else
{
// entry. What happens if we actually are in the left side?
// This could happen only when re-editing an entered expression
// We'll see...
- logger.debug("push: the frame.entry has no arguments, so i assert that i's rightOpne");
assert(frame.entry.rightOpen);
- logger.debug("push: this assert is OK, now i process the token");
process(token);
- logger.debug("push: the token has been processed");
}
}
else if (parent.isC())
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)
{
// As by the TeX parsing rules of undelimited parameters,
// 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
- logger.debug("TPushParser.push: we should be here");
frame.pos++;
process(token);
}
else
{
// There is a mismatch. Emit an error and ignore the token?
- cerr << "ERROR: token ignored: " << token.value << " (cat: " << token.category << ")" << endl;
+ logger.debug("parser: token ignored: " + token.value);
}
}
process(token);
else
{
- cout << "ignored token" << endl;
+ logger.warning("ignored token");
}
} // this end corresponds to the else of the if (token.category == TToken::GDELETE)
if (factory) factory->documentModified(doc);
- if (frames.empty()) cout << "stack vuoto" << endl;
- else
- {
- logger.debug("push: the stack is not empty");
- logger.debug("push: is the top element rightOpen?");
- cout << frames.top().entry.rightOpen << endl;
- logger.debug("push: is the pattern empty");
- cout << frames.top().entry.pattern.empty() << endl;
- }
}
void