我希望匹配多个函数以接受逗号分隔的占位符列表,然后接受单元的定义,该单元再次由其余参数的逗号分隔。要解析的文本看起来像示例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给出了错误“行1:18不匹配输入'EURO'期待UNIT”。据我了解,这意味着“EURO”本身与UNIT的模式不匹配,但“EURO_CENT”的确如此。我不明白为什么会这样,因为UNIT的模式说“_CENT”部分是可选的,只有第一部分是强制性的。
我还尝试通过将Unit的模式更改为UNIT: 'Unit.' TEXT ('_' TEXT)*;
来向UNIT提供一些前缀(在本例中为“Unit。”)。
我相应地将输入字符串更改为"produkt([F1],[F2],Unit.EURO)"
,这就像魅力一样
然而,第二种方法不是非常用户友好,因为我们必须添加一些(在我们看来)不必要的输入。所以问题是:当UNIT-String是单个单词时,为什么第一个选项与预期不匹配?是否有解决方法?
答案 0 :(得分:1)
简短的回答是PLACE
和UNIT
对于仅匹配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.
BTW,Antlr通常会自上而下地评估其语法,因此混合您的规则就像实际上混淆了逻辑一样。