Skip to content

Commit

Permalink
[Swift] Report InputMismatchException with original context information
Browse files Browse the repository at this point in the history
Port 0803c74 from the Java runtime to Swift.  This was issue antlr#1922.
  • Loading branch information
ewanmellor committed Nov 10, 2018
1 parent 40e883a commit 2d4bb9a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ public static class ExtraneousInput extends BaseParserTestDescriptor {

@Override
public boolean ignore(String targetName) {
return !"Java".equals(targetName);
return !"Java".equals(targetName) && !"Swift".equals(targetName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ public static class PredFromAltTestedInLoopBack_1 extends PredFromAltTestedInLoo

@Override
public boolean ignore(String targetName) {
return !"Java".equals(targetName);
return !"Java".equals(targetName) && !"Swift".equals(targetName);
}
}

Expand Down
34 changes: 32 additions & 2 deletions runtime/Swift/Sources/Antlr4/DefaultErrorStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ open class DefaultErrorStrategy: ANTLRErrorStrategy {

open var lastErrorStates: IntervalSet?

/**
* This field is used to propagate information about the lookahead following
* the previous match. Since prediction prefers completing the current rule
* to error recovery efforts, error reporting may occur later than the
* original point where it was discoverable. The original context is used to
* compute the true expected sets as though the reporting occurred as early
* as possible.
*/
open var nextTokensContext: ParserRuleContext?

/**
* @see #nextTokensContext
*/
open var nextTokensState = ATNState.INVALID_STATE_NUMBER


public init() {
}

Expand Down Expand Up @@ -207,7 +223,20 @@ open class DefaultErrorStrategy: ANTLRErrorStrategy {

// try cheaper subset first; might get lucky. seems to shave a wee bit off
let nextToks = recognizer.getATN().nextTokens(s)
if nextToks.contains(CommonToken.EPSILON) || nextToks.contains(la) {
if nextToks.contains(la) {
// We are sure the token matches
nextTokensContext = nil
nextTokensState = ATNState.INVALID_STATE_NUMBER
return
}

if nextToks.contains(CommonToken.EPSILON) {
if nextTokensContext == nil {
// It's possible the next token won't match; information tracked
// by sync is restricted for performance.
nextTokensContext = recognizer.getContext()
nextTokensState = recognizer.getState()
}
return
}

Expand Down Expand Up @@ -423,7 +452,8 @@ open class DefaultErrorStrategy: ANTLRErrorStrategy {
return try getMissingSymbol(recognizer)
}
// even that didn't work; must throw the exception
throw ANTLRException.recognition(e: InputMismatchException(recognizer))
let exn = InputMismatchException(recognizer, state: nextTokensState, ctx: nextTokensContext)
throw ANTLRException.recognition(e: exn)
}

///
Expand Down
8 changes: 6 additions & 2 deletions runtime/Swift/Sources/Antlr4/InputMismatchException.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
///

public class InputMismatchException: RecognitionException {
public init(_ recognizer: Parser) {
super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx)
public init(_ recognizer: Parser, state: Int = ATNState.INVALID_STATE_NUMBER, ctx: ParserRuleContext? = nil) {
let bestCtx = ctx ?? recognizer._ctx

super.init(recognizer, recognizer.getInputStream()!, bestCtx)

if let token = try? recognizer.getCurrentToken() {
setOffendingToken(token)
}
setOffendingState(state)
}
}

0 comments on commit 2d4bb9a

Please sign in to comment.