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

ANTLR4: Unexpected behavior that I can't understand

我是 ANTLR4 的新手,正在尝试构建自己的语言。所以我的语法从

开始
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){}'

由于提供的信息不完整,无法回答您的问题:statement 规则不完整且缺少 compoundStatement 规则。

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

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

其次,使用自定义 ErrorListener 来提供 meaningful/detailed 对遇到的每个错误的解析路径的描述。一个例子:

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

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

最后,Antlr 不会做 'weird' 事情 - 只会做你不理解的事情。