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
|
||||
/// 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
|
||||
|
@ -115,5 +115,5 @@ public protocol ANTLRErrorStrategy {
|
|||
/// - parameter recognizer: the parser instance
|
||||
/// - 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
|
||||
/// 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()
|
||||
while let contextWrap = context {
|
||||
contextWrap.exception = e
|
||||
|
@ -56,7 +56,7 @@ public class BailErrorStrategy: DefaultErrorStrategy {
|
|||
///
|
||||
override
|
||||
public func recoverInline(_ recognizer: Parser) throws -> Token {
|
||||
let e = try InputMismatchException(recognizer)
|
||||
let e = InputMismatchException(recognizer)
|
||||
var context = recognizer.getContext()
|
||||
while let contextWrap = context {
|
||||
contextWrap.exception = e
|
||||
|
|
|
@ -90,7 +90,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
|||
/// the exception
|
||||
///
|
||||
public func reportError(_ recognizer: Parser,
|
||||
_ e: AnyObject) {
|
||||
_ e: RecognitionException) {
|
||||
// if we've already reported an error and have not matched a token
|
||||
// yet successfully, don't report any errors.
|
||||
if inErrorRecoveryMode(recognizer) {
|
||||
|
@ -109,8 +109,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
|||
}
|
||||
else {
|
||||
errPrint("unknown recognition error type: " + String(describing: type(of: e)))
|
||||
let re = (e as! RecognitionException<ParserATNSimulator>)
|
||||
recognizer.notifyErrorListeners(re.getOffendingToken(), re.message ?? "", e)
|
||||
recognizer.notifyErrorListeners(e.getOffendingToken(), e.message ?? "", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +118,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
|||
/// until we find one in the resynchronization set--loosely the set of tokens
|
||||
/// 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()+
|
||||
// " index="+getTokenStream(recognizer).index()+
|
||||
// ", lastErrorIndex="+
|
||||
|
@ -219,7 +218,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
|||
if try singleTokenDeletion(recognizer) != nil {
|
||||
return
|
||||
}
|
||||
throw try ANTLRException.recognition(e: InputMismatchException(recognizer))
|
||||
throw ANTLRException.recognition(e: InputMismatchException(recognizer))
|
||||
|
||||
case ATNState.PLUS_LOOP_BACK: fallthrough
|
||||
case ATNState.STAR_LOOP_BACK:
|
||||
|
@ -418,11 +417,8 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy {
|
|||
if try singleTokenInsertion(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
|
||||
//throwException() /* throw InputMismatchException(recognizer); */
|
||||
throw ANTLRException.recognition(e: InputMismatchException(recognizer))
|
||||
}
|
||||
|
||||
///
|
||||
|
|
|
@ -11,23 +11,12 @@
|
|||
/// Disambiguating predicate evaluation occurs when we test a predicate during
|
||||
/// prediction.
|
||||
///
|
||||
public class FailedPredicateException: RecognitionException<ParserATNSimulator> {
|
||||
public class FailedPredicateException: RecognitionException {
|
||||
private final var ruleIndex: Int
|
||||
private final var predicateIndex: Int
|
||||
private final var predicate: String?
|
||||
|
||||
public convenience init(_ recognizer: Parser) throws {
|
||||
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
|
||||
{
|
||||
public init(_ recognizer: Parser, _ predicate: String? = nil, _ message: String? = nil) {
|
||||
let s = recognizer.getInterpreter().atn.states[recognizer.getState()]!
|
||||
|
||||
let trans = s.transition(0) as! AbstractPredicateTransition
|
||||
|
@ -42,9 +31,10 @@ public class FailedPredicateException: RecognitionException<ParserATNSimulator>
|
|||
|
||||
self.predicate = predicate
|
||||
|
||||
super.init(FailedPredicateException.formatMessage(predicate!, message), recognizer , recognizer.getInputStream()!, recognizer._ctx)
|
||||
|
||||
try self.setOffendingToken(recognizer.getCurrentToken())
|
||||
super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx, FailedPredicateException.formatMessage(predicate, message))
|
||||
if let token = try? recognizer.getCurrentToken() {
|
||||
setOffendingToken(token)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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.
|
||||
///
|
||||
|
||||
public class InputMismatchException: RecognitionException<ParserATNSimulator> {
|
||||
public init(_ recognizer: Parser) throws {
|
||||
public class InputMismatchException: RecognitionException {
|
||||
public init(_ recognizer: Parser) {
|
||||
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?
|
||||
///
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
/// 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)?
|
||||
|
||||
private final var deadEndConfigs: ATNConfigSet?
|
||||
|
@ -22,14 +22,15 @@ public class NoViableAltException: RecognitionException<ParserATNSimulator> {
|
|||
///
|
||||
private final var startToken: Token
|
||||
|
||||
public convenience init(_ recognizer: Parser?) throws {
|
||||
public convenience init(_ recognizer: Parser) {
|
||||
// LL(1) error
|
||||
let token = try! recognizer.getCurrentToken()
|
||||
self.init(recognizer,
|
||||
recognizer!.getInputStream()!,
|
||||
try recognizer!.getCurrentToken(),
|
||||
try recognizer!.getCurrentToken(),
|
||||
recognizer.getInputStream()!,
|
||||
token,
|
||||
token,
|
||||
nil,
|
||||
recognizer!._ctx)
|
||||
recognizer._ctx)
|
||||
}
|
||||
|
||||
public init(_ recognizer: Parser?,
|
||||
|
@ -42,7 +43,6 @@ public class NoViableAltException: RecognitionException<ParserATNSimulator> {
|
|||
self.deadEndConfigs = deadEndConfigs
|
||||
self.startToken = startToken
|
||||
|
||||
// as? Recognizer<AnyObject, ATNSimulator>
|
||||
super.init(recognizer, input, ctx)
|
||||
self.setOffendingToken(offendingToken)
|
||||
}
|
||||
|
|
|
@ -237,11 +237,8 @@ public class ParserInterpreter: Parser {
|
|||
case Transition.PREDICATE:
|
||||
let predicateTransition = transition as! PredicateTransition
|
||||
if try !sempred(_ctx!, predicateTransition.ruleIndex, predicateTransition.predIndex) {
|
||||
|
||||
throw try ANTLRException.recognition(e: FailedPredicateException(self))
|
||||
|
||||
throw ANTLRException.recognition(e: FailedPredicateException(self))
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
case Transition.ACTION:
|
||||
|
@ -251,9 +248,7 @@ public class ParserInterpreter: Parser {
|
|||
|
||||
case Transition.PRECEDENCE:
|
||||
if !precpred(_ctx!, (transition as! PrecedencePredicateTransition).precedence) {
|
||||
|
||||
throw try ANTLRException.recognition(e: FailedPredicateException(self, "precpred(_ctx,\((transition as! PrecedencePredicateTransition).precedence))"))
|
||||
|
||||
throw ANTLRException.recognition(e: FailedPredicateException(self, "precpred(_ctx,\((transition as! PrecedencePredicateTransition).precedence))"))
|
||||
}
|
||||
break
|
||||
|
||||
|
|
|
@ -11,12 +11,11 @@
|
|||
/// and what kind of problem occurred.
|
||||
///
|
||||
|
||||
public class RecognitionException<T:ATNSimulator> {
|
||||
public class RecognitionException {
|
||||
///
|
||||
/// The _org.antlr.v4.runtime.Recognizer_ where this exception originated.
|
||||
///
|
||||
private final var recognizer: Recognizer<T>?
|
||||
//Recognizer<AnyObject,ATNSimulator>? ;
|
||||
private final var recognizer: RecognizerProtocol?
|
||||
|
||||
private final let ctx: RuleContext?
|
||||
|
||||
|
@ -32,25 +31,15 @@ public class RecognitionException<T:ATNSimulator> {
|
|||
private var offendingState = -1
|
||||
|
||||
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,
|
||||
_ recognizer: Recognizer<T>?,
|
||||
public init(_ recognizer: RecognizerProtocol?,
|
||||
_ input: IntStream,
|
||||
_ ctx: ParserRuleContext?) {
|
||||
self.message = message
|
||||
_ ctx: ParserRuleContext? = nil,
|
||||
_ message: String? = nil) {
|
||||
self.recognizer = recognizer
|
||||
self.input = input
|
||||
self.ctx = ctx
|
||||
self.message = message
|
||||
if let recognizer = recognizer {
|
||||
self.offendingState = recognizer.getState()
|
||||
}
|
||||
|
@ -87,7 +76,6 @@ public class RecognitionException<T:ATNSimulator> {
|
|||
if let recognizer = recognizer {
|
||||
return try? recognizer.getATN().getExpectedTokens(offendingState, ctx!)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -134,7 +122,7 @@ public class RecognitionException<T:ATNSimulator> {
|
|||
/// - Returns: The recognizer where this exception occurred, or `null` if
|
||||
/// the recognizer is not available.
|
||||
///
|
||||
public func getRecognizer() -> Recognizer<T>? {
|
||||
public func getRecognizer() -> RecognizerProtocol? {
|
||||
return recognizer
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,25 @@
|
|||
|
||||
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>>
|
||||
private let tokenTypeMapCache = HashMap<Vocabulary, [String : Int]>()
|
||||
|
||||
private let ruleIndexMapCache = HashMap<ArrayWrapper<String>, [String : Int]>()
|
||||
|
||||
|
||||
private var _listeners: [ANTLRErrorListener] = [ConsoleErrorListener.INSTANCE]
|
||||
|
||||
public var _interp: ATNInterpreter!
|
||||
|
@ -151,8 +163,8 @@ open class Recognizer<ATNInterpreter:ATNSimulator> {
|
|||
///
|
||||
/// What is the error header, normally line/character position information?
|
||||
///
|
||||
open func getErrorHeader(_ e: AnyObject) -> String {
|
||||
let offending = (e as! RecognitionException).getOffendingToken()
|
||||
open func getErrorHeader(_ e: RecognitionException) -> String {
|
||||
let offending = e.getOffendingToken()
|
||||
let line = offending.getLine()
|
||||
let charPositionInLine = offending.getCharPositionInLine()
|
||||
return "line \(line):\(charPositionInLine)"
|
||||
|
|
|
@ -16,5 +16,5 @@ import Foundation
|
|||
|
||||
public enum ANTLRException: Error {
|
||||
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>);"
|
||||
|
||||
ThrowNoViableAlt(t) ::= "throw try ANTLRException.recognition(e: NoViableAltException(self))"
|
||||
ThrowNoViableAlt(t) ::= "throw ANTLRException.recognition(e: NoViableAltException(self))"
|
||||
|
||||
TestSetInline(s) ::= <<
|
||||
<!<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) ::= <<
|
||||
setState(<p.stateNumber>)
|
||||
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