在antlr4

时间:2015-11-30 10:51:23

标签: regex antlr 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给出了错误“行1:18不匹配输入'EURO'期待UNIT”。据我了解,这意味着“EURO”本身与UNIT的模式不匹配,但“EURO_CENT”的确如此。我不明白为什么会这样,因为UNIT的模式说“_CENT”部分是可选的,只有第一部分是强制性的。
我还尝试通过将Unit的模式更改为UNIT: 'Unit.' TEXT ('_' TEXT)*;来向UNIT提供一些前缀(在本例中为“Unit。”)。 我相应地将输入字符串更改为"produkt([F1],[F2],Unit.EURO)",这就像魅力一样 然而,第二种方法不是非常用户友好,因为我们必须添加一些(在我们看来)不必要的输入。所以问题是:当UNIT-String是单个单词时,为什么第一个选项与预期不匹配?是否有解决方法?

1 个答案:

答案 0 :(得分:1)

简短的回答是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.
BTW,Antlr通常会自上而下地评估其语法,因此混合您的规则就像实际上混淆了逻辑一样。