Implements #1674 "augment TerminalNode with setParent()" for Swift target.

This commit is contained in:
Hanzhou Shi 2017-02-24 23:54:25 -08:00
parent 392c637565
commit 38c3aaae8f
4 changed files with 44 additions and 26 deletions

View File

@ -595,35 +595,21 @@ open class Parser: Recognizer<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 func createTerminalNode(parent: ParserRuleContext, t: Token) -> TerminalNode {
let node = TerminalNodeImpl(t);
node.parent = parent;
return node;
return 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 func createErrorNode(parent: ParserRuleContext, t: Token) -> ErrorNode {
let node = ErrorNode(t);
node.parent = parent;
return node;
return ErrorNode(t);
}
internal func addContextToParseTree() {

View File

@ -72,6 +72,14 @@ open class ParserRuleContext: RuleContext {
/** COPY a ctx (I'm deliberately not using copy constructor) to avoid
* confusion with creating node with parent. Does not copy children.
*
* 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
* not really a generic copy function.
*
* If we do an error sync() at start of a rule, we might add error nodes
* to the generic XContext so this function must copy those nodes to
* the YContext as well else they are lost!
*/
open func copyFrom(_ ctx: ParserRuleContext) {
self.parent = ctx.parent
@ -81,13 +89,12 @@ open class ParserRuleContext: RuleContext {
self.stop = ctx.stop
// copy any error nodes to alt label node
if ctx.children != nil{
if ctx.children != nil {
self.children = Array<ParseTree>()
// reset parent pointer for any error nodes
for child: ParseTree in ctx.children! {
if child is ErrorNode{
self.children?.append(child)
( (child as! ErrorNode)).parent = self
if child is ErrorNode {
addChild(child as! ErrorNode)
}
}
}
@ -130,14 +137,20 @@ open class ParserRuleContext: RuleContext {
return addAnyChild(ruleInvocation)
}
/** Add a token leaf node child and force its parent to be this node. */
@discardableResult
open func addChild(_ t: TerminalNode) -> TerminalNode {
t.setParent(self)
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
*/
@discardableResult
open func addErrorNode(_ errorNode: ErrorNode) -> ErrorNode {
errorNode.setParent(self)
return addAnyChild(errorNode)
}
@ -150,7 +163,7 @@ open class ParserRuleContext: RuleContext {
open func addChild(_ matchedToken: Token) -> TerminalNode {
let t: TerminalNodeImpl = TerminalNodeImpl(matchedToken)
addAnyChild(t)
t.parent = self
t.setParent(self)
return t
}
@ -164,7 +177,7 @@ open class ParserRuleContext: RuleContext {
open func addErrorNode(_ badToken: Token) -> ErrorNode {
let t: ErrorNode = ErrorNode(badToken)
addAnyChild(t)
t.parent = self
t.setParent(self)
return t
}

View File

@ -9,4 +9,18 @@ public class TerminalNode: ParseTree {
fatalError()
}
/** 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
*/
public func setParent(_ parent: RuleContext) {
RuntimeException(" must overriden !")
fatalError()
}
}

View File

@ -27,6 +27,11 @@ public class TerminalNodeImpl: TerminalNode {
return parent
}
override
public func setParent(_ parent: RuleContext) {
self.parent = parent
}
override
public func getPayload() -> AnyObject {
return symbol