我已经开始使用 ANTLR 并注意到它的词法分析器规则非常变化无常。一个极其令人沮丧的例子如下:
grammar output;
test: FILEPATH NEWLINE TITLE ;
FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ;
NEWLINE: '\r'? '\n' ;
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ;
该语法将不匹配如下内容:
c:\test.txt
x
奇怪的是如果我改变TITLE
to be TITLE: 'x' ;
这次它仍然失败,给出一条错误消息,指出“输入‘x’期望‘x’不匹配”,这非常令人困惑。更奇怪的是,如果我替换使用TITLE
in test
with FILEPATH
整个事情有效(尽管FILEPATH
会匹配比我想要匹配的更多,所以一般来说这对我来说不是一个有效的解决方案)。
我非常困惑为什么 ANTLR 会给出如此极其奇怪的错误,然后在处理事情时突然无缘无故地工作。
这似乎是一个常见的误解ANTLR
:
ANTLR 中的语言处理:
语言处理分两个严格独立的阶段完成:
- 词法分析,即将文本划分为标记
- 解析,即从标记构建解析树
由于词法分析必须先于解析,因此会产生一个结果:词法分析器独立于解析器,解析器不能影响词法分析.
Lexing
ANTLR 中的词法分析工作如下:
- 所有第一个字符大写的规则都是词法分析器规则
- 词法分析器从头开始并尝试找到与当前输入最匹配的规则
- 最佳匹配是具有最大长度的匹配,即将下一个输入字符附加到最大长度匹配而产生的标记与任何词法分析器规则都不匹配
- tokens are generated from matches:
- if one rule匹配最大长度匹配对应的token被push到token流中
- if 多重规则匹配最大长度匹配语法中第一个定义的标记被推送到标记流
示例:你的语法有什么问题
你的语法有两条至关重要的规则:
FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ;
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ;
每个与 TITLE 匹配的匹配项也将与 FILEPATH 匹配。并且 FILEPATH 定义在 TITLE 之前:因此,您希望成为标题的每个标记都将是一个 FILEPATH。
有两个提示:
- 保持词法分析器规则分离(任何标记都不应与另一个标记的超集匹配)。
- 如果您的标记有意匹配相同的字符串,则将它们按正确的顺序排列(在您的情况下这就足够了)。
- 如果您需要解析器驱动的词法分析器,则必须更改为另一个解析器生成器:PEG-Parsers 或 GLR-Parsers 可以做到这一点(但当然这可能会产生其他问题)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)