ANTLR 尝试匹配未指定为选项的表达式
ANTLR Tries to Match an Expression That Wasn't Specified as an Option
我试图了解 ANTLR 语法的工作原理,但我遇到了一种情况,它的行为异常,我无法解释原因或找出解决方法。
示例如下:
root : title '\n' fields EOF;
title : STR;
fields : field_1 field_2;
field_1 : 'a' | 'b' | 'c';
field_2 : 'd' | 'e' | 'f';
STR : [a-z]+;
分为两部分:
- 标题是一个没有特殊字符的小写字符串
- 表示一组可能配置的两个字符串
当我去测试语法时,会发生以下情况:首先我写下标题,然后在新的一行中给出第一个字段的字符。到目前为止,一切都很好。到目前为止,解析树看起来和我预期的一样。
当我添加下一个字段时,问题就来了。 ANTLR 决定将该行重新解释为 STR
的实例,而不是我期望的字段的串联。
我不明白为什么 ANTLR 在语法未将其指定为选项时尝试强制执行不相关的终端表达式。它难道不应该知道只查找与字段规则匹配的字符,因为它是解析树中 fields
节点的后代吗?这是怎么回事,我该如何编写我的 ANTLR 语法,这样它们就不会出现这个问题?
我读到 ANTLR 试图从语法的顶部到底部贪婪地匹配格式,但这并不能解释为什么会发生这种情况,因为 STR 终端是文件中的最后一行。如果 ANTLR 给予匹配终端特殊的优先权,我如何格式化语法以便正确解释它?据我了解,正则表达式不适用于 non-terminals 因此似乎必须定义它现在的样子。
澄清说明:这只是我尝试按原样使用文本格式的可能语法的示例,因此我不是在寻找答案,例如添加 space在字段之间或将标题更改为大写。
之前不明白的是,生成parser有两步:
- 使用词法分析器规则(大写语句)扫描输入以获取标记列表,然后...
- 使用解析器规则(小写语句)和生成的标记构建解析树
我的问题是 ANTLR 无法知道我希望在生成标记时对特定字符串进行不同的解释。为了解决这个问题,我为字段字符串编写了一个新的词法分析器规则,以便将其识别为标记。关键是让 FIELDS
规则出现在 STR
规则之前,因为 ANTLR 按照它们出现的顺序检查它们。
root : title FIELDS EOF;
title : STR;
FIELDS : [a-c] [d-f];
STR : [a-z]+;
注意:我不得不硬着头皮阅读 ANTLR Mega Tutorial 来解决这个问题。
我试图了解 ANTLR 语法的工作原理,但我遇到了一种情况,它的行为异常,我无法解释原因或找出解决方法。
示例如下:
root : title '\n' fields EOF;
title : STR;
fields : field_1 field_2;
field_1 : 'a' | 'b' | 'c';
field_2 : 'd' | 'e' | 'f';
STR : [a-z]+;
分为两部分:
- 标题是一个没有特殊字符的小写字符串
- 表示一组可能配置的两个字符串
当我去测试语法时,会发生以下情况:首先我写下标题,然后在新的一行中给出第一个字段的字符。到目前为止,一切都很好。到目前为止,解析树看起来和我预期的一样。
当我添加下一个字段时,问题就来了。 ANTLR 决定将该行重新解释为 STR
的实例,而不是我期望的字段的串联。
我不明白为什么 ANTLR 在语法未将其指定为选项时尝试强制执行不相关的终端表达式。它难道不应该知道只查找与字段规则匹配的字符,因为它是解析树中 fields
节点的后代吗?这是怎么回事,我该如何编写我的 ANTLR 语法,这样它们就不会出现这个问题?
我读到 ANTLR 试图从语法的顶部到底部贪婪地匹配格式,但这并不能解释为什么会发生这种情况,因为 STR 终端是文件中的最后一行。如果 ANTLR 给予匹配终端特殊的优先权,我如何格式化语法以便正确解释它?据我了解,正则表达式不适用于 non-terminals 因此似乎必须定义它现在的样子。
澄清说明:这只是我尝试按原样使用文本格式的可能语法的示例,因此我不是在寻找答案,例如添加 space在字段之间或将标题更改为大写。
之前不明白的是,生成parser有两步:
- 使用词法分析器规则(大写语句)扫描输入以获取标记列表,然后...
- 使用解析器规则(小写语句)和生成的标记构建解析树
我的问题是 ANTLR 无法知道我希望在生成标记时对特定字符串进行不同的解释。为了解决这个问题,我为字段字符串编写了一个新的词法分析器规则,以便将其识别为标记。关键是让 FIELDS
规则出现在 STR
规则之前,因为 ANTLR 按照它们出现的顺序检查它们。
root : title FIELDS EOF;
title : STR;
FIELDS : [a-c] [d-f];
STR : [a-z]+;
注意:我不得不硬着头皮阅读 ANTLR Mega Tutorial 来解决这个问题。