TPushParser::TPushParser(ALogger& l, const TDictionary& d) : APushParser(l), dictionary(d)
{
- init();
+ reset();
}
TPushParser::TPushParser(ALogger& l, AMathMLFactory& f, const TDictionary& d) : APushParser(l, f), dictionary(d)
{
- init();
+ reset();
+}
+
+TPushParser::~TPushParser()
+{
}
void
-TPushParser::init()
+TPushParser::reset()
{
+ APushParser::reset();
nextId = 1;
cursor = doc.create("cursor");
cursor["id"] = "I0";
doc.clearDirty();
doc.root().append(cursor);
- logger.verbosity(ALogger::Debug);
-}
-
-TPushParser::~TPushParser()
-{
}
std::string
case TToken::ACTIVE: do_active(token.value); break;
case TToken::COMMENT: do_comment(); break;
case TToken::CONTROL: do_control(token.value); break;
- case TToken::GDELETE: do_gdelete(); break;
}
}
void
TPushParser::push(const TToken& token)
{
- if (token.category == TToken::GDELETE)
- {
- process(token);
- }
- else
- {
-
- TNode parent = cursor.parent();
- // If the cursor has no parent then it is detached from the editing
- // tree, which means this token will be ignored
-
- if (parent)
- // If the parent is a phantom group and the grand-parent is a
- // control sequence, there are two cases:
- // a. we are parsing a delimited argument of a entry
- // b. we are parsing a side of a right- or left-open entry
- if (parent.isG() && !parent.hasId() && parent.parent().isC())
- {
- // There must be an open frame, for the grand-parent is a control sequence
- assert(!frames.empty());
- Frame& frame = frames.top();
- if (!frame.entry.pattern.empty())
+ TNode parent = cursor.parent();
+ // If the cursor has no parent then it is detached from the editing
+ // tree, which means this token will be ignored
+
+ if (parent)
+ // If the parent is a phantom group and the grand-parent is a
+ // control sequence, there are two cases:
+ // a. we are parsing a delimited argument of a entry
+ // b. we are parsing a side of a right- or left-open entry
+ if (parent.isG() && !parent.hasId() && parent.parent().isC())
+ {
+ // There must be an open frame, for the grand-parent is a control sequence
+ assert(!frames.empty());
+ Frame& frame = frames.top();
+ if (!frame.entry.pattern.empty())
+ {
+ // The entry pattern is not empty. By our conventions this means
+ // the entry cannot be open at either end, hence we are parsing
+ // a delimited argument
+ assert(frame.pos + 1 < frame.entry.pattern.size());
+ assert(frame.entry.pattern[frame.pos + 1].category != TToken::PARAMETER);
+ if (frame.entry.pattern[frame.pos + 1] == token)
{
- // The entry pattern is not empty. By our conventions this means
- // the entry cannot be open at either end, hence we are parsing
- // a delimited argument
- assert(frame.pos + 1 < frame.entry.pattern.size());
- assert(frame.entry.pattern[frame.pos + 1].category != TToken::PARAMETER);
- if (frame.entry.pattern[frame.pos + 1] == token)
- {
- // The token matches with a delimiter of the argument,
- // so we increment the frame.pos
+ // The token matches with a delimiter of the argument,
+ // so we increment the frame.pos
+ frame.pos++;
+
+ if (frame.entry.lastDelimiter(frame.pos))
+ {
+ // this delimiter is the last one for the argumet,
+ // so the argument is completed
+ cursor.remove();
frame.pos++;
- if (frame.entry.lastDelimiter(frame.pos))
+ if (frame.pos == frame.entry.pattern.size())
{
- // this delimiter is the last one for the argumet,
- // so the argument is completed
- cursor.remove();
- frame.pos++;
-
- if (frame.pos == frame.entry.pattern.size())
- {
- // This token has completed the entry
- advance(parent);
- }
- else if (frame.entry.paramDelimited(frame.pos))
- {
- // For the next is a delimited argument we have to place
- // a suitable phantom group with the cursor inside
- TNode g = doc.createG();
- parent.parent().append(g);
- g.append(cursor);
- }
- else
- parent.parent().append(cursor);
+ // This token has completed the entry
+ advance(parent);
}
- }
- else
- {
- // Delimiter mismatch.
- if (frame.entry.pattern[frame.pos].category != TToken::PARAMETER)
+ 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 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
- // 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);
+ // For the next is a delimited argument we have to place
+ // a suitable phantom group with the cursor inside
+ TNode g = doc.createG();
+ parent.parent().append(g);
+ g.append(cursor);
}
else
- {
- // in this case, the sequence of delimiters is composed of one
- // delimiter. It means that we have to process the token
- process(token);
- }
- }
+ parent.parent().append(cursor);
+ }
}
else
{
- // The entry pattern is empty, hence we are parsing a right-open
- // entry. What happens if we actually are in the left side?
- // This could happen only when re-editing an entered expression
- // We'll see...
- assert(frame.entry.rightOpen);
- process(token);
- }
- }
- else if (parent.isC())
- {
- // We are parsing a non-delimited argument entry
- // or a fixed token
- Frame& frame = frames.top();
- assert(frame.pos < frame.entry.pattern.size());
-
- if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER)
- {
- // As by the TeX parsing rules of undelimited parameters,
- // empty spaces are ignored
- if (token.category != TToken::SPACE)
- {
- // We need to increase the frame position here, becase inside
- // process the function advance will be called. At that point
- // it will be important for the parser to know that the entry
- // has been completed in order to place the cursor correctly
- // in the next position
- frame.pos++;
+ // Delimiter mismatch.
+ if (frame.entry.pattern[frame.pos].category != TToken::PARAMETER)
+ {
+ // in this case, there is a sequence of delimiters that delimitates
+ // the argument, and the user correctly inserted a portion of this
+ // sequence, but 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
+ // 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
+ {
+ // in this case, the sequence of delimiters is composed of one
+ // delimiter. It means that we have to process the token
process(token);
- }
+ }
}
- else if (frame.entry.pattern[frame.pos] == token)
+ }
+ else
+ {
+ // The entry pattern is empty, hence we are parsing a right-open
+ // entry. What happens if we actually are in the left side?
+ // This could happen only when re-editing an entered expression
+ // We'll see...
+ assert(frame.entry.rightOpen);
+ process(token);
+ }
+ }
+ else if (parent.isC())
+ {
+ // We are parsing a non-delimited argument entry
+ // or a fixed token
+ Frame& frame = frames.top();
+ assert(frame.pos < frame.entry.pattern.size());
+
+ if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER)
+ {
+ // As by the TeX parsing rules of undelimited parameters,
+ // empty spaces are ignored
+ if (token.category != TToken::SPACE)
{
- // The token has been accepted
- frame.pos++;
- if (frame.pos < frame.entry.pattern.size() &&
- frame.entry.paramDelimited(frame.pos))
- {
- // If the next is a delimited argument we have to place
- // the phantom group with the cursor inside
- TNode g = doc.createG();
- cursor.replace(g);
- g.append(cursor);
- }
- else
- advance(parent);
+ // We need to increase the frame position here, becase inside
+ // process the function advance will be called. At that point
+ // it will be important for the parser to know that the entry
+ // has been completed in order to place the cursor correctly
+ // in the next position
+ frame.pos++;
+ process(token);
}
- else
+ }
+ else if (frame.entry.pattern[frame.pos] == token)
+ {
+ // The token has been accepted
+ frame.pos++;
+ if (frame.pos < frame.entry.pattern.size() &&
+ frame.entry.paramDelimited(frame.pos))
{
- // There is a mismatch. Emit an error and ignore the token?
- logger.debug("parser: token ignored: " + token.value);
+ // If the next is a delimited argument we have to place
+ // the phantom group with the cursor inside
+ TNode g = doc.createG();
+ cursor.replace(g);
+ g.append(cursor);
}
+ else
+ advance(parent);
+ }
+ else
+ {
+ // There is a mismatch. Emit an error and ignore the token?
+ logger.debug("parser: token ignored: " + token.value);
+ }
- }
- else
- process(token);
- else
- {
- logger.warning("ignored token");
- }
-
- } // this end corresponds to the else of the if (token.category == TToken::GDELETE)
+ }
+ else
+ process(token);
+ else
+ {
+ logger.warning("ignored token");
+ }
- if (factory) factory->documentModified(doc);
+ if (factory && doc.dirtyNode() && !frozen()) factory->documentModified(doc);
+}
+std::string
+TPushParser::drop()
+{
+ do_gdelete();
+ if (factory && doc.dirtyNode() && !frozen()) factory->documentModified(doc);
+ return "";
}
void
void
TPushParser::setCursorHint(const std::string& c)
{
- cursor["val"] = c;
- if (factory) factory->documentModified(doc);
+ if (cursor["val"] != c)
+ {
+ cursor["val"] = c;
+ if (factory && doc.dirtyNode() && !frozen()) factory->documentModified(doc);
+ }
+}
+
+bool
+TPushParser::thaw()
+{
+ if (APushParser::thaw() && factory && doc.dirtyNode())
+ {
+ factory->documentModified(doc);
+ return true;
+ }
+ else
+ return false;
}