diff --git a/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift b/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift index deabbc0bd..7810eb7a3 100644 --- a/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift +++ b/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift @@ -28,13 +28,14 @@ /// open class ParserRuleContext: RuleContext { public var visited = false + /// If we are debugging or building a parse tree for a visitor, /// we need to track all of the tokens and rule invocations associated /// with this rule's context. This is empty for parsing w/o tree constr. /// operation because we don't the need to track the details about /// how we parse this rule. /// - public var children: Array? + public var children: [ParseTree]? /// For debugging/tracing purposes, we want to track all of the nodes in /// the ATN traversed by the parser for a particular rule. @@ -60,12 +61,16 @@ open class ParserRuleContext: RuleContext { /// The exception that forced this rule to return. If the rule successfully /// completed, this is `null`. /// - public var exception: AnyObject! + public var exception: RecognitionException? public override init() { super.init() } + public init(_ parent: ParserRuleContext?, _ invokingStateNumber: Int) { + super.init(parent, invokingStateNumber) + } + /// COPY a ctx (I'm deliberately not using copy constructor) to avoid /// confusion with creating node with parent. Does not copy children. /// @@ -80,26 +85,21 @@ open class ParserRuleContext: RuleContext { open func copyFrom(_ ctx: ParserRuleContext) { self.parent = ctx.parent self.invokingState = ctx.invokingState - self.start = ctx.start self.stop = ctx.stop // copy any error nodes to alt label node - if ctx.children != nil { - self.children = Array() + if let ctxChildren = ctx.children { + self.children = [ParseTree]() // reset parent pointer for any error nodes - for child: ParseTree in ctx.children! { - if child is ErrorNode { - addChild(child as! ErrorNode) + for child in ctxChildren { + if let errNode = child as? ErrorNode { + addChild(errNode) } } } } - public init(_ parent: ParserRuleContext?, _ invokingStateNumber: Int) { - super.init(parent, invokingStateNumber) - } - // Double dispatch methods for listeners open func enterRule(_ listener: ParseTreeListener) { @@ -141,99 +141,55 @@ open class ParserRuleContext: RuleContext { } /// Add an error node child and force its parent to be this node. - /// - /// - Since: 4.7 - /// @discardableResult open func addErrorNode(_ errorNode: ErrorNode) -> ErrorNode { errorNode.setParent(self) return addAnyChild(errorNode) } - /// Add a child to this node based upon matchedToken. It - /// creates a TerminalNodeImpl rather than using - /// _Parser#createTerminalNode(ParserRuleContext, Token)_. I'm leaving this - /// in for compatibility but the parser doesn't use this anymore. - /// - @available(*, deprecated) - open func addChild(_ matchedToken: Token) -> TerminalNode { - let t: TerminalNodeImpl = TerminalNodeImpl(matchedToken) - addAnyChild(t) - t.setParent(self) - return t - } - - /// Add a child to this node based upon badToken. It - /// creates a ErrorNodeImpl rather than using - /// _Parser#createErrorNode(ParserRuleContext, Token)_. I'm leaving this - /// in for compatibility but the parser doesn't use this anymore. - /// - @discardableResult - @available(*, deprecated) - open func addErrorNode(_ badToken: Token) -> ErrorNode { - let t: ErrorNode = ErrorNode(badToken) - addAnyChild(t) - t.setParent(self) - return t - } - - // public void trace(int s) { - // if ( states==null ) states = new ArrayList(); - // 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. /// open func removeLastChild() { - if children != nil { - children!.remove(at: children!.count-1) - } + children?.removeLast() } - override - /// - /// Override to make type more specific - /// - open func getParent() -> Tree? { - return super.getParent() - } - override open func getChild(_ i: Int) -> Tree? { - guard let children = children , i >= 0 && i < children.count else { + guard let children = children, i >= 0 && i < children.count else { return nil } return children[i] } - open func getChild(_ ctxType: T.Type, i: Int) -> T? { - guard let children = children , i >= 0 && i < children.count else { + open func getChild(_ ctxType: T.Type, i: Int) -> T? { + guard let children = children, i >= 0 && i < children.count else { return nil } - var j: Int = -1 // what element have we found with ctxType? - for o: ParseTree in children { - //if ( ctxType.isInstance(o) ) { + var j = -1 // what element have we found with ctxType? + for o in children { if let o = o as? T { j += 1 if j == i { - return o //ctxType.cast(o); + return o } } } + return nil } open func getToken(_ ttype: Int, _ i: Int) -> TerminalNode? { - guard let children = children , i >= 0 && i < children.count else { + guard let children = children, i >= 0 && i < children.count else { return nil } - var j: Int = -1 // what token with ttype have we found? - for o: ParseTree in children{ + var j = -1 // what token with ttype have we found? + for o in children { if let tnode = o as? TerminalNode { - let symbol: Token = tnode.getSymbol()! + let symbol = tnode.getSymbol()! if symbol.getType() == ttype { j += 1 if j == i { @@ -246,60 +202,40 @@ open class ParserRuleContext: RuleContext { return nil } - open func getTokens(_ ttype: Int) -> Array { - if children == nil { - return Array() + open func getTokens(_ ttype: Int) -> [TerminalNode] { + guard let children = children else { + return [TerminalNode]() } - var tokens: Array? = nil - for o: ParseTree in children! { - if o is TerminalNode { - let tnode: TerminalNode = o as! TerminalNode - let symbol: Token = tnode.getSymbol()! - if symbol.getType() == ttype { - if tokens == nil { - tokens = Array() - } - tokens?.append(tnode) - } + return children.flatMap { + if let tnode = $0 as? TerminalNode, let symbol = tnode.getSymbol(), symbol.getType() == ttype { + return tnode + } + else { + return nil } } - - if tokens == nil { - return Array() - } - - return tokens! } - open func getRuleContext(_ ctxType: T.Type, _ i: Int) -> T? { - + open func getRuleContext(_ ctxType: T.Type, _ i: Int) -> T? { return getChild(ctxType, i: i) } - open func getRuleContexts(_ ctxType: T.Type) -> Array { - - guard let children = children else { - return Array()//Collections.emptyList(); + open func getRuleContexts(_ ctxType: T.Type) -> [T] { + guard let children = children else { + return [T]() } - var contexts = Array() - for o: ParseTree in children { - if let o = o as? T { - contexts.append(o) - //contexts.(ctxType.cast(o)); - } - } - return contexts + return children.flatMap { $0 as? T } } override open func getChildCount() -> Int { - return children != nil ? children!.count : 0 + return children?.count ?? 0 } override open func getSourceInterval() -> Interval { - guard let start = start,let stop = stop else { + guard let start = start, let stop = stop else { return Interval.INVALID } return Interval.of(start.getTokenIndex(), stop.getTokenIndex()) @@ -324,10 +260,9 @@ open class ParserRuleContext: RuleContext { /// Used for rule context info debugging during parse-time, not so much for ATN debugging open func toInfoString(_ recognizer: Parser) -> String { - var rules: Array = recognizer.getRuleInvocationStack(self) - // Collections.reverse(rules); - rules = rules.reversed() - return "ParserRuleContext\(rules){start= + \(String(describing: start)), stop=\(String(describing: stop))}" - + let rules = Array(recognizer.getRuleInvocationStack(self).reversed()) + let startStr = start == nil ? "" : start!.description + let stopStr = stop == nil ? "" : stop!.description + return "ParserRuleContext\(rules){start=\(startStr)), stop=\(stopStr)}" } } diff --git a/runtime/Swift/Sources/Antlr4/tree/AbstractParseTreeVisitor.swift b/runtime/Swift/Sources/Antlr4/tree/AbstractParseTreeVisitor.swift index 689e2d7db..e4ed79946 100644 --- a/runtime/Swift/Sources/Antlr4/tree/AbstractParseTreeVisitor.swift +++ b/runtime/Swift/Sources/Antlr4/tree/AbstractParseTreeVisitor.swift @@ -7,11 +7,8 @@ open class AbstractParseTreeVisitor: ParseTreeVisitor { public override init() { super.init() - } - /// - /// /// /// The default implementation calls _org.antlr.v4.runtime.tree.ParseTree#accept_ on the /// specified tree. @@ -20,9 +17,7 @@ open class AbstractParseTreeVisitor: ParseTreeVisitor { return tree.accept(self) } - /// - /// - /// + /// /// The default implementation initializes the aggregate result to /// _#defaultResult defaultResult()_. Before visiting each child, it /// calls _#shouldVisitNextChild shouldVisitNextChild_; if the result @@ -37,24 +32,22 @@ open class AbstractParseTreeVisitor: ParseTreeVisitor { /// open override func visitChildren(_ node: RuleNode) -> T? { var result: T? = defaultResult() - let n: Int = node.getChildCount() + let n = node.getChildCount() for i in 0..: ParseTreeVisitor { return defaultResult() } - /// - /// - /// + /// /// The default implementation returns the result of /// _#defaultResult defaultResult_. /// diff --git a/runtime/Swift/Sources/Antlr4/tree/ParseTreeWalker.swift b/runtime/Swift/Sources/Antlr4/tree/ParseTreeWalker.swift index c93874561..f73f3217d 100644 --- a/runtime/Swift/Sources/Antlr4/tree/ParseTreeWalker.swift +++ b/runtime/Swift/Sources/Antlr4/tree/ParseTreeWalker.swift @@ -6,27 +6,28 @@ public class ParseTreeWalker { public static let DEFAULT = ParseTreeWalker() - public init() { + public init() { } public func walk(_ listener: ParseTreeListener, _ t: ParseTree) throws { - if t is ErrorNode { - listener.visitErrorNode(t as! ErrorNode) - return - } else { - if t is TerminalNode { - listener.visitTerminal(t as! TerminalNode) - return + if let errNode = t as? ErrorNode { + listener.visitErrorNode(errNode) + } + else if let termNode = t as? TerminalNode { + listener.visitTerminal(termNode) + } + else if let r = t as? RuleNode { + try enterRule(listener, r) + let n = r.getChildCount() + for i in 0..