Merge pull request #1665 from parrt/factor-create-leaves
factor out the creation of error nodes and terminal nodes in the parser
This commit is contained in:
commit
628aa8ff02
|
@ -6,6 +6,8 @@
|
|||
|
||||
package org.antlr.v4.runtime;
|
||||
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
|
||||
/**
|
||||
* The interface for defining strategies to deal with syntax errors encountered
|
||||
* during a parse by ANTLR-generated parsers. We distinguish between three
|
||||
|
@ -89,8 +91,9 @@ public interface ANTLRErrorStrategy {
|
|||
* Tests whether or not {@code recognizer} is in the process of recovering
|
||||
* from an error. In error recovery mode, {@link Parser#consume} adds
|
||||
* symbols to the parse tree by calling
|
||||
* {@link ParserRuleContext#addErrorNode(Token)} instead of
|
||||
* {@link ParserRuleContext#addChild(Token)}.
|
||||
* {@link Parser#createErrorNode(ParserRuleContext, Token)} then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)} instead of
|
||||
* {@link Parser#createTerminalNode(ParserRuleContext, Token)}.
|
||||
*
|
||||
* @param recognizer the parser instance
|
||||
* @return {@code true} if the parser is currently recovering from a parse
|
||||
|
|
|
@ -19,9 +19,12 @@ import org.antlr.v4.runtime.dfa.DFA;
|
|||
import org.antlr.v4.runtime.misc.IntegerStack;
|
||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.ErrorNodeImpl;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
|
||||
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
|
||||
import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
|
||||
|
||||
|
@ -182,7 +185,8 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
* strategy to attempt recovery. If {@link #getBuildParseTree} is
|
||||
* {@code true} and the token index of the symbol returned by
|
||||
* {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to
|
||||
* the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p>
|
||||
* the parse tree by calling {@link #createErrorNode(ParserRuleContext, Token)} then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)}.</p>
|
||||
*
|
||||
* @param ttype the token type to match
|
||||
* @return the matched symbol
|
||||
|
@ -204,7 +208,7 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
if ( _buildParseTrees && t.getTokenIndex()==-1 ) {
|
||||
// we must have conjured up a new token during single token insertion
|
||||
// if it's not the current symbol
|
||||
_ctx.addErrorNode(t);
|
||||
_ctx.addErrorNode(createErrorNode(_ctx,t));
|
||||
}
|
||||
}
|
||||
return t;
|
||||
|
@ -220,7 +224,8 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
* strategy to attempt recovery. If {@link #getBuildParseTree} is
|
||||
* {@code true} and the token index of the symbol returned by
|
||||
* {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to
|
||||
* the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p>
|
||||
* the parse tree by calling {@link Parser#createErrorNode(ParserRuleContext, Token)}. then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)}</p>
|
||||
*
|
||||
* @return the matched symbol
|
||||
* @throws RecognitionException if the current input symbol did not match
|
||||
|
@ -238,7 +243,7 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
if (_buildParseTrees && t.getTokenIndex() == -1) {
|
||||
// we must have conjured up a new token during single token insertion
|
||||
// if it's not the current symbol
|
||||
_ctx.addErrorNode(t);
|
||||
_ctx.addErrorNode(createErrorNode(_ctx,t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,11 +558,11 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
* </pre>
|
||||
*
|
||||
* If the parser is not in error recovery mode, the consumed symbol is added
|
||||
* to the parse tree using {@link ParserRuleContext#addChild(Token)}, and
|
||||
* to the parse tree using {@link ParserRuleContext#addChild(TerminalNode)}, and
|
||||
* {@link ParseTreeListener#visitTerminal} is called on any parse listeners.
|
||||
* If the parser <em>is</em> in error recovery mode, the consumed symbol is
|
||||
* added to the parse tree using
|
||||
* {@link ParserRuleContext#addErrorNode(Token)}, and
|
||||
* added to the parse tree using {@link #createErrorNode(ParserRuleContext, Token)} then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)} and
|
||||
* {@link ParseTreeListener#visitErrorNode} is called on any parse
|
||||
* listeners.
|
||||
*/
|
||||
|
@ -569,7 +574,7 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
boolean hasListener = _parseListeners != null && !_parseListeners.isEmpty();
|
||||
if (_buildParseTrees || hasListener) {
|
||||
if ( _errHandler.inErrorRecoveryMode(this) ) {
|
||||
ErrorNode node = _ctx.addErrorNode(o);
|
||||
ErrorNode node = _ctx.addErrorNode(createErrorNode(_ctx,o));
|
||||
if (_parseListeners != null) {
|
||||
for (ParseTreeListener listener : _parseListeners) {
|
||||
listener.visitErrorNode(node);
|
||||
|
@ -577,7 +582,7 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
}
|
||||
}
|
||||
else {
|
||||
TerminalNode node = _ctx.addChild(o);
|
||||
TerminalNode node = _ctx.addChild(createTerminalNode(_ctx,o));
|
||||
if (_parseListeners != null) {
|
||||
for (ParseTreeListener listener : _parseListeners) {
|
||||
listener.visitTerminal(node);
|
||||
|
@ -588,6 +593,38 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
return o;
|
||||
}
|
||||
|
||||
/** How to create a token leaf node associated with a parent.
|
||||
* Typically, the terminal node to create is not a function of the parent
|
||||
* but this method must still set the parent pointer of the terminal node
|
||||
* returned. I would prefer having {@link ParserRuleContext#addAnyChild(ParseTree)}
|
||||
* set the parent pointer, but the parent pointer is implementation dependent
|
||||
* and currently there is no setParent() in {@link TerminalNode} (and can't
|
||||
* add method in Java 1.7 without breaking backward compatibility).
|
||||
*
|
||||
* @since 4.6.1
|
||||
*/
|
||||
public TerminalNode createTerminalNode(ParserRuleContext parent, Token t) {
|
||||
TerminalNodeImpl node = new TerminalNodeImpl(t);
|
||||
node.parent = parent;
|
||||
return node;
|
||||
}
|
||||
|
||||
/** How to create an error node, given a token, associated with a parent.
|
||||
* Typically, the error node to create is not a function of the parent
|
||||
* but this method must still set the parent pointer of the terminal node
|
||||
* returned. I would prefer having {@link ParserRuleContext#addAnyChild(ParseTree)}
|
||||
* set the parent pointer, but the parent pointer is implementation dependent
|
||||
* and currently there is no setParent() in {@link ErrorNode} (and can't
|
||||
* add method in Java 1.7 without breaking backward compatibility).
|
||||
*
|
||||
* @since 4.6.1
|
||||
*/
|
||||
public ErrorNode createErrorNode(ParserRuleContext parent, Token t) {
|
||||
ErrorNodeImpl node = new ErrorNodeImpl(t);
|
||||
node.parent = parent;
|
||||
return node;
|
||||
}
|
||||
|
||||
protected void addContextToParseTree() {
|
||||
ParserRuleContext parent = (ParserRuleContext)_ctx.parent;
|
||||
// add current context to parent if we have a parent
|
||||
|
@ -925,3 +962,4 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
return _tracer != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -414,7 +414,7 @@ public class ParserInterpreter extends Parser {
|
|||
Token.DEFAULT_CHANNEL,
|
||||
-1, -1, // invalid start/stop
|
||||
tok.getLine(), tok.getCharPositionInLine());
|
||||
_ctx.addErrorNode(errToken);
|
||||
_ctx.addErrorNode(createErrorNode(_ctx,errToken));
|
||||
}
|
||||
else { // NoViableAlt
|
||||
Token tok = e.getOffendingToken();
|
||||
|
@ -424,7 +424,7 @@ public class ParserInterpreter extends Parser {
|
|||
Token.DEFAULT_CHANNEL,
|
||||
-1, -1, // invalid start/stop
|
||||
tok.getLine(), tok.getCharPositionInLine());
|
||||
_ctx.addErrorNode(errToken);
|
||||
_ctx.addErrorNode(createErrorNode(_ctx,errToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,3 +445,4 @@ public class ParserInterpreter extends Parser {
|
|||
return rootContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,19 +118,67 @@ public class ParserRuleContext extends RuleContext {
|
|||
public void enterRule(ParseTreeListener listener) { }
|
||||
public void exitRule(ParseTreeListener listener) { }
|
||||
|
||||
/** Does not set parent link; other add methods do that */
|
||||
public TerminalNode addChild(TerminalNode t) {
|
||||
if ( children==null ) children = new ArrayList<ParseTree>();
|
||||
/** Add a parse tree node to this as a child. Works for
|
||||
* internal and leaf nodes. Does not set parent link;
|
||||
* other add methods must do that. Other addChild methods
|
||||
* call this.
|
||||
*
|
||||
* We cannot set the parent pointer of the incoming node
|
||||
* because the existing interfaces do not have a setParent()
|
||||
* method and I don't want to break backward compatibility for this.
|
||||
*
|
||||
* @since 4.6.1
|
||||
*/
|
||||
public <T extends ParseTree> T addAnyChild(T t) {
|
||||
if ( children==null ) children = new ArrayList<>();
|
||||
children.add(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
public RuleContext addChild(RuleContext ruleInvocation) {
|
||||
if ( children==null ) children = new ArrayList<ParseTree>();
|
||||
children.add(ruleInvocation);
|
||||
return ruleInvocation;
|
||||
return addAnyChild(ruleInvocation);
|
||||
}
|
||||
|
||||
public TerminalNode addChild(TerminalNode t) {
|
||||
return addAnyChild(t);
|
||||
}
|
||||
|
||||
/** Add an error node child. @since 4.6.1 */
|
||||
public ErrorNode addErrorNode(ErrorNode errorNode) {
|
||||
return addAnyChild(errorNode);
|
||||
}
|
||||
|
||||
/** Add a child to this node based upon matchedToken. It
|
||||
* creates a TerminalNodeImpl rather than using
|
||||
* {@link Parser#createTerminalNode(ParserRuleContext, Token)}. I'm leaving this
|
||||
* in for compatibility but the parser doesn't use this anymore.
|
||||
*/
|
||||
@Deprecated
|
||||
public TerminalNode addChild(Token matchedToken) {
|
||||
TerminalNodeImpl t = new TerminalNodeImpl(matchedToken);
|
||||
addAnyChild(t);
|
||||
t.parent = this;
|
||||
return t;
|
||||
}
|
||||
|
||||
/** Add a child to this node based upon badToken. It
|
||||
* creates a ErrorNodeImpl rather than using
|
||||
* {@link Parser#createErrorNode(ParserRuleContext, Token)}. I'm leaving this
|
||||
* in for compatibility but the parser doesn't use this anymore.
|
||||
*/
|
||||
@Deprecated
|
||||
public ErrorNode addErrorNode(Token badToken) {
|
||||
ErrorNodeImpl t = new ErrorNodeImpl(badToken);
|
||||
addAnyChild(t);
|
||||
t.parent = this;
|
||||
return t;
|
||||
}
|
||||
|
||||
// public void trace(int s) {
|
||||
// if ( states==null ) states = new ArrayList<Integer>();
|
||||
// states.add(s);
|
||||
// }
|
||||
|
||||
/** Used by enterOuterAlt to toss out a RuleContext previously added as
|
||||
* we entered a rule. If we have # label, we will need to remove
|
||||
* generic ruleContext object.
|
||||
|
@ -141,25 +189,6 @@ public class ParserRuleContext extends RuleContext {
|
|||
}
|
||||
}
|
||||
|
||||
// public void trace(int s) {
|
||||
// if ( states==null ) states = new ArrayList<Integer>();
|
||||
// states.add(s);
|
||||
// }
|
||||
|
||||
public TerminalNode addChild(Token matchedToken) {
|
||||
TerminalNodeImpl t = new TerminalNodeImpl(matchedToken);
|
||||
addChild(t);
|
||||
t.parent = this;
|
||||
return t;
|
||||
}
|
||||
|
||||
public ErrorNode addErrorNode(Token badToken) {
|
||||
ErrorNodeImpl t = new ErrorNodeImpl(badToken);
|
||||
addChild(t);
|
||||
t.parent = this;
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
/** Override to make type more specific */
|
||||
public ParserRuleContext getParent() {
|
||||
|
@ -300,3 +329,4 @@ public class ParserRuleContext extends RuleContext {
|
|||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue