我对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;
现在的问题是,当我针对selectionStatement
或statement
测试一段代码时,它会通过测试,但是当我针对program
对其进行测试时,它无法识别。谁可以帮我这个事?非常感谢你
编辑:我用来测试的代码如下:
if (x == 2) {}
它会针对selectionStatement
和statement
通过测试,但在program
处失败。 program
似乎只接受if...else
if (x == 2) {} else {}
编辑2: 我收到的错误消息是
<unknown>: Incorrect error: no viable alternative at input 'if(x==2){}'
答案 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并不会做出奇怪的事情。事情 - 只是你不理解的事情。