Antlr中不明确的Lexer规则

Antlr中不明确的Lexer规则,antlr,antlr4,Antlr,Antlr4,我有一个antlr语法,它有多个与同一个单词匹配的词法规则。在词法分析过程中无法解决这个问题,但通过语法,它就变得毫不含糊了 例如: conversion: NUMBER UNIT CONVERT UNIT; NUMBER: [0-9]+; UNIT: 'in' | 'meters' | ......; CONVERT: 'in'; 输入:1英寸(米) 单词“in”与lexer规则UNIT和CONVERT相匹配 如何在保持语法文件可读性的同时解决此问题?根据您问题中的信息,很难说最好的解决方案

我有一个antlr语法,它有多个与同一个单词匹配的词法规则。在词法分析过程中无法解决这个问题,但通过语法,它就变得毫不含糊了

例如:

conversion: NUMBER UNIT CONVERT UNIT;
NUMBER: [0-9]+;
UNIT: 'in' | 'meters' | ......;
CONVERT: 'in';
输入:
1英寸(米)

单词“in”与lexer规则
UNIT
CONVERT
相匹配


如何在保持语法文件可读性的同时解决此问题?

根据您问题中的信息,很难说最好的解决方案是什么-例如,我不知道您的lexer规则是什么-我也无法告诉您为什么有模棱两可的lexer规则

根据我使用antlr的经验,lexer规则通常没有任何语义含义;它们只是与某种正则表达式匹配的文本。因此,我不需要使用
变量
方法名
等,而只需要使用
标识符
,然后在更高的层次上进行计算

换句话说,似乎(从我从你的问题中收集到的一点信息)你可以从用语法规则替换
UNIT
CONVERT
中获益,或者只使用一条规则:

conversion: NUMBER TEXT TEXT TEXT
以及验证ANTLR listener/tree walker/etc中的文本值

编辑

感谢您使用lexer规则更新您的问题。现在很清楚为什么它失败了——正如BernardK指出的,antlr总是选择第一个匹配的lexer规则。这意味着两个模棱两可的lexer规则中的第二个不可能匹配,这使得您提出的设计不可行

我的观点是lexer规则不是做单元验证之类事情的正确层;他们擅长结构,而不是内容。评估解析树比尝试扭曲antlr语法要实际得多


最后,您还可以对解析规则执行嵌入操作,比如根据一组已知的单元验证ID标记的值。它可以工作,但会破坏语法的可重用性。

根据您问题中的信息,很难说最好的解决方案是什么-例如,我不知道您的lexer规则是什么-我也不知道您为什么有模棱两可的lexer规则

根据我使用antlr的经验,lexer规则通常没有任何语义含义;它们只是与某种正则表达式匹配的文本。因此,我不需要使用
变量
方法名
等,而只需要使用
标识符
,然后在更高的层次上进行计算

换句话说,似乎(从我从你的问题中收集到的一点信息)你可以从用语法规则替换
UNIT
CONVERT
中获益,或者只使用一条规则:

conversion: NUMBER TEXT TEXT TEXT
以及验证ANTLR listener/tree walker/etc中的文本值

编辑

感谢您使用lexer规则更新您的问题。现在很清楚为什么它失败了——正如BernardK指出的,antlr总是选择第一个匹配的lexer规则。这意味着两个模棱两可的lexer规则中的第二个不可能匹配,这使得您提出的设计不可行

我的观点是lexer规则不是做单元验证之类事情的正确层;他们擅长结构,而不是内容。评估解析树比尝试扭曲antlr语法要实际得多


最后,您还可以对解析规则执行嵌入操作,比如根据一组已知的单元验证ID标记的值。它可以工作,但会破坏语法的可重用性。

当输入匹配两个lexer规则时,ANTLR会选择最长的或第一个,请参阅。根据您的语法,中的
将被解释为
单位
,从不
转换
,以及规则

