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

时间:2015-06-08 02:39:53

标签: antlr antlr4

我对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){}'

1 个答案:

答案 0 :(得分: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并不会做出奇怪的事情。事情 - 只是你不理解的事情。