Tidy up the exception handling around RecognitionException.
This removes the generic parameter on RecognitionException, to make it easier to handle them. This means that we no longer need to store them as AnyObject and cast them back again. To do this, we add RecognizerProtocol, which is a non-generic equivalent of the Recognizer interface (at least, the parts of it that we need for error handling). Remove all paths where the RecognitionException subclasses were throwing exceptions in their initializers. This is just insane.
This commit is contained in:
parent
7e03b0857a
commit
fbe8c0d2a6
|
@ -63,7 +63,7 @@ public protocol ANTLRErrorStrategy {
|
||||||
/// - throws: _RecognitionException_ if the error strategy could not recover from
|
/// - throws: _RecognitionException_ if the error strategy could not recover from
|
||||||
/// the recognition exception
|
/// the recognition exception
|
||||||
///
|
///
|
||||||
func recover(_ recognizer: Parser, _ e: AnyObject) throws
|
func recover(_ recognizer: Parser, _ e: RecognitionException) throws
|
||||||
|
|
||||||
///
|
///
|
||||||
/// This method provides the error handler with an opportunity to handle
|
/// This method provides the error handler with an opportunity to handle
|
||||||
|
@ -115,5 +115,5 @@ public protocol ANTLRErrorStrategy {
|
||||||
/// - parameter recognizer: the parser instance
|
/// - parameter recognizer: the parser instance
|
||||||
/// - parameter e: the recognition exception to report
|
/// - parameter e: the recognition exception to report
|
||||||
///
|
///
|
||||||
func reportError(_ recognizer: Parser, _ e: AnyObject)
|
func reportError(_ recognizer: Parser, _ e: RecognitionException)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class BailErrorStrategy: DefaultErrorStrategy {
|
||||||
/// rule function catches. Use _Exception#getCause()_ to get the
|
/// rule function catches. Use _Exception#getCause()_ to get the
|
||||||
/// original _org.antlr.v4.runtime.RecognitionException_.
|
/// original _org.antlr.v4.runtime.RecognitionException_.
|
||||||
///
|
///
|
||||||
override public func recover(_ recognizer: Parser, _ e: AnyObject) throws {
|
override public func recover(_ recognizer: Parser, _ e: RecognitionException) throws {
|
||||||
var context = recognizer.getContext()
|
var context = recognizer.getContext()
|
||||||
while let contextWrap = context {
|
while let contextWrap = context {
|
||||||
contextWrap.exception = e
|
contextWrap.exception = e
|
||||||
|
@ -56,7 +56,7 @@ public class BailErrorStrategy: DefaultErrorStrategy {
|
||||||
///
|
///
|
||||||
override
|
override
|
||||||
public func recoverInline(_ recognizer: Parser) throws -> Token {
|
public func recoverInline(_ recognizer: Parser) throws -> Token {
|
||||||
let e = try InputMismatchException(recognizer)
|
let e = InputMismatchException(recognizer)
|
||||||
var context = recognizer.getContext()
|
var context = recognizer.getContext()
|
||||||
while let contextWrap = context {
|
while let contextWrap = context {
|
||||||
contextWrap.exception = e
|
contextWrap.exception = e
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
||||||
/// the exception
|
/// the exception
|
||||||
///
|
///
|
||||||
public func reportError(_ recognizer: Parser,
|
public func reportError(_ recognizer: Parser,
|
||||||
_ e: AnyObject) {
|
_ e: RecognitionException) {
|
||||||
// if we've already reported an error and have not matched a token
|
// if we've already reported an error and have not matched a token
|
||||||
// yet successfully, don't report any errors.
|
// yet successfully, don't report any errors.
|
||||||
if inErrorRecoveryMode(recognizer) {
|
if inErrorRecoveryMode(recognizer) {
|
||||||
|
@ -109,8 +109,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errPrint("unknown recognition error type: " + String(describing: type(of: e)))
|
errPrint("unknown recognition error type: " + String(describing: type(of: e)))
|
||||||
let re = (e as! RecognitionException<ParserATNSimulator>)
|
recognizer.notifyErrorListeners(e.getOffendingToken(), e.message ?? "", e)
|
||||||
recognizer.notifyErrorListeners(re.getOffendingToken(), re.message ?? "", e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +118,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
||||||
/// until we find one in the resynchronization set--loosely the set of tokens
|
/// until we find one in the resynchronization set--loosely the set of tokens
|
||||||
/// that can follow the current rule.
|
/// that can follow the current rule.
|
||||||
///
|
///
|
||||||
public func recover(_ recognizer: Parser, _ e: AnyObject) throws {
|
public func recover(_ recognizer: Parser, _ e: RecognitionException) throws {
|
||||||
// print("recover in "+recognizer.getRuleInvocationStack()+
|
// print("recover in "+recognizer.getRuleInvocationStack()+
|
||||||
// " index="+getTokenStream(recognizer).index()+
|
// " index="+getTokenStream(recognizer).index()+
|
||||||
// ", lastErrorIndex="+
|
// ", lastErrorIndex="+
|
||||||
|
@ -219,7 +218,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
||||||
if try singleTokenDeletion(recognizer) != nil {
|
if try singleTokenDeletion(recognizer) != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw try ANTLRException.recognition(e: InputMismatchException(recognizer))
|
throw ANTLRException.recognition(e: InputMismatchException(recognizer))
|
||||||
|
|
||||||
case ATNState.PLUS_LOOP_BACK: fallthrough
|
case ATNState.PLUS_LOOP_BACK: fallthrough
|
||||||
case ATNState.STAR_LOOP_BACK:
|
case ATNState.STAR_LOOP_BACK:
|
||||||
|
@ -418,11 +417,8 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
||||||
if try singleTokenInsertion(recognizer) {
|
if try singleTokenInsertion(recognizer) {
|
||||||
return try getMissingSymbol(recognizer)
|
return try getMissingSymbol(recognizer)
|
||||||
}
|
}
|
||||||
throw try ANTLRException.recognition(e: InputMismatchException(recognizer))
|
|
||||||
// throw try ANTLRException.InputMismatch(e: InputMismatchException(recognizer) )
|
|
||||||
//RuntimeException("InputMismatchException")
|
|
||||||
// even that didn't work; must throw the exception
|
// even that didn't work; must throw the exception
|
||||||
//throwException() /* throw InputMismatchException(recognizer); */
|
throw ANTLRException.recognition(e: InputMismatchException(recognizer))
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
|
@ -11,23 +11,12 @@
|
||||||
/// Disambiguating predicate evaluation occurs when we test a predicate during
|
/// Disambiguating predicate evaluation occurs when we test a predicate during
|
||||||
/// prediction.
|
/// prediction.
|
||||||
///
|
///
|
||||||
public class FailedPredicateException: RecognitionException<ParserATNSimulator> {
|
public class FailedPredicateException: RecognitionException {
|
||||||
private final var ruleIndex: Int
|
private final var ruleIndex: Int
|
||||||
private final var predicateIndex: Int
|
private final var predicateIndex: Int
|
||||||
private final var predicate: String?
|
private final var predicate: String?
|
||||||
|
|
||||||
public convenience init(_ recognizer: Parser) throws {
|
public init(_ recognizer: Parser, _ predicate: String? = nil, _ message: String? = nil) {
|
||||||
try self.init(recognizer, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
public convenience init(_ recognizer: Parser, _ predicate: String?)throws {
|
|
||||||
try self.init(recognizer, predicate, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(_ recognizer: Parser,
|
|
||||||
_ predicate: String?,
|
|
||||||
_ message: String?) throws
|
|
||||||
{
|
|
||||||
let s = recognizer.getInterpreter().atn.states[recognizer.getState()]!
|
let s = recognizer.getInterpreter().atn.states[recognizer.getState()]!
|
||||||
|
|
||||||
let trans = s.transition(0) as! AbstractPredicateTransition
|
let trans = s.transition(0) as! AbstractPredicateTransition
|
||||||
|
@ -42,9 +31,10 @@ public class FailedPredicateException: RecognitionException<ParserATNSimulator>
|
||||||
|
|
||||||
self.predicate = predicate
|
self.predicate = predicate
|
||||||
|
|
||||||
super.init(FailedPredicateException.formatMessage(predicate!, message), recognizer , recognizer.getInputStream()!, recognizer._ctx)
|
super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx, FailedPredicateException.formatMessage(predicate, message))
|
||||||
|
if let token = try? recognizer.getCurrentToken() {
|
||||||
try self.setOffendingToken(recognizer.getCurrentToken())
|
setOffendingToken(token)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getRuleIndex() -> Int {
|
public func getRuleIndex() -> Int {
|
||||||
|
@ -60,11 +50,12 @@ public class FailedPredicateException: RecognitionException<ParserATNSimulator>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static func formatMessage(_ predicate: String, _ message: String?) -> String {
|
private static func formatMessage(_ predicate: String?, _ message: String?) -> String {
|
||||||
if message != nil {
|
if message != nil {
|
||||||
return message!
|
return message!
|
||||||
}
|
}
|
||||||
|
|
||||||
return "failed predicate: {predicate}?" //String.format(Locale.getDefault(), "failed predicate: {%s}?", predicate);
|
let predstr = predicate ?? "<unknown>"
|
||||||
|
return "failed predicate: {\(predstr)}?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
/// when the current input does not match the expected token.
|
/// when the current input does not match the expected token.
|
||||||
///
|
///
|
||||||
|
|
||||||
public class InputMismatchException: RecognitionException<ParserATNSimulator> {
|
public class InputMismatchException: RecognitionException {
|
||||||
public init(_ recognizer: Parser) throws {
|
public init(_ recognizer: Parser) {
|
||||||
super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx)
|
super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx)
|
||||||
self.setOffendingToken(try recognizer.getCurrentToken())
|
if let token = try? recognizer.getCurrentToken() {
|
||||||
|
setOffendingToken(token)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
public class LexerNoViableAltException: RecognitionException<LexerATNSimulator>, CustomStringConvertible {
|
public class LexerNoViableAltException: RecognitionException, CustomStringConvertible {
|
||||||
///
|
///
|
||||||
/// Matching attempted at what input index?
|
/// Matching attempted at what input index?
|
||||||
///
|
///
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
/// in the various paths when the error. Reported by reportNoViableAlternative()
|
/// in the various paths when the error. Reported by reportNoViableAlternative()
|
||||||
///
|
///
|
||||||
|
|
||||||
public class NoViableAltException: RecognitionException<ParserATNSimulator> {
|
public class NoViableAltException: RecognitionException {
|
||||||
/// Which configurations did we try at input.index() that couldn't match input.LT(1)?
|
/// Which configurations did we try at input.index() that couldn't match input.LT(1)?
|
||||||
|
|
||||||
private final var deadEndConfigs: ATNConfigSet?
|
private final var deadEndConfigs: ATNConfigSet?
|
||||||
|
@ -22,14 +22,15 @@ public class NoViableAltException: RecognitionException<ParserATNSimulator> {
|
||||||
///
|
///
|
||||||
private final var startToken: Token
|
private final var startToken: Token
|
||||||
|
|
||||||
public convenience init(_ recognizer: Parser?) throws {
|
public convenience init(_ recognizer: Parser) {
|
||||||
// LL(1) error
|
// LL(1) error
|
||||||
|
let token = try! recognizer.getCurrentToken()
|
||||||
self.init(recognizer,
|
self.init(recognizer,
|
||||||
recognizer!.getInputStream()!,
|
recognizer.getInputStream()!,
|
||||||
try recognizer!.getCurrentToken(),
|
token,
|
||||||
try recognizer!.getCurrentToken(),
|
token,
|
||||||
nil,
|
nil,
|
||||||
recognizer!._ctx)
|
recognizer._ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ recognizer: Parser?,
|
public init(_ recognizer: Parser?,
|
||||||
|
@ -42,7 +43,6 @@ public class NoViableAltException: RecognitionException<ParserATNSimulator> {
|
||||||
self.deadEndConfigs = deadEndConfigs
|
self.deadEndConfigs = deadEndConfigs
|
||||||
self.startToken = startToken
|
self.startToken = startToken
|
||||||
|
|
||||||
// as? Recognizer<AnyObject, ATNSimulator>
|
|
||||||
super.init(recognizer, input, ctx)
|
super.init(recognizer, input, ctx)
|
||||||
self.setOffendingToken(offendingToken)
|
self.setOffendingToken(offendingToken)
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,11 +237,8 @@ public class ParserInterpreter: Parser {
|
||||||
case Transition.PREDICATE:
|
case Transition.PREDICATE:
|
||||||
let predicateTransition = transition as! PredicateTransition
|
let predicateTransition = transition as! PredicateTransition
|
||||||
if try !sempred(_ctx!, predicateTransition.ruleIndex, predicateTransition.predIndex) {
|
if try !sempred(_ctx!, predicateTransition.ruleIndex, predicateTransition.predIndex) {
|
||||||
|
throw ANTLRException.recognition(e: FailedPredicateException(self))
|
||||||
throw try ANTLRException.recognition(e: FailedPredicateException(self))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case Transition.ACTION:
|
case Transition.ACTION:
|
||||||
|
@ -251,9 +248,7 @@ public class ParserInterpreter: Parser {
|
||||||
|
|
||||||
case Transition.PRECEDENCE:
|
case Transition.PRECEDENCE:
|
||||||
if !precpred(_ctx!, (transition as! PrecedencePredicateTransition).precedence) {
|
if !precpred(_ctx!, (transition as! PrecedencePredicateTransition).precedence) {
|
||||||
|
throw ANTLRException.recognition(e: FailedPredicateException(self, "precpred(_ctx,\((transition as! PrecedencePredicateTransition).precedence))"))
|
||||||
throw try ANTLRException.recognition(e: FailedPredicateException(self, "precpred(_ctx,\((transition as! PrecedencePredicateTransition).precedence))"))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,11 @@
|
||||||
/// and what kind of problem occurred.
|
/// and what kind of problem occurred.
|
||||||
///
|
///
|
||||||
|
|
||||||
public class RecognitionException<T:ATNSimulator> {
|
public class RecognitionException {
|
||||||
///
|
///
|
||||||
/// The _org.antlr.v4.runtime.Recognizer_ where this exception originated.
|
/// The _org.antlr.v4.runtime.Recognizer_ where this exception originated.
|
||||||
///
|
///
|
||||||
private final var recognizer: Recognizer<T>?
|
private final var recognizer: RecognizerProtocol?
|
||||||
//Recognizer<AnyObject,ATNSimulator>? ;
|
|
||||||
|
|
||||||
private final let ctx: RuleContext?
|
private final let ctx: RuleContext?
|
||||||
|
|
||||||
|
@ -32,25 +31,15 @@ public class RecognitionException<T:ATNSimulator> {
|
||||||
private var offendingState = -1
|
private var offendingState = -1
|
||||||
|
|
||||||
public var message: String?
|
public var message: String?
|
||||||
public init(_ recognizer: Recognizer<T>?,
|
|
||||||
_ input: IntStream,
|
|
||||||
_ ctx: ParserRuleContext?) {
|
|
||||||
self.recognizer = recognizer
|
|
||||||
self.input = input
|
|
||||||
self.ctx = ctx
|
|
||||||
if let recognizer = recognizer {
|
|
||||||
self.offendingState = recognizer.getState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(_ message: String,
|
public init(_ recognizer: RecognizerProtocol?,
|
||||||
_ recognizer: Recognizer<T>?,
|
|
||||||
_ input: IntStream,
|
_ input: IntStream,
|
||||||
_ ctx: ParserRuleContext?) {
|
_ ctx: ParserRuleContext? = nil,
|
||||||
self.message = message
|
_ message: String? = nil) {
|
||||||
self.recognizer = recognizer
|
self.recognizer = recognizer
|
||||||
self.input = input
|
self.input = input
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
|
self.message = message
|
||||||
if let recognizer = recognizer {
|
if let recognizer = recognizer {
|
||||||
self.offendingState = recognizer.getState()
|
self.offendingState = recognizer.getState()
|
||||||
}
|
}
|
||||||
|
@ -87,7 +76,6 @@ public class RecognitionException<T:ATNSimulator> {
|
||||||
if let recognizer = recognizer {
|
if let recognizer = recognizer {
|
||||||
return try? recognizer.getATN().getExpectedTokens(offendingState, ctx!)
|
return try? recognizer.getATN().getExpectedTokens(offendingState, ctx!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +122,7 @@ public class RecognitionException<T:ATNSimulator> {
|
||||||
/// - Returns: The recognizer where this exception occurred, or `null` if
|
/// - Returns: The recognizer where this exception occurred, or `null` if
|
||||||
/// the recognizer is not available.
|
/// the recognizer is not available.
|
||||||
///
|
///
|
||||||
public func getRecognizer() -> Recognizer<T>? {
|
public func getRecognizer() -> RecognizerProtocol? {
|
||||||
return recognizer
|
return recognizer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,25 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
open class Recognizer<ATNInterpreter:ATNSimulator> {
|
|
||||||
|
public protocol RecognizerProtocol {
|
||||||
|
func getATN() -> ATN
|
||||||
|
func getGrammarFileName() -> String
|
||||||
|
func getParseInfo() -> ParseInfo?
|
||||||
|
func getRuleNames() -> [String]
|
||||||
|
func getSerializedATN() -> String
|
||||||
|
func getState() -> Int
|
||||||
|
func getTokenType(_ tokenName: String) -> Int
|
||||||
|
func getVocabulary() -> Vocabulary
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open class Recognizer<ATNInterpreter: ATNSimulator>: RecognizerProtocol {
|
||||||
//TODO: WeakKeyDictionary NSMapTable Dictionary MapTable<Vocabulary,HashMap<String, Int>>
|
//TODO: WeakKeyDictionary NSMapTable Dictionary MapTable<Vocabulary,HashMap<String, Int>>
|
||||||
private let tokenTypeMapCache = HashMap<Vocabulary, [String : Int]>()
|
private let tokenTypeMapCache = HashMap<Vocabulary, [String : Int]>()
|
||||||
|
|
||||||
private let ruleIndexMapCache = HashMap<ArrayWrapper<String>, [String : Int]>()
|
private let ruleIndexMapCache = HashMap<ArrayWrapper<String>, [String : Int]>()
|
||||||
|
|
||||||
|
|
||||||
private var _listeners: [ANTLRErrorListener] = [ConsoleErrorListener.INSTANCE]
|
private var _listeners: [ANTLRErrorListener] = [ConsoleErrorListener.INSTANCE]
|
||||||
|
|
||||||
public var _interp: ATNInterpreter!
|
public var _interp: ATNInterpreter!
|
||||||
|
@ -151,8 +163,8 @@ open class Recognizer<ATNInterpreter:ATNSimulator> {
|
||||||
///
|
///
|
||||||
/// What is the error header, normally line/character position information?
|
/// What is the error header, normally line/character position information?
|
||||||
///
|
///
|
||||||
open func getErrorHeader(_ e: AnyObject) -> String {
|
open func getErrorHeader(_ e: RecognitionException) -> String {
|
||||||
let offending = (e as! RecognitionException).getOffendingToken()
|
let offending = e.getOffendingToken()
|
||||||
let line = offending.getLine()
|
let line = offending.getLine()
|
||||||
let charPositionInLine = offending.getCharPositionInLine()
|
let charPositionInLine = offending.getCharPositionInLine()
|
||||||
return "line \(line):\(charPositionInLine)"
|
return "line \(line):\(charPositionInLine)"
|
||||||
|
|
|
@ -16,5 +16,5 @@ import Foundation
|
||||||
|
|
||||||
public enum ANTLRException: Error {
|
public enum ANTLRException: Error {
|
||||||
case cannotInvokeStartRule
|
case cannotInvokeStartRule
|
||||||
case recognition(e:AnyObject)
|
case recognition(e: RecognitionException)
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,7 +589,7 @@ case <i><if(!choice.ast.greedy)>+1<endif>:
|
||||||
|
|
||||||
Sync(s) ::= "sync(<s.expecting.name>);"
|
Sync(s) ::= "sync(<s.expecting.name>);"
|
||||||
|
|
||||||
ThrowNoViableAlt(t) ::= "throw try ANTLRException.recognition(e: NoViableAltException(self))"
|
ThrowNoViableAlt(t) ::= "throw ANTLRException.recognition(e: NoViableAltException(self))"
|
||||||
|
|
||||||
TestSetInline(s) ::= <<
|
TestSetInline(s) ::= <<
|
||||||
<!<s.bitsets:{bits | <if(rest(rest(bits.ttypes)))><bitsetBitfieldComparison(s, bits)><else><bitsetInlineComparison(s, bits)><endif>}; separator=" || ">!>
|
<!<s.bitsets:{bits | <if(rest(rest(bits.ttypes)))><bitsetBitfieldComparison(s, bits)><else><bitsetInlineComparison(s, bits)><endif>}; separator=" || ">!>
|
||||||
|
@ -694,7 +694,7 @@ ArgAction(a, chunks) ::= "<chunks>"
|
||||||
SemPred(p, chunks, failChunks) ::= <<
|
SemPred(p, chunks, failChunks) ::= <<
|
||||||
setState(<p.stateNumber>)
|
setState(<p.stateNumber>)
|
||||||
if (!(<chunks>)) {
|
if (!(<chunks>)) {
|
||||||
throw try ANTLRException.recognition(e:FailedPredicateException(self, <p.predicate><if(failChunks)>, <failChunks><elseif(p.msg)>, <p.msg><endif>))
|
throw ANTLRException.recognition(e:FailedPredicateException(self, <p.predicate><if(failChunks)>, <failChunks><elseif(p.msg)>, <p.msg><endif>))
|
||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue