augment TerminalNode with setParent(). Technically, this is not backward compatible as it changes the interface but no one was able to create custom TerminalNodes anyway so I'm adding as it improves internal code quality. addChild now sets the parent rather than create. MUCH better.

This commit is contained in:
parrt 2017-02-18 11:21:17 -08:00
parent 2b3508d57e
commit 81681abfb3
4 changed files with 35 additions and 26 deletions

View File

@ -20,7 +20,6 @@ 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;
@ -594,35 +593,21 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
}
/** 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).
* Typically, the terminal node to create is not a function of the parent.
*
* @since 4.6.1
*/
public TerminalNode createTerminalNode(ParserRuleContext parent, Token t) {
TerminalNodeImpl node = new TerminalNodeImpl(t);
node.parent = parent;
return node;
return new TerminalNodeImpl(t);
}
/** 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).
* Typically, the error node to create is not a function of the parent.
*
* @since 4.6.1
*/
public ErrorNode createErrorNode(ParserRuleContext parent, Token t) {
ErrorNodeImpl node = new ErrorNodeImpl(t);
node.parent = parent;
return node;
return new ErrorNodeImpl(t);
}
protected void addContextToParseTree() {

View File

@ -79,7 +79,8 @@ public class ParserRuleContext extends RuleContext {
public ParserRuleContext() { }
/** COPY a ctx (I'm deliberately not using copy constructor) to avoid
* confusion with creating node with parent. Does not copy children.
* confusion with creating node with parent. Does not copy children
* (except error leaves).
*
* This is used in the generated parser code to flip a generic XContext
* node for rule X to a YContext for alt label Y. In that sense, it is
@ -101,9 +102,8 @@ public class ParserRuleContext extends RuleContext {
this.children = new ArrayList<>();
// reset parent pointer for any error nodes
for (ParseTree child : ctx.children) {
if ( child instanceof ErrorNodeImpl ) {
this.children.add(child);
((ErrorNodeImpl) child).parent = this;
if ( child instanceof ErrorNode ) {
addChild((ErrorNode)child);
}
}
}
@ -139,12 +139,18 @@ public class ParserRuleContext extends RuleContext {
return addAnyChild(ruleInvocation);
}
/** Add a token leaf node child and force its parent to be this node. */
public TerminalNode addChild(TerminalNode t) {
t.setParent(this);
return addAnyChild(t);
}
/** Add an error node child. @since 4.6.1 */
/** Add an error node child and force its parent to be this node.
*
* @since 4.6.1
*/
public ErrorNode addErrorNode(ErrorNode errorNode) {
errorNode.setParent(this);
return addAnyChild(errorNode);
}
@ -157,7 +163,7 @@ public class ParserRuleContext extends RuleContext {
public TerminalNode addChild(Token matchedToken) {
TerminalNodeImpl t = new TerminalNodeImpl(matchedToken);
addAnyChild(t);
t.parent = this;
t.setParent(this);
return t;
}
@ -170,7 +176,7 @@ public class ParserRuleContext extends RuleContext {
public ErrorNode addErrorNode(Token badToken) {
ErrorNodeImpl t = new ErrorNodeImpl(badToken);
addAnyChild(t);
t.parent = this;
t.setParent(this);
return t;
}

View File

@ -6,8 +6,20 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
public interface TerminalNode extends ParseTree {
Token getSymbol();
/** Set the parent for this leaf node.
*
* Technically, this is not backward compatible as it changes
* the interface but no one was able to create custom
* TerminalNodes anyway so I'm adding as it improves internal
* code quality.
*
* @since 4.6.1
*/
void setParent(RuleContext parent);
}

View File

@ -7,6 +7,7 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;
@ -25,6 +26,11 @@ public class TerminalNodeImpl implements TerminalNode {
@Override
public ParseTree getParent() { return parent; }
@Override
public void setParent(RuleContext parent) {
this.parent = parent;
}
@Override
public Token getPayload() { return symbol; }