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;
现在的问题是,当我用 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){}'
由于提供的信息不完整,无法回答您的问题: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' 事情 - 只会做你不理解的事情。
我是 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){}'
由于提供的信息不完整,无法回答您的问题: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' 事情 - 只会做你不理解的事情。