conversion: NUMBER UNIT CONVERT UNIT;
无法工作,因为有三个
UNIT
令牌:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:3='in',<UNIT>,1:2]
[@3,4:4=' ',<WS>,channel=1,1:4]
[@4,5:6='in',<UNIT>,1:5]
[@5,7:7=' ',<WS>,channel=1,1:7]
[@6,8:13='meters',<UNIT>,1:8]
[@7,14:14='\n',<NL>,1:14]
[@8,15:14='<EOF>',<EOF>,2:0]
Question last update 0159
line 1:5 missing 'in' at 'in'
line 1:8 mismatched input 'meters' expecting <EOF>
执行:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:3='in',<ID>,1:2]
[@3,4:4=' ',<WS>,channel=1,1:4]
[@4,5:6='in',<ID>,1:5]
[@5,7:7=' ',<WS>,channel=1,1:7]
[@6,8:13='meters',<ID>,1:8]
[@7,14:14='\n',<NL>,1:14]
[@8,15:14='<EOF>',<EOF>,2:0]
Question last update 0132
Quantity 1 in to convert in meters
$grun Question Question-tokens-diagnostics input.txt
[@0,0:0='1',,1:0]
[@1,1:1='',通道=1,1:1]
[@2,2:3='in',1:2]
[@3,4:4='',频道=1,1:4]
[@4,5:6='in',1:5]
[@5,7:7='',频道=1,1:7]
[@6,8:13='meters',1:8]
[@7,14:14='\n',1:14]
[@8,15:14='',,2:0]
问题最后更新0132
以米为单位换算的1英寸数量

标签可从访问者中规则的上下文中获得,因此很容易区分相同类型的标记。

当输入匹配两个lexer规则时,ANTLR选择最长或第一个,请参阅。根据您的语法,
中的
将被解释为
单位
,从不
转换
,以及规则

conversion: NUMBER UNIT CONVERT UNIT;
无法工作,因为有三个
UNIT
令牌:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:3='in',<UNIT>,1:2]
[@3,4:4=' ',<WS>,channel=1,1:4]
[@4,5:6='in',<UNIT>,1:5]
[@5,7:7=' ',<WS>,channel=1,1:7]
[@6,8:13='meters',<UNIT>,1:8]
[@7,14:14='\n',<NL>,1:14]
[@8,15:14='<EOF>',<EOF>,2:0]
Question last update 0159
line 1:5 missing 'in' at 'in'
line 1:8 mismatched input 'meters' expecting <EOF>
执行:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:3='in',<ID>,1:2]
[@3,4:4=' ',<WS>,channel=1,1:4]
[@4,5:6='in',<ID>,1:5]
[@5,7:7=' ',<WS>,channel=1,1:7]
[@6,8:13='meters',<ID>,1:8]
[@7,14:14='\n',<NL>,1:14]
[@8,15:14='<EOF>',<EOF>,2:0]
Question last update 0132
Quantity 1 in to convert in meters
$grun Question Question-tokens-diagnostics input.txt
[@0,0:0='1',,1:0]
[@1,1:1='',通道=1,1:1]
[@2,2:3='in',1:2]
[@3,4:4='',频道=1,1:4]
[@4,5:6='in',1:5]
[@5,7:7='',频道=1,1:7]
[@6,8:13='meters',1:8]
[@7,14:14='\n',1:14]
[@8,15:14='',,2:0]
问题最后更新0132
以米为单位换算的1英寸数量

标签可以从访问者中规则的上下文中获得,因此很容易区分相同类型的令牌。

我在示例中添加了lexer规则,以使其更加清晰。捕获lexer规则中的所有文本并在访问者中手动解析,这会破坏使用Antlr的目的。将lexer规则移动到语法规则会起作用,但会使语法难以阅读:
unit:'m'e't'e'r'|我在示例中添加了lexer规则以使其更加清晰。捕获lexer规则中的所有文本并在访问者中手动解析,这会破坏使用Antlr的目的。将lexer规则移动到语法规则会起作用,但会使语法难以阅读:
unit:'m'e't'e'r'|