forked from jasder/antlr
Merge pull request #1697 from hanjoes/master
Swift imple of #1665, #1674.
This commit is contained in:
commit
e04e7a40cc
|
@ -72,11 +72,12 @@ public protocol ANTLRErrorStrategy {
|
|||
/// the parsing process
|
||||
func sync(_ recognizer: Parser) throws // RecognitionException;
|
||||
|
||||
/// Tests whether or not {@code recognizer} is in the process of recovering
|
||||
/// Tests whether or not recognizer} is in the process of recovering
|
||||
/// from an error. In error recovery mode, {@link org.antlr.v4.runtime.Parser#consume} adds
|
||||
/// symbols to the parse tree by calling
|
||||
/// {@link org.antlr.v4.runtime.ParserRuleContext#addErrorNode(org.antlr.v4.runtime.Token)} instead of
|
||||
/// {@link org.antlr.v4.runtime.ParserRuleContext#addChild(org.antlr.v4.runtime.Token)}.
|
||||
/// {@link Parser#createErrorNode(ParserRuleContext, Token)} then
|
||||
/// {@link ParserRuleContext#addErrorNode(ErrorNode)} instead of
|
||||
/// {@link Parser#createTerminalNode(ParserRuleContext, Token)}.
|
||||
///
|
||||
/// - parameter recognizer: the parser instance
|
||||
/// - returns: {@code true} if the parser is currently recovering from a parse
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
/* Copyright (c) 2012-2016 The ANTLR Project. All rights reserved.
|
||||
* Use of this file is governed by the BSD 3-clause license that
|
||||
* can be found in the LICENSE.txt file in the project root.
|
||||
*/
|
||||
|
||||
|
||||
/** This is all the parsing support code essentially; most of it is error recovery stuff. */
|
||||
//public abstract class Parser : Recognizer<Token, ParserATNSimulator> {
|
||||
///
|
||||
/// Copyright (c) 2012-2016 The ANTLR Project. All rights reserved.
|
||||
/// Use of this file is governed by the BSD 3-clause license that
|
||||
/// can be found in the LICENSE.txt file in the project root.
|
||||
///
|
||||
|
||||
import Foundation
|
||||
|
||||
/// This is all the parsing support code essentially; most of it is error recovery stuff.
|
||||
open class Parser: Recognizer<ParserATNSimulator> {
|
||||
public static let EOF: Int = -1
|
||||
public static var ConsoleError = true
|
||||
//false
|
||||
|
||||
public class TraceListener: ParseTreeListener {
|
||||
var host: Parser
|
||||
|
@ -62,10 +59,7 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
|
||||
|
||||
public func exitEveryRule(_ ctx: ParserRuleContext) {
|
||||
//TODO: check necessary
|
||||
// if (ctx.children is ArrayList) {
|
||||
// (ctx.children as ArrayList<?>).trimToSize();
|
||||
// }
|
||||
// TODO: Print exit info.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,10 +69,8 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
*
|
||||
* @see org.antlr.v4.runtime.atn.ATNDeserializationOptions#isGenerateRuleBypassTransitions()
|
||||
*/
|
||||
//private let bypassAltsAtnCache : Dictionary<String, ATN> =
|
||||
// WeakHashMap<String, ATN>(); MapTable<NSString, ATN>
|
||||
|
||||
private let bypassAltsAtnCache: HashMap<String, ATN> = HashMap<String, ATN>()
|
||||
|
||||
/**
|
||||
* The error handling strategy for the parser. The default value is a new
|
||||
* instance of {@link org.antlr.v4.runtime.DefaultErrorStrategy}.
|
||||
|
@ -86,7 +78,6 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
* @see #getErrorHandler
|
||||
* @see #setErrorHandler
|
||||
*/
|
||||
|
||||
public var _errHandler: ANTLRErrorStrategy = DefaultErrorStrategy()
|
||||
|
||||
/**
|
||||
|
@ -177,14 +168,15 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
* strategy to attempt recovery. If {@link #getBuildParseTree} is
|
||||
* {@code true} and the token index of the symbol returned by
|
||||
* {@link org.antlr.v4.runtime.ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to
|
||||
* the parse tree by calling {@link org.antlr.v4.runtime.ParserRuleContext#addErrorNode}.</p>
|
||||
* the parse tree by calling {@link #createErrorNode(ParserRuleContext, Token)} then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)}.</p>
|
||||
*
|
||||
* @param ttype the token type to match
|
||||
* @return the matched symbol
|
||||
* @throws org.antlr.v4.runtime.RecognitionException if the current input symbol did not match
|
||||
* {@code ttype} and the error strategy could not recover from the
|
||||
* mismatched symbol
|
||||
*///; RecognitionException
|
||||
*/
|
||||
@discardableResult
|
||||
public func match(_ ttype: Int) throws -> Token {
|
||||
var t: Token = try getCurrentToken()
|
||||
|
@ -196,7 +188,7 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
if _buildParseTrees && t.getTokenIndex() == -1 {
|
||||
// we must have conjured up a new token during single token insertion
|
||||
// if it's not the current symbol
|
||||
_ctx!.addErrorNode(t)
|
||||
_ctx!.addErrorNode(createErrorNode(parent: _ctx!, t: t))
|
||||
}
|
||||
}
|
||||
return t
|
||||
|
@ -212,7 +204,8 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
* strategy to attempt recovery. If {@link #getBuildParseTree} is
|
||||
* {@code true} and the token index of the symbol returned by
|
||||
* {@link org.antlr.v4.runtime.ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to
|
||||
* the parse tree by calling {@link org.antlr.v4.runtime.ParserRuleContext#addErrorNode}.</p>
|
||||
* the parse tree by calling {@link #createErrorNode(ParserRuleContext, Token)} then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)}.</p>
|
||||
*
|
||||
* @return the matched symbol
|
||||
* @throws org.antlr.v4.runtime.RecognitionException if the current input symbol did not match
|
||||
|
@ -230,7 +223,7 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
if _buildParseTrees && t.getTokenIndex() == -1 {
|
||||
// we must have conjured up a new token during single token insertion
|
||||
// if it's not the current symbol
|
||||
_ctx!.addErrorNode(t)
|
||||
_ctx!.addErrorNode(createErrorNode(parent: _ctx!, t: t))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -562,11 +555,11 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
* </pre>
|
||||
*
|
||||
* If the parser is not in error recovery mode, the consumed symbol is added
|
||||
* to the parse tree using {@link org.antlr.v4.runtime.ParserRuleContext#addChild(org.antlr.v4.runtime.Token)}, and
|
||||
* to the parse tree using {@link ParserRuleContext#addChild(TerminalNode)}, and
|
||||
* {@link org.antlr.v4.runtime.tree.ParseTreeListener#visitTerminal} is called on any parse listeners.
|
||||
* If the parser <em>is</em> in error recovery mode, the consumed symbol is
|
||||
* added to the parse tree using
|
||||
* {@link org.antlr.v4.runtime.ParserRuleContext#addErrorNode(org.antlr.v4.runtime.Token)}, and
|
||||
* added to the parse tree using {@link #createErrorNode(ParserRuleContext, Token)} then
|
||||
* {@link ParserRuleContext#addErrorNode(ErrorNode)} and
|
||||
* {@link org.antlr.v4.runtime.tree.ParseTreeListener#visitErrorNode} is called on any parse
|
||||
* listeners.
|
||||
*/
|
||||
|
@ -583,14 +576,14 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
|
||||
if _buildParseTrees || hasListener {
|
||||
if _errHandler.inErrorRecoveryMode(self) {
|
||||
let node: ErrorNode = _ctx.addErrorNode(o)
|
||||
let node: ErrorNode = _ctx.addErrorNode(createErrorNode(parent: _ctx, t: o))
|
||||
if let _parseListeners = _parseListeners {
|
||||
for listener: ParseTreeListener in _parseListeners {
|
||||
listener.visitErrorNode(node)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let node: TerminalNode = _ctx.addChild(o)
|
||||
let node: TerminalNode = _ctx.addChild(createTerminalNode(parent: _ctx, t: o))
|
||||
if let _parseListeners = _parseListeners {
|
||||
for listener: ParseTreeListener in _parseListeners {
|
||||
listener.visitTerminal(node)
|
||||
|
@ -600,6 +593,24 @@ open class Parser: Recognizer<ParserATNSimulator> {
|
|||
}
|
||||
return o
|
||||
}
|
||||
|
||||
/** How to create a token leaf node associated with a parent.
|
||||
* 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 {
|
||||
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.
|
||||
*
|
||||
* @since 4.6.1
|
||||
*/
|
||||
public func createErrorNode(parent: ParserRuleContext, t: Token) -> ErrorNode {
|
||||
return ErrorNode(t);
|
||||
}
|
||||
|
||||
internal func addContextToParseTree() {
|
||||
|
||||
|
|
|
@ -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
|
||||
for child: ParseTree in ctx.children! {
|
||||
if child is ErrorNode {
|
||||
addChild(child as! ErrorNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,51 +112,90 @@ open class ParserRuleContext: RuleContext {
|
|||
open func exitRule(_ listener: ParseTreeListener) {
|
||||
}
|
||||
|
||||
/** Does not set parent link; other add methods do that */
|
||||
/** Add a parse tree node to this as a child. Works for
|
||||
* internal and leaf nodes. Does not set parent link;
|
||||
* other add methods must do that. Other addChild methods
|
||||
* call this.
|
||||
*
|
||||
* We cannot set the parent pointer of the incoming node
|
||||
* because the existing interfaces do not have a setParent()
|
||||
* method and I don't want to break backward compatibility for this.
|
||||
*
|
||||
* @since 4.6.1
|
||||
*/
|
||||
@discardableResult
|
||||
open func addChild(_ t: TerminalNode) -> TerminalNode {
|
||||
open func addAnyChild<T: ParseTree>(_ t: T) -> T {
|
||||
if children == nil {
|
||||
children = Array<ParseTree>()
|
||||
children = [T]()
|
||||
}
|
||||
children!.append(t)
|
||||
return t
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
open func addChild(_ ruleInvocation: RuleContext) -> RuleContext {
|
||||
if children == nil {
|
||||
children = Array<ParseTree>()
|
||||
}
|
||||
children!.append(ruleInvocation)
|
||||
return ruleInvocation
|
||||
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 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)
|
||||
}
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
@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
|
||||
* {@link 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
|
||||
* we entered a rule. If we have # label, we will need to remove
|
||||
* generic ruleContext object.
|
||||
*/
|
||||
*/
|
||||
open func removeLastChild() {
|
||||
children?.removeLast()
|
||||
//children.remove(children.size()-1);
|
||||
}
|
||||
|
||||
// public void trace(int s) {
|
||||
// if ( states==null ) states = new ArrayList<Integer>();
|
||||
// states.add(s);
|
||||
// }
|
||||
|
||||
open func addChild(_ matchedToken: Token) -> TerminalNode {
|
||||
let t: TerminalNodeImpl = TerminalNodeImpl(matchedToken)
|
||||
addChild(t)
|
||||
t.parent = self
|
||||
return t
|
||||
}
|
||||
@discardableResult
|
||||
open func addErrorNode(_ badToken: Token) -> ErrorNode {
|
||||
let t: ErrorNode = ErrorNode(badToken)
|
||||
addChild(t)
|
||||
t.parent = self
|
||||
return t
|
||||
if children != nil {
|
||||
children!.remove(at: children!.count-1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override
|
||||
/** Override to make type more specific */
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue