我正在尝试创建一个 ANTLR 语法来解析可选地具有重复计数的键序列。例如,(a b c r5)
表示“重复键 a、b 和 c 五次。”
我有适用于 KEYS 的语法:('a'..'z'|'A'..'Z')
。
但是当我尝试添加数字键 KEYS : ('a'..'z'|'A'..'Z'|'0'..'9')
时输入表达式如 (a 5 r5)
,解析在中间的 5 上失败,因为它无法判断 5 是 INTEGER 还是 KEY。 (或者我认为是这样;错误消息很难解释“NoViableAltException”)。
我尝试过这些语法形式,它们有效(“r”表示“重复计数”):
repeat : '(' LETTERKEYS INTEGER ')' - works for a-zA-Z
repeat : '(' LETTERKEYS 'r' INTEGER ')'; - works for a-zA-Z
但是我失败了
repeat : '(' LETTERSandDIGITKEYS INTEGER ')' - fails on '(a 5 r5)'
repeat : '(' LETTERSandDIGITKEYS 'r' INTEGER ')'; - fails on '(a 5 r5)'
也许语法无法识别;也许我需要以相同的方式识别所有 5 的键(如键、数字或整数),并在解析树中将中间的数字实例解释为键,将最后一组数字解释为整数计数?
是否可以定义一个语法,允许我重复数字键和字母键,以便正确识别像 (a 5 123 r5)
这样的表达式? (也就是说,“重复键 a,5,1,2,3 五次。”)我不受特定语法的限制,尽管使用类似的语法会很好。
谢谢。
最佳答案
the parse fails on the middle 5 because it can't tell if the 5 is an INTEGER or a KEY.
如果您定义了以下规则:
INTEGER : [0-9]+;
KEY : [a-zA-Z0-9];
那么单个数字(例如示例中的 5
)将始终成为 INTEGER
标记。即使
解析器尝试匹配 KEY
标记,5
将变成 INTEGER
。没有什么
你可以这样做:这就是 ANTLR 词法分析器的工作方式。词法分析器的工作方式如下:
- 尝试消耗尽可能多的字符(最长的匹配获胜)
- 如果 2 个或更多规则匹配相同的字符(如
INTEGER
和KEY
在5
的情况下),则先定义规则“获胜”
如果您希望 5
成为 INTEGER
,但有时是 KEY
,请执行以下操作:
key : KEY | SINGLE_DIGIT | R;
integer : INTEGER | SINGLE_DIGIT;
repeat : R integer;
SINGLE_DIGIT : [0-9];
INTEGER : [0-9]+;
R : 'r';
KEY : [a-zA-Z];
并且在解析器规则中,您使用key
和integer
而不是KEY
和INTEGER
。
关于parsing - ANTLR 语法也可以识别数字键和整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64548645/