ANTLR4中的强制语义错误(失败的谓词)

ANTLR4中的强制语义错误(失败的谓词),antlr,antlr4,Antlr,Antlr4,基本上,我已经扩展了BaseErrorListener,我需要知道错误何时是语义错误,何时是语法错误。因此,我希望下面给出一个失败的谓词异常,但我得到的是一个NoviableException(我知道计数正在工作,因为我可以打印出things的值,这是正确的)。有没有一种方法可以让它重新工作来做我想做的事情?在下面的示例中,如果我们没有得到6个东西,我希望出现一个失败的谓词异常 grammar Test; @parser::members { int things = 0; } . .

基本上,我已经扩展了BaseErrorListener,我需要知道错误何时是语义错误,何时是语法错误。因此,我希望下面给出一个失败的谓词异常,但我得到的是一个
NoviableException
(我知道计数正在工作,因为我可以打印出
things
的值,这是正确的)。有没有一种方法可以让它重新工作来做我想做的事情?在下面的示例中,如果我们没有得到6个
东西,我希望出现一个失败的谓词异常

grammar Test;

@parser::members {
    int things = 0;
}
.
.
.
samplerule : THING { things++; } ;
.
.
.
// Want this to be a failed predicate instead of NoViableAltException
anotherrule : ENDTOKEN { things == 6 }? ;
.
.
.

我已经正确地获得了以下失败谓词异常(针对不同的场景):

somerule:{Integer.valueOf(getCurrentToken().getText())<256}?数量;
.
.
.
编号:[0-9]+;

在ANTLR 4中,谓词只应在您的输入导致两个不同的可能解析树(歧义语法)并且默认处理是生成错误解析树的情况下使用。您应该创建一个侦听器或访问者实现,其中包含对源代码进行语义验证的逻辑。

由于答案和谓词不应用于我试图做的事情这一明显事实,我走了另一条路

如果您知道自己在寻找什么,那么ANTLR4的文档实际上非常有用——请访问我的文档并进一步浏览,看看我下面的实现还能做些什么

我的司机最后看起来像是这样:

// NameOfMyGrammar.java
public class NameOfMyGrammar {

    public static void main(String[] args) throws Exception {

        String inputFile = args[0];

        try {
            ANTLRInputStream input = new ANTLRFileStream(inputFile);

            NameOfMyGrammarLexer lexer = new NameOfMyGrammarLexer(input);

            CommonTokenStream tokens = new CommonTokenStream(lexer);

            MyCustomParser parser = new MyCustomParser(tokens);

            try {
                // begin parsing at "start" rule
                ParseTree tree = parser.start();
                // can print out parse tree if you want..
            } catch (RuntimeException e) {
                // Handle errors if you want..
            }
        } catch (IOException e) {
            System.err.println("Error: " + e);
        }   
    }

    // extend ANTLR-generated parser
    private static class MyCustomParser extends NameOfMyGrammarParser {

        // Constructor (my understanding is that you DO need this)
        public MyCustomParser(TokenStream input) {
            super(input);
        }

        @Override
        public Token getCurrentToken() {
            // Do your semantic checking as you encounter tokens here..
            // Depending on how you want to handle your errors, you can
            // throw exceptions, print out errors, etc.

            // Make sure you end by returning the current token
            return _input.LT(1);
        }
    }
}
// NameOfMyGrammar.java
public class NameOfMyGrammar {

    public static void main(String[] args) throws Exception {

        String inputFile = args[0];

        try {
            ANTLRInputStream input = new ANTLRFileStream(inputFile);

            NameOfMyGrammarLexer lexer = new NameOfMyGrammarLexer(input);

            CommonTokenStream tokens = new CommonTokenStream(lexer);

            MyCustomParser parser = new MyCustomParser(tokens);

            try {
                // begin parsing at "start" rule
                ParseTree tree = parser.start();
                // can print out parse tree if you want..
            } catch (RuntimeException e) {
                // Handle errors if you want..
            }
        } catch (IOException e) {
            System.err.println("Error: " + e);
        }   
    }

    // extend ANTLR-generated parser
    private static class MyCustomParser extends NameOfMyGrammarParser {

        // Constructor (my understanding is that you DO need this)
        public MyCustomParser(TokenStream input) {
            super(input);
        }

        @Override
        public Token getCurrentToken() {
            // Do your semantic checking as you encounter tokens here..
            // Depending on how you want to handle your errors, you can
            // throw exceptions, print out errors, etc.

            // Make sure you end by returning the current token
            return _input.LT(1);
        }
    }
}