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



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

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 }? NUMBER ;
.
.
.
NUMBER : [0-9]+ ;

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

由于 280Z28 的答案以及谓词不应该用于我想要做的事情的明显事实,我走了一条不同的路线。

如果你知道你要找什么,ANTLR4的文档实际上非常有用——访问Parser.getCurrentToken()的文档,进一步看看你可以用下面的实现做些什么。

我的驱动程序最终看起来像下面这样:

// 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);
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新