diff --git a/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java b/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java index 0c577dc7d..6a8d4f9eb 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java +++ b/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java @@ -40,6 +40,7 @@ import org.antlr.v4.runtime.misc.Nullable; public class FailedPredicateException extends RecognitionException { public int ruleIndex; public int predIndex; + public String predicate; public String msg; public FailedPredicateException(Parser recognizer) { @@ -52,8 +53,25 @@ public class FailedPredicateException extends RecognitionException { PredicateTransition trans = (PredicateTransition)s.transition(0); ruleIndex = trans.ruleIndex; predIndex = trans.predIndex; + this.predicate = predicate; this.msg = String.format("failed predicate: {%s}?", predicate); Token la = recognizer.getCurrentToken(); this.offendingToken = la; } + + public FailedPredicateException(Parser recognizer, + @Nullable String predicate, + @Nullable String msg) + { + super(recognizer, recognizer.getInputStream(), recognizer._ctx); + ATNState s = recognizer.getInterpreter().atn.states.get(recognizer._ctx.s); + PredicateTransition trans = (PredicateTransition)s.transition(0); + ruleIndex = trans.ruleIndex; + predIndex = trans.predIndex; + this.predicate = predicate; + this.msg = msg; + Token la = recognizer.getCurrentToken(); + this.offendingToken = la; + } + } diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index e4deb05f8..1d105d4de 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -489,7 +489,7 @@ ArgAction(a, chunks) ::= "" SemPred(p, chunks, failChunks) ::= << setState(); -if (!()) throw new FailedPredicateException(this, ); +if (!()) throw new FailedPredicateException(this, , , ); >> ExceptionClause(e, catchArg, catchAction) ::= << diff --git a/tool/src/org/antlr/v4/codegen/model/SemPred.java b/tool/src/org/antlr/v4/codegen/model/SemPred.java index c3ebe96e7..979becf34 100644 --- a/tool/src/org/antlr/v4/codegen/model/SemPred.java +++ b/tool/src/org/antlr/v4/codegen/model/SemPred.java @@ -35,28 +35,28 @@ import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.model.chunk.ActionChunk; import org.antlr.v4.tool.ast.ActionAST; import org.antlr.v4.tool.ast.GrammarAST; -import org.antlr.v4.tool.ast.PredAST; import java.util.List; /** */ public class SemPred extends Action { - public String msg; // user-specified in grammar option + public String msg; // user-specified string in fail grammar option + public String predicate; // the predicate string with { }? stripped + /** user-specified action in fail grammar option */ @ModelElement public List failChunks; public SemPred(OutputModelFactory factory, ActionAST ast) { super(factory,ast); - GrammarAST failNode = ((PredAST)ast).getOptionAST("fail"); + GrammarAST failNode = ast.getOptionAST("fail"); CodeGenerator gen = factory.getGenerator(); - if ( failNode==null ) { - msg = ast.getText(); - if (msg.startsWith("{") && msg.endsWith("}?")) { - msg = msg.substring(1, msg.length() - 2); - } - msg = gen.target.getTargetStringLiteralFromString(msg); - return; + predicate = ast.getText(); + if (predicate.startsWith("{") && predicate.endsWith("}?")) { + predicate = predicate.substring(1, predicate.length() - 2); } + predicate = gen.target.getTargetStringLiteralFromString(predicate); + + if ( failNode==null ) return; if ( failNode instanceof ActionAST ) { ActionAST failActionNode = (ActionAST)failNode;