use of org.antlr.v4.runtime.ParserRuleContext in project antlr4 by antlr.
the class ParseTreePatternMatcher method matchImpl.
// ---- SUPPORT CODE ----
/**
* Recursively walk {@code tree} against {@code patternTree}, filling
* {@code match.}{@link ParseTreeMatch#labels labels}.
*
* @return the first node encountered in {@code tree} which does not match
* a corresponding node in {@code patternTree}, or {@code null} if the match
* was successful. The specific node returned depends on the matching
* algorithm used by the implementation, and may be overridden.
*/
protected ParseTree matchImpl(ParseTree tree, ParseTree patternTree, MultiMap<String, ParseTree> labels) {
if (tree == null) {
throw new IllegalArgumentException("tree cannot be null");
}
if (patternTree == null) {
throw new IllegalArgumentException("patternTree cannot be null");
}
// x and <ID>, x and y, or x and x; or could be mismatched types
if (tree instanceof TerminalNode && patternTree instanceof TerminalNode) {
TerminalNode t1 = (TerminalNode) tree;
TerminalNode t2 = (TerminalNode) patternTree;
ParseTree mismatchedNode = null;
// both are tokens and they have same type
if (t1.getSymbol().getType() == t2.getSymbol().getType()) {
if (t2.getSymbol() instanceof TokenTagToken) {
// x and <ID>
TokenTagToken tokenTagToken = (TokenTagToken) t2.getSymbol();
// track label->list-of-nodes for both token name and label (if any)
labels.map(tokenTagToken.getTokenName(), tree);
if (tokenTagToken.getLabel() != null) {
labels.map(tokenTagToken.getLabel(), tree);
}
} else if (t1.getText().equals(t2.getText())) {
// x and x
} else {
// x and y
if (mismatchedNode == null) {
mismatchedNode = t1;
}
}
} else {
if (mismatchedNode == null) {
mismatchedNode = t1;
}
}
return mismatchedNode;
}
if (tree instanceof ParserRuleContext && patternTree instanceof ParserRuleContext) {
ParserRuleContext r1 = (ParserRuleContext) tree;
ParserRuleContext r2 = (ParserRuleContext) patternTree;
ParseTree mismatchedNode = null;
// (expr ...) and <expr>
RuleTagToken ruleTagToken = getRuleTagToken(r2);
if (ruleTagToken != null) {
ParseTreeMatch m = null;
if (r1.getRuleContext().getRuleIndex() == r2.getRuleContext().getRuleIndex()) {
// track label->list-of-nodes for both rule name and label (if any)
labels.map(ruleTagToken.getRuleName(), tree);
if (ruleTagToken.getLabel() != null) {
labels.map(ruleTagToken.getLabel(), tree);
}
} else {
if (mismatchedNode == null) {
mismatchedNode = r1;
}
}
return mismatchedNode;
}
// (expr ...) and (expr ...)
if (r1.getChildCount() != r2.getChildCount()) {
if (mismatchedNode == null) {
mismatchedNode = r1;
}
return mismatchedNode;
}
int n = r1.getChildCount();
for (int i = 0; i < n; i++) {
ParseTree childMatch = matchImpl(r1.getChild(i), patternTree.getChild(i), labels);
if (childMatch != null) {
return childMatch;
}
}
return mismatchedNode;
}
// if nodes aren't both tokens or both rule nodes, can't match
return tree;
}
use of org.antlr.v4.runtime.ParserRuleContext in project antlr4 by antlr.
the class XPath method evaluate.
/**
* Return a list of all nodes starting at {@code t} as root that satisfy the
* path. The root {@code /} is relative to the node passed to
* {@link #evaluate}.
*/
public Collection<ParseTree> evaluate(final ParseTree t) {
ParserRuleContext dummyRoot = new ParserRuleContext();
// don't set t's parent.
dummyRoot.children = Collections.singletonList(t);
Collection<ParseTree> work = Collections.<ParseTree>singleton(dummyRoot);
int i = 0;
while (i < elements.length) {
Collection<ParseTree> next = new LinkedHashSet<ParseTree>();
for (ParseTree node : work) {
if (node.getChildCount() > 0) {
// only try to match next element if it has children
// e.g., //func/*/stat might have a token node for which
// we can't go looking for stat nodes.
Collection<? extends ParseTree> matching = elements[i].evaluate(node);
next.addAll(matching);
}
}
i++;
work = next;
}
return work;
}
use of org.antlr.v4.runtime.ParserRuleContext in project antlr4 by antlr.
the class Parser method isExpectedToken.
/**
* Checks whether or not {@code symbol} can follow the current state in the
* ATN. The behavior of this method is equivalent to the following, but is
* implemented such that the complete context-sensitive follow set does not
* need to be explicitly constructed.
*
* <pre>
* return getExpectedTokens().contains(symbol);
* </pre>
*
* @param symbol the symbol type to check
* @return {@code true} if {@code symbol} can follow the current state in
* the ATN, otherwise {@code false}.
*/
public boolean isExpectedToken(int symbol) {
// return getInterpreter().atn.nextTokens(_ctx);
ATN atn = getInterpreter().atn;
ParserRuleContext ctx = _ctx;
ATNState s = atn.states.get(getState());
IntervalSet following = atn.nextTokens(s);
if (following.contains(symbol)) {
return true;
}
// System.out.println("following "+s+"="+following);
if (!following.contains(Token.EPSILON))
return false;
while (ctx != null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {
ATNState invokingState = atn.states.get(ctx.invokingState);
RuleTransition rt = (RuleTransition) invokingState.transition(0);
following = atn.nextTokens(rt.followState);
if (following.contains(symbol)) {
return true;
}
ctx = (ParserRuleContext) ctx.parent;
}
if (following.contains(Token.EPSILON) && symbol == Token.EOF) {
return true;
}
return false;
}
use of org.antlr.v4.runtime.ParserRuleContext in project antlr4 by antlr.
the class ParserInterpreter method visitRuleStopState.
protected void visitRuleStopState(ATNState p) {
RuleStartState ruleStartState = atn.ruleToStartState[p.ruleIndex];
if (ruleStartState.isLeftRecursiveRule) {
Pair<ParserRuleContext, Integer> parentContext = _parentContextStack.pop();
unrollRecursionContexts(parentContext.a);
setState(parentContext.b);
} else {
exitRule();
}
RuleTransition ruleTransition = (RuleTransition) atn.states.get(getState()).transition(0);
setState(ruleTransition.followState.stateNumber);
}
use of org.antlr.v4.runtime.ParserRuleContext in project antlr4 by antlr.
the class ParserRuleContext method addChild.
/** 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.setParent(this);
return t;
}
Aggregations