令牌的antlr长度和错误处理
我正在使用altlr版本3.4 第一个问题,请看语法:令牌的antlr长度和错误处理,antlr,Antlr,我正在使用altlr版本3.4 第一个问题,请看语法: request: 'C' DELIM source DELIM target { System.out.println("Hi"); } ; source: ID ; target: ID ; DELIM: '|' ; fragment ALPHA: 'a'..'z' | 'A'..'Z' ; fragment NUM: '0'..'9' ; ID: ALPHA (ALPHA | NUM)* ; “源”和“目标”不能为空。但我的
request: 'C' DELIM source DELIM target
{ System.out.println("Hi"); }
;
source: ID ;
target: ID ;
DELIM: '|' ;
fragment ALPHA: 'a'..'z' | 'A'..'Z' ;
fragment NUM: '0'..'9' ;
ID: ALPHA (ALPHA | NUM)* ;
“源”和“目标”不能为空。但我的测试表明:
- 对于输入“C | n1 | n2”:正常情况下,没有问题
- 对于输入“C | | n2”:语法错误和“Hi”未打印。预期。嗯
- 对于输入“C | n1 |”:语法错误,但会打印“Hi”。不太好
- 对于输入“C | n1 |”:语法错误,但会打印“Hi”。不太好
grammar T;
// options...
@members {
@Override
public void emitErrorMessage(String message) {
throw new RuntimeException(message);
}
}
request
: 'C' DELIM source DELIM target { System.out.println("Hi"); }
;
// more rules...
请注意,@members
是@parser::members
的缩写,它只会导致emitErrorMessage(…)
在解析器中被重写,而不会在lexer中被重写。对于lexer成员,您需要执行@lexer::members
第二个问题:如何为固定长度的令牌指定规则,例如,精确为10位的令牌
见:
第三个问题是关于错误处理
请参阅我答案的第一部分:只需覆盖emitErrorMessage()
,而不在其中执行任何操作(默认操作是在std.err
上打印)
我可以在lexer中重写emitErrorMessage()而不做任何事情,并完全依赖解析器来报告错误吗
嗯,解析器和lexer处理不同的类型或错误,因此忽略lexer中的某些问题可能不会导致解析器产生警告/错误。Bart,您的帮助非常好。我也仔细考虑了一下,明白问题1的行为是合法的。与编译器一样,解析器将恢复并继续查找尽可能多的错误 对于问题2,我还想出了一些固定长度的方法。不知道这是否是流行的方式: 示例:exact3'|'exact4 //方法1:
exact3:(d+=数字)+{$d!=null&&$d.size()==3} //方法2
exact4:atmost4{$atmost4.text.length()==4}
大气4:
@init{int n=1;}
:({nDIGIT{n++;})+
) 数字:'0'..'9' 对于问题#3,我将在第一个错误时失败,即在lexer和parser中重写emitErrorMessage()以引发异常。选择emitErrorMessage(msg)是因为它正确准备了错误消息
谢谢所有分享的人!谢谢。你的回答在不同的背景下帮助了我。我不知道
@成员
只适用于解析器。