Tidy-ups inside the Swift runtime.

Change ParserRuleContext.exception to be RecognitionException?
rather than AnyObject!.  I don't know why it was declared that
way because the Java code uses RecognitionException.

Remove ParserRuleContext.addChild(Token) and addErrorNode(Token).
These are deprecated in the Java code and there was no need to
bring them over to the Swift runtime.

Fix ParserRuleContext.toInfoString, which was mangled when it was
ported from Java.

Various other tidyups: removal of useless type annotations, use of
if let, etc.
This commit is contained in:
Ewan Mellor 2017-11-06 23:34:19 -08:00
parent 5dd835f0a1
commit 8c2f80f1c7
No known key found for this signature in database
GPG Key ID: 7CE1C6BC9EC8645D
3 changed files with 67 additions and 140 deletions

View File

@ -28,13 +28,14 @@
/// ///
open class ParserRuleContext: RuleContext { open class ParserRuleContext: RuleContext {
public var visited = false public var visited = false
/// If we are debugging or building a parse tree for a visitor, /// If we are debugging or building a parse tree for a visitor,
/// we need to track all of the tokens and rule invocations associated /// 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. /// 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 /// operation because we don't the need to track the details about
/// how we parse this rule. /// how we parse this rule.
/// ///
public var children: Array<ParseTree>? public var children: [ParseTree]?
/// For debugging/tracing purposes, we want to track all of the nodes in /// For debugging/tracing purposes, we want to track all of the nodes in
/// the ATN traversed by the parser for a particular rule. /// 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 /// The exception that forced this rule to return. If the rule successfully
/// completed, this is `null`. /// completed, this is `null`.
/// ///
public var exception: AnyObject! public var exception: RecognitionException?
public override init() { public override init() {
super.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 /// 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.
/// ///
@ -80,26 +85,21 @@ open class ParserRuleContext: RuleContext {
open func copyFrom(_ ctx: ParserRuleContext) { open func copyFrom(_ ctx: ParserRuleContext) {
self.parent = ctx.parent self.parent = ctx.parent
self.invokingState = ctx.invokingState self.invokingState = ctx.invokingState
self.start = ctx.start self.start = ctx.start
self.stop = ctx.stop self.stop = ctx.stop
// copy any error nodes to alt label node // copy any error nodes to alt label node
if ctx.children != nil { if let ctxChildren = ctx.children {
self.children = Array<ParseTree>() self.children = [ParseTree]()
// reset parent pointer for any error nodes // reset parent pointer for any error nodes
for child: ParseTree in ctx.children! { for child in ctxChildren {
if child is ErrorNode { if let errNode = child as? ErrorNode {
addChild(child as! ErrorNode) addChild(errNode)
} }
} }
} }
} }
public init(_ parent: ParserRuleContext?, _ invokingStateNumber: Int) {
super.init(parent, invokingStateNumber)
}
// Double dispatch methods for listeners // Double dispatch methods for listeners
open func enterRule(_ listener: ParseTreeListener) { 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. /// Add an error node child and force its parent to be this node.
///
/// - Since: 4.7
///
@discardableResult @discardableResult
open func addErrorNode(_ errorNode: ErrorNode) -> ErrorNode { open func addErrorNode(_ errorNode: ErrorNode) -> ErrorNode {
errorNode.setParent(self) errorNode.setParent(self)
return addAnyChild(errorNode) 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<Integer>();
// states.add(s);
// }
/// Used by enterOuterAlt to toss out a RuleContext previously added as /// Used by enterOuterAlt to toss out a RuleContext previously added as
/// we entered a rule. If we have # label, we will need to remove /// we entered a rule. If we have # label, we will need to remove
/// generic ruleContext object. /// generic ruleContext object.
/// ///
open func removeLastChild() { open func removeLastChild() {
if children != nil { children?.removeLast()
children!.remove(at: children!.count-1)
}
} }
override
///
/// Override to make type more specific
///
open func getParent() -> Tree? {
return super.getParent()
}
override override
open func getChild(_ i: Int) -> Tree? { 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 nil
} }
return children[i] return children[i]
} }
open func getChild<T:ParseTree>(_ ctxType: T.Type, i: Int) -> T? { open func getChild<T: ParseTree>(_ ctxType: T.Type, i: Int) -> T? {
guard let children = children , i >= 0 && i < children.count else { guard let children = children, i >= 0 && i < children.count else {
return nil return nil
} }
var j: Int = -1 // what element have we found with ctxType? var j = -1 // what element have we found with ctxType?
for o: ParseTree in children { for o in children {
//if ( ctxType.isInstance(o) ) {
if let o = o as? T { if let o = o as? T {
j += 1 j += 1
if j == i { if j == i {
return o //ctxType.cast(o); return o
} }
} }
} }
return nil return nil
} }
open func getToken(_ ttype: Int, _ i: Int) -> TerminalNode? { 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 return nil
} }
var j: Int = -1 // what token with ttype have we found? var j = -1 // what token with ttype have we found?
for o: ParseTree in children{ for o in children {
if let tnode = o as? TerminalNode { if let tnode = o as? TerminalNode {
let symbol: Token = tnode.getSymbol()! let symbol = tnode.getSymbol()!
if symbol.getType() == ttype { if symbol.getType() == ttype {
j += 1 j += 1
if j == i { if j == i {
@ -246,60 +202,40 @@ open class ParserRuleContext: RuleContext {
return nil return nil
} }
open func getTokens(_ ttype: Int) -> Array<TerminalNode> { open func getTokens(_ ttype: Int) -> [TerminalNode] {
if children == nil { guard let children = children else {
return Array<TerminalNode>() return [TerminalNode]()
} }
var tokens: Array<TerminalNode>? = nil return children.flatMap {
for o: ParseTree in children! { if let tnode = $0 as? TerminalNode, let symbol = tnode.getSymbol(), symbol.getType() == ttype {
if o is TerminalNode { return tnode
let tnode: TerminalNode = o as! TerminalNode }
let symbol: Token = tnode.getSymbol()! else {
if symbol.getType() == ttype { return nil
if tokens == nil {
tokens = Array<TerminalNode>()
}
tokens?.append(tnode)
}
} }
} }
if tokens == nil {
return Array<TerminalNode>()
}
return tokens!
} }
open func getRuleContext<T:ParserRuleContext>(_ ctxType: T.Type, _ i: Int) -> T? { open func getRuleContext<T: ParserRuleContext>(_ ctxType: T.Type, _ i: Int) -> T? {
return getChild(ctxType, i: i) return getChild(ctxType, i: i)
} }
open func getRuleContexts<T:ParserRuleContext>(_ ctxType: T.Type) -> Array<T> { open func getRuleContexts<T: ParserRuleContext>(_ ctxType: T.Type) -> [T] {
guard let children = children else {
guard let children = children else { return [T]()
return Array<T>()//Collections.emptyList();
} }
var contexts = Array<T>() return children.flatMap { $0 as? T }
for o: ParseTree in children {
if let o = o as? T {
contexts.append(o)
//contexts.(ctxType.cast(o));
}
}
return contexts
} }
override override
open func getChildCount() -> Int { open func getChildCount() -> Int {
return children != nil ? children!.count : 0 return children?.count ?? 0
} }
override override
open func getSourceInterval() -> Interval { 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.INVALID
} }
return Interval.of(start.getTokenIndex(), stop.getTokenIndex()) 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 /// Used for rule context info debugging during parse-time, not so much for ATN debugging
open func toInfoString(_ recognizer: Parser) -> String { open func toInfoString(_ recognizer: Parser) -> String {
var rules: Array<String> = recognizer.getRuleInvocationStack(self) let rules = Array(recognizer.getRuleInvocationStack(self).reversed())
// Collections.reverse(rules); let startStr = start == nil ? "<unknown>" : start!.description
rules = rules.reversed() let stopStr = stop == nil ? "<unknown>" : stop!.description
return "ParserRuleContext\(rules){start= + \(String(describing: start)), stop=\(String(describing: stop))}" return "ParserRuleContext\(rules){start=\(startStr)), stop=\(stopStr)}"
} }
} }

View File

@ -7,11 +7,8 @@
open class AbstractParseTreeVisitor<T>: ParseTreeVisitor<T> { open class AbstractParseTreeVisitor<T>: ParseTreeVisitor<T> {
public override init() { public override init() {
super.init() super.init()
} }
///
///
/// ///
/// The default implementation calls _org.antlr.v4.runtime.tree.ParseTree#accept_ on the /// The default implementation calls _org.antlr.v4.runtime.tree.ParseTree#accept_ on the
/// specified tree. /// specified tree.
@ -20,9 +17,7 @@ open class AbstractParseTreeVisitor<T>: ParseTreeVisitor<T> {
return tree.accept(self) return tree.accept(self)
} }
/// ///
///
///
/// The default implementation initializes the aggregate result to /// The default implementation initializes the aggregate result to
/// _#defaultResult defaultResult()_. Before visiting each child, it /// _#defaultResult defaultResult()_. Before visiting each child, it
/// calls _#shouldVisitNextChild shouldVisitNextChild_; if the result /// calls _#shouldVisitNextChild shouldVisitNextChild_; if the result
@ -37,24 +32,22 @@ open class AbstractParseTreeVisitor<T>: ParseTreeVisitor<T> {
/// ///
open override func visitChildren(_ node: RuleNode) -> T? { open override func visitChildren(_ node: RuleNode) -> T? {
var result: T? = defaultResult() var result: T? = defaultResult()
let n: Int = node.getChildCount() let n = node.getChildCount()
for i in 0..<n { for i in 0..<n {
if !shouldVisitNextChild(node, result) { if !shouldVisitNextChild(node, result) {
break break
} }
let c: ParseTree? = node.getChild(i) as? ParseTree let c = node.getChild(i) as? ParseTree
let childResult: T? = c?.accept(self) let childResult = c?.accept(self)
result = aggregateResult(result, childResult) result = aggregateResult(result, childResult)
} }
return result return result
} }
/// ///
///
///
/// The default implementation returns the result of /// The default implementation returns the result of
/// _#defaultResult defaultResult_. /// _#defaultResult defaultResult_.
/// ///
@ -62,9 +55,7 @@ open class AbstractParseTreeVisitor<T>: ParseTreeVisitor<T> {
return defaultResult() return defaultResult()
} }
/// ///
///
///
/// The default implementation returns the result of /// The default implementation returns the result of
/// _#defaultResult defaultResult_. /// _#defaultResult defaultResult_.
/// ///

View File

@ -6,27 +6,28 @@
public class ParseTreeWalker { public class ParseTreeWalker {
public static let DEFAULT = ParseTreeWalker() public static let DEFAULT = ParseTreeWalker()
public init() {
public init() {
} }
public func walk(_ listener: ParseTreeListener, _ t: ParseTree) throws { public func walk(_ listener: ParseTreeListener, _ t: ParseTree) throws {
if t is ErrorNode { if let errNode = t as? ErrorNode {
listener.visitErrorNode(t as! ErrorNode) listener.visitErrorNode(errNode)
return }
} else { else if let termNode = t as? TerminalNode {
if t is TerminalNode { listener.visitTerminal(termNode)
listener.visitTerminal(t as! TerminalNode) }
return else if let r = t as? RuleNode {
try enterRule(listener, r)
let n = r.getChildCount()
for i in 0..<n {
try walk(listener, r.getChild(i) as! ParseTree)
} }
try exitRule(listener, r)
} }
let r: RuleNode = t as! RuleNode else {
try enterRule(listener, r) preconditionFailure()
let n: Int = r.getChildCount()
for i in 0..<n {
try walk(listener, r.getChild(i) as! ParseTree)
} }
try exitRule(listener, r)
} }
/// ///
@ -36,13 +37,13 @@ public class ParseTreeWalker {
/// the rule specific. We to them in reverse order upon finishing the node. /// the rule specific. We to them in reverse order upon finishing the node.
/// ///
internal func enterRule(_ listener: ParseTreeListener, _ r: RuleNode) throws { internal func enterRule(_ listener: ParseTreeListener, _ r: RuleNode) throws {
let ctx: ParserRuleContext = r.getRuleContext() as! ParserRuleContext let ctx = r.getRuleContext() as! ParserRuleContext
try listener.enterEveryRule(ctx) try listener.enterEveryRule(ctx)
ctx.enterRule(listener) ctx.enterRule(listener)
} }
internal func exitRule(_ listener: ParseTreeListener, _ r: RuleNode) throws { internal func exitRule(_ listener: ParseTreeListener, _ r: RuleNode) throws {
let ctx: ParserRuleContext = r.getRuleContext() as! ParserRuleContext let ctx = r.getRuleContext() as! ParserRuleContext
ctx.exitRule(listener) ctx.exitRule(listener)
try listener.exitEveryRule(ctx) try listener.exitEveryRule(ctx)
} }