在 antlr4 中解析带有可选后缀的字符串时出现意外行为

Unexpected behaviour when parsing a string with optional Suffix in antlr4

我想匹配多个函数以接受以逗号分隔的占位符列表,然后是单元的定义,它与其余参数再次以逗号分隔。要解析的文本类似于示例 1:"produkt([F1],[F2],EURO_CENT)" 或示例 2:"produkt([F1],[F2],EURO)"

我希望它能正常工作的语法是这样的:

[...]

term: [...]
    | 'produkt(' placeholder ',' placeholder ',' UNIT ')' #MultUnit
    [...]
    | placeholder #PlaceholderTwo
    ;

WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

LBRACK: '[';
RBRACK: ']';
PLACE: TEXT+ NUMBER?;

placeholder: LBRACK PLACE+ RBRACK;

[..]

UNIT: TEXT (('_' TEXT)*)?;

TEXT: ('a' .. 'z' | 'A' .. 'Z')+;//[a-zA-Z]+;

[...]

使用此语法示例 1 按预期工作,但示例 2 给出了错误 "line 1:18 mismatched input 'EURO' expecting UNIT"。据我了解,这意味着 "EURO" 本身与 UNIT 的模式不匹配,但 "EURO_CENT" 匹配。我不明白为什么会这样,因为 UNIT 的模式表明“_CENT”部分是可选的,只有第一部分是强制性的。
我还尝试通过将 Unit 的模式更改为 UNIT: 'Unit.' TEXT ('_' TEXT)*;
来为 UNIT 提供一些前缀(在本例中为 "Unit.") 我相应地将输入字符串更改为 "produkt([F1],[F2],Unit.EURO)",这非常匹配。
然而,第二种方法对用户来说不是很友好,因为我们必须在输入中添加一些(在我们看来)不必要的东西。所以问题是:当 UNIT-String 是单个单词时,为什么第一个选项与预期不匹配,是否有解决方法?

简短的回答是 PLACEUNIT 对于只匹配 TEXT 的内容是相互不明确的。如果样本输入是规范的,则更改 PLACE 规则以消除歧义:

PLACE : TEXT+ NUMBER ;

其他可能性包括将 PLACE 重新定义为

PLACE : LBRACK TEXT+ NUMBER? RBRACK; // adjust other rules accordingly

向规则添加谓词:

PLACE : {followsLBRACK()}? TEXT+ NUMBER ;

并重新定义 UNIT

UNIT: TEXT ( 'S' | ( '_' TEXT )+ ) ; // EUROS or EURO_CENT; similar for other units.

顺便说一句,Antlr 通常自上而下地评估其语法,因此混合您的规则实际上会混淆逻辑。