首页 文章

ANTLR4:我无法理解的意外行为

提问于
浏览
0

我对 ANTLR4 很新,我正在努力 Build 自己的语言 . 所以我的语法开始于

program: <EOF> | statement | functionDef | statement program | functionDef program;

我的 statement

statement: selectionStatement | compoundStatement | ...;

selectionStatement
:   If LeftParen expression RightParen compoundStatement (Else compoundStatement)?
|   Switch LeftParen expression RightParen compoundStatement
;

compoundStatement
: LeftBrace statement* RightBrace;

现在的问题是,当我测试一段代码对抗 selectionStatementstatement 时,它通过了测试,但是当我针对 program 进行测试时,它无法识别 . 谁可以帮我这个事?非常感谢你


编辑:我用来测试的代码如下:

if (x == 2) {}

它通过 selectionStatementstatement 的测试,但在 program 失败 . 似乎 program 只接受 if...else

if (x == 2) {} else {}

编辑2:我收到的错误消息是

<unknown>: Incorrect error: no viable alternative at input 'if(x==2){}'

1 回答

  • 2

    鉴于提供的信息不完整,无法回答您的问题:声明规则是部分规则,并且缺少复合声明规则 .

    尽管如此,您应该使用两种技术来自己回答这类问题(除了单元测试) .

    首先,确保词法分析器按预期工作 . This answer显示了如何直接转储令牌流 .

    其次,使用自定义ErrorListener为每个遇到的错误提供其解析路径的有意义/详细描述 . 一个例子:

    public class JavaErrorListener extends BaseErrorListener {
    
        public int lastError = -1;
    
        @Override
        public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
                String msg, RecognitionException e) {
    
            Parser parser = (Parser) recognizer;
            String name = parser.getSourceName();
            TokenStream tokens = parser.getInputStream();
    
            Token offSymbol = (Token) offendingSymbol;
            int thisError = offSymbol.getTokenIndex();
            if (offSymbol.getType() == -1 && thisError == tokens.size() - 1) {
                Log.debug(this, name + ": Incorrect error: " + msg);
                return;
            }
            String offSymName = JavaLexer.VOCABULARY.getSymbolicName(offSymbol.getType());
    
            List<String> stack = parser.getRuleInvocationStack();
            // Collections.reverse(stack);
    
            Log.error(this, name);
            Log.error(this, "Rule stack: " + stack);
            Log.error(this, "At line " + line + ":" + charPositionInLine + " at " + offSymName + ": " + msg);
    
            if (thisError > lastError + 10) {
                lastError = thisError - 10;
            }
            for (int idx = lastError + 1; idx <= thisError; idx++) {
                Token token = tokens.get(idx);
                if (token.getChannel() != Token.HIDDEN_CHANNEL) Log.error(this, token.toString());
            }
            lastError = thisError;
        }
    }
    

    注意:将Log语句调整为您正在使用的任何日志包 .

    最后,Antlr不做“怪异”的事情 - 只是你不理解的事情 .

相关问题