Antlr4 将分数视为空白。这正常吗?
在我的语法中,我有一个空格:Antlr4 将分数视为空白。这正常吗?,antlr4,Antlr4,在我的语法中,我有一个空格: WS: (' '|'\r'|'\t'|'\n') -> skip ; 但是,如果我放置一个未加分数而不是一个空格,解析器不会阻塞 My-first-module_DEFINITIONS_::= 被认为是 My-first-module DEFINITIONS ::= 是否有一个选项我必须在lexer中设置一些 谢谢 这是简化的语法,有助于再现我所看到的内容 grammar ASN; /*--------------------- Modul
WS:
(' '|'\r'|'\t'|'\n') -> skip
;
但是,如果我放置一个未加分数而不是一个空格,解析器不会阻塞
My-first-module_DEFINITIONS_::=
被认为是
My-first-module DEFINITIONS ::=
是否有一个选项我必须在lexer中设置一些
谢谢
这是简化的语法,有助于再现我所看到的内容
grammar ASN;
/*--------------------- Module definition -------------------------------------------*/
/* ModuleDefinition (see 13 in ITU-T X.680 (08/2015) */
moduleDefinition:
moduleIdentifier
DEFINITIONS_LITERAL
ASSIGN
BEGIN_LITERAL
END_LITERAL
;
moduleIdentifier:
UCASE_ID
;
/*--------------------- LITERAL -----------------------------------------------------*/
DEFINITIONS_LITERAL:
'DEFINITIONS'
;
BEGIN_LITERAL:
'BEGIN'
;
END_LITERAL:
'END'
;
ASSIGN:
'::='
;
UCASE_ID:
('A'..'Z') ('-'('a'..'z'|'A'..'Z'|'0'..'9')|('a'..'z'|'A'..'Z'|'0'..'9'))*
;
/* white-space (see 12.1.6 in ITU-T X.680 (08/2015) */
WS:
(' '|'\r'|'\t'|'\n') -> skip
;
以及解析器不应接受的示例:
My-first-module_DEFINITIONS_::=
BEGIN
END
编辑:我意识到我的问题是因为我使用JUnit来运行测试,我只是检查解析器发现的语法错误。
下面是代码,包括巴特的答案,如果lexer出现问题,它会导致测试失败
// load test data
InputStream inStream = getClass().getClassLoader().getResourceAsStream(resourceName);
if (inStream == null) {
throw new RuntimeException("Resource not found: " + resourceName);
}
// create a CharStream that reads from standard input
CharStream input = new ANTLRInputStream(inStream);
// create a lexer that feeds off of input CharStream
ASNLexer lexer = new ASNLexer(input);
lexer.addErrorListener(new BaseErrorListener() {
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException(e);
}
}
);
// create a buffer of tokens pulled from the lexer
TokenStream tokens = new CommonTokenStream(lexer);
// create a parser that feeds off the tokens buffer
ASNParser parser = new ASNParser(tokens);
parser.moduleDefinition(); // begin parsing at moduleDefinition rule
assert(0 == parser.getNumberOfSyntaxErrors());
//负载测试数据
InputStream inStream=getClass().getClassLoader().getResourceAsStream(resourceName);
如果(流内==null){
抛出新的RuntimeException(“未找到资源:+resourceName”);
}
//创建从标准输入读取的字符流
CharStream输入=新的AntlInputStream(流内);
//创建一个lexer,该lexer从输入字符流中获取信息
ASNLexer lexer=新ASNLexer(输入);
lexer.addErrorListener(新的BaseErrorListener(){
public void syntaxError(识别器识别器、对象违规符号、int行、int charPositionInLine、字符串消息、识别异常e){
抛出新的运行时异常(e);
}
}
);
//创建从lexer提取的令牌缓冲区
令牌流令牌=新的CommonTokenStream(lexer);
//创建一个以令牌缓冲区为源的解析器
ASNParser parser=新的ASNParser(令牌);
parser.moduleDefinition();//从moduleDefinition规则开始解析
断言(0==parser.getNumberOfSyntaxErrors());
lexer从意外输入中恢复。通过运行此类,可以看到这一点:
public class Main {
public static void main(String[] args) {
String source = "My-first-module_DEFINITIONS_::= \n" +
"BEGIN \n" +
"\n" +
"END";
ASNLexer lexer = new ASNLexer(CharStreams.fromString(source));
ASNParser parser = new ASNParser(new CommonTokenStream(lexer));
parser.moduleDefinition();
}
}
将在标准输出中打印以下内容:
line 1:15 token recognition error at: '_'
line 1:27 token recognition error at: '_'
这里有几个选项:
1.添加一个全面的规则
在语法末尾添加这样一条规则:
Other
: .
;
然后根据需要在解析器中处理Other
2.添加自定义ErrorListener
这样做:
lexer.addErrorListener(new BaseErrorListener(){
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException(e);
}
});
UCASE_ID:
[A-Z] ( '-'? [a-zA-Z0-9] )*
;
WS:
[ \t\r\n] -> skip
;
可能是lexer或解析器从中恢复,也可能是其他东西。如果看不到一个“最小的、完整的、可验证的例子”(见:),我将把我的东西放到网上。根据你的回答,我想这是不正常的?“我想这是不正常的?”-不,这很可能是ANTLR按预期执行。“我会把我的东西放在网上”-无需发布数百个LOC,只需重现问题即可。请将代码添加到您的问题中,而不是一些非现场位置。这只是一个测试用例: