我正在使用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)* ;
“source”和“target”不能为空。但我的测试显示如下:
如果达到“请求”令牌,我确实需要设置其他内容。但是从上面来说,即使语法错误,代码仍然达到“请求”令牌。为什么呢?
第二个问题:如何为固定长度令牌指定规则,例如,精确10位数的令牌?
第三个问题是关于错误处理。我在解析器中覆盖emitErrorMessage()以设置错误标志,但我在词法分析器中找到了另一个emitErrorMessage()。我不想在解析器和词法分析器对象之间共享错误标志。我可以覆盖lexer中的emitErrorMessage()来做什么,并完全依赖解析器报告错误?或换句话说,如果出现错误,解析器是否会捕获它?
如果错误标志设置为一个错误,解析器是否可以实际恢复并匹配其他规则,那么之前的错误是错误警报?
感谢您的帮助!
答案 0 :(得分:1)
- ...
- 输入“C | n1 |” :语法错误,但打印“嗨”。不好。
如果达到“请求”令牌,我确实需要设置其他内容。但是从上面来说,即使语法错误,代码仍然达到“请求”令牌。为什么呢?
因为解析器试图从中恢复。如果您不希望解析器(尝试)从错误匹配的标记中恢复,只需抛出这样的异常:
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::members
。
第二个问题:如何为固定长度令牌指定规则,例如,精确10位数的令牌?
请参阅:ANTR3 set the number of accepted characters for a token
第三个问题是关于错误处理。 ...
请参阅我的答案的第一部分:只需覆盖emitErrorMessage()
并在其中不执行任何操作(默认操作是在std.err
上打印)。
我可以覆盖lexer中的emitErrorMessage()来做什么,完全依赖解析器来报告错误吗?
好吧,解析器和词法分析器处理不同的类型或错误,因此忽略词法分析器中的某些问题可能不会导致解析器产生警告/错误。
答案 1 :(得分:0)
对于问题#2,我也想出了一些固定长度的方法。不知道这是否是流行的方式:
示例:exact3'|' exact4;
//方法1:
exact3:(d + = DIGIT)+ {$ d!= null&& $ d.size()== 3}? ;
//方法2
exact4:atmost4 {$ atmost4.text.length()== 4}? ;
atmost4:
@init {int n = 1;}
:({n <= 4}?=&gt; DIGIT {n ++;})+
;
DIGIT:'0'..'9';
对于问题#3,我将在第一次错误时失败,即在词法分析器和解析器中覆盖emitErrorMessage()以引发异常。 emitErrorMessage(msg)的选择是因为它正确准备了错误消息。
感谢所有分享的人!