From: Paolo Marinelli Date: Thu, 6 Feb 2003 11:53:48 +0000 (+0000) Subject: Added some controls to handle the case in which the user type an unexpected '{' X-Git-Tag: V_0_0_4_1~54 X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=commitdiff_plain;h=2f7288d494e3053b02d589ffcd3d54b7c595d2cc;p=helm.git Added some controls to handle the case in which the user type an unexpected '{' character. Now, the editor doesn't crash, but emit an error. Removed some debug messages. --- diff --git a/helm/DEVEL/mathml_editor/src/TPushParser.cc b/helm/DEVEL/mathml_editor/src/TPushParser.cc index 870e9f0a7..62a9208e6 100644 --- a/helm/DEVEL/mathml_editor/src/TPushParser.cc +++ b/helm/DEVEL/mathml_editor/src/TPushParser.cc @@ -78,7 +78,7 @@ TPushParser::do_end() 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 @@ -91,7 +91,7 @@ TPushParser::do_end() { // 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); } } @@ -150,7 +150,7 @@ TPushParser::do_shift() // 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"); } } @@ -326,7 +326,7 @@ TPushParser::do_apostrophe() 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 @@ -344,8 +344,8 @@ TPushParser::do_other(const std::string& s) do_apostrophe(); break; default: - cout << "TPushParser::do_other " << s << endl; - cout << "DOCUMENT: " << static_cast(cursor.element().get_ownerDocument()) << endl; + /*cout << "TPushParser::do_other " << s << endl; + cout << "DOCUMENT: " << static_cast(cursor.element().get_ownerDocument()) << endl;*/ TNode elem = doc.createT("o", s, nextId++); cursor.replace(elem); advance(elem); @@ -427,10 +427,6 @@ TPushParser::do_control(const std::string& name) 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()); @@ -480,7 +476,7 @@ TPushParser::do_control(const std::string& name) 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); @@ -488,7 +484,7 @@ TPushParser::do_control(const std::string& name) 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); @@ -507,14 +503,11 @@ TPushParser::gdelete_prev_token() 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); @@ -527,7 +520,6 @@ TPushParser::gdelete_prev_token() 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 @@ -536,47 +528,38 @@ TPushParser::gdelete_prev_token() 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(); @@ -586,69 +569,45 @@ TPushParser::gdelete_prev_macro() 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()); @@ -660,64 +619,59 @@ TPushParser::gdelete_prev_macro() } 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()) @@ -725,17 +679,15 @@ TPushParser::gdelete_prev_macro() } // 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 @@ -743,8 +695,6 @@ TPushParser::gdelete_prev() { // 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()); @@ -764,7 +714,7 @@ TPushParser::gdelete_prev() } 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 @@ -772,18 +722,17 @@ TPushParser::gdelete_prev() // 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()); @@ -798,6 +747,7 @@ TPushParser::rgreplace_futher(void) 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(); @@ -809,14 +759,12 @@ TPushParser::rgreplace_futher(void) 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(); @@ -827,29 +775,33 @@ TPushParser::do_gdelete_script() 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 @@ -858,7 +810,7 @@ TPushParser::do_gdelete_macro() // 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(); @@ -869,27 +821,26 @@ TPushParser::do_gdelete_macro() // 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); @@ -898,22 +849,18 @@ TPushParser::do_gdelete_macro() } 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; @@ -921,13 +868,12 @@ TPushParser::do_gdelete_macro() 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 @@ -942,27 +888,25 @@ TPushParser::do_gdelete_groupId() 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 @@ -970,7 +914,6 @@ TPushParser::do_gdelete_phantom_group() { // 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(); @@ -980,29 +923,30 @@ TPushParser::do_gdelete_phantom_group() 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); @@ -1012,63 +956,57 @@ TPushParser::do_gdelete_phantom_group() { // 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()) @@ -1077,9 +1015,6 @@ TPushParser::do_gdelete_phantom_group() // 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) { @@ -1089,7 +1024,7 @@ TPushParser::do_gdelete_phantom_group() assert(frame.pos == 0); cursor.remove(); parent.remove(); - gfuther.replace(cursor); + gfather.replace(cursor); frames.pop(); } else @@ -1099,7 +1034,7 @@ TPushParser::do_gdelete_phantom_group() 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()); @@ -1119,7 +1054,7 @@ TPushParser::do_gdelete_phantom_group() 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 @@ -1127,45 +1062,43 @@ TPushParser::do_gdelete_phantom_group() 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(); @@ -1173,7 +1106,7 @@ TPushParser::do_gdelete_phantom_group() 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(); @@ -1182,7 +1115,7 @@ TPushParser::do_gdelete_phantom_group() } 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(); @@ -1200,41 +1133,45 @@ TPushParser::do_gdelete_phantom_group() 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()) { @@ -1248,392 +1185,34 @@ TPushParser::do_gdelete() 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) { @@ -1661,18 +1240,13 @@ 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 @@ -1685,19 +1259,13 @@ TPushParser::push(const TToken& token) 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) @@ -1716,8 +1284,7 @@ TPushParser::push(const TToken& 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)) { @@ -1738,14 +1305,12 @@ TPushParser::push(const TToken& token) { // 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 { @@ -1761,11 +1326,8 @@ TPushParser::push(const TToken& token) // 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()) @@ -1775,7 +1337,6 @@ TPushParser::push(const TToken& 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) { // As by the TeX parsing rules of undelimited parameters, @@ -1787,7 +1348,6 @@ TPushParser::push(const TToken& token) // 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); } @@ -1811,7 +1371,7 @@ TPushParser::push(const TToken& 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); } } @@ -1819,22 +1379,13 @@ TPushParser::push(const TToken& token) 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 diff --git a/helm/DEVEL/mathml_editor/src/TPushParser.hh b/helm/DEVEL/mathml_editor/src/TPushParser.hh index 143e8fad1..e852bc607 100644 --- a/helm/DEVEL/mathml_editor/src/TPushParser.hh +++ b/helm/DEVEL/mathml_editor/src/TPushParser.hh @@ -52,7 +52,7 @@ private: void gdelete_prev_macro(void); void gdelete_prev(void); - void rgreplace_futher(void); + void rgreplace_father(void); void do_gdelete_script(void); void do_gdelete_macro(void);