在ANTLR4解析器中向后匹配子规则

时间:2014-09-11 15:59:15

标签: parsing antlr4

我有一部分ANTLR4规则,我想向后解析。我怀疑这不是真正的解决方案,所以我可能会缺少一些东西。

我的问题的症结在于,我想要提取的表达中间有一部分。但是,如果可能的话,这部分有一些(定义的)后缀我真的想单独提取。这些后缀可以用逗号分隔或不用;语法可以正常使用逗号,但是如果逗号丢失,则整个部分都为unknown,即使后缀存在也是如此。

我把我的语法简化成一个小例子,可以在这篇帖子的底部看到。

给定字符串why hello, x y z foo bar baz blah blah blah, goodbye!,我的语法将x y z foo bar baz解析为phrase。我希望将x y zunknownfoo bar baz匹配作为后缀。如果有逗号(x y z, foo bar baz),则有效: tree generated with comma

但是,如果没有逗号,则整个x y z foo bar baz(以及之后的一些文字)为unknowntree generated with no comma

我尝试将unknown更改为不同意(+?),但这也是不受欢迎的,只消耗phrase的一个令牌: tree generated with no comma and nongreedy unknown

有没有办法强制phrase规则首先尝试匹配右边的后缀,然后再回到unknown

另一种说法:当结束带有一个或多个后缀时,有没有办法unknown匹配之外的任何内容? (后缀可以出现在文本中,只要它们不在最后)

示例语法:

grammar Example;

// parse tree root
exampleExpression : ignored HELLO separator phrase separator? unknown separator? GOODBYE ignored;

// what I want to match
phrase : unknown (COMMA? suffix+)*;

// convenience rule for swaths of tokens to be ignored (e.g. at the beginning and end)
ignored : (unknown | separator)*;

// roll up unknown tokens under one rule
unknown : (~(PERIOD | COMMA | PIPE | BULLET | SP_SEP_DASH))+;
separator : PERIOD | COMMA | PIPE | BULLET | SP_SEP_DASH;

// the pre-defined suffixes
suffix : FOO | BAR | BAZ;

/* TOKENS */

HELLO : 'hello';
GOODBYE : 'goodbye';
FOO : 'foo';
BAR : 'bar';
BAZ : 'baz';

/* FRAGMENTS */

fragment DIGIT : [0-9];
fragment DASH : '-';

/* REMAINING TOKENS */

LPAREN : '(' ;
RPAREN : ')' ;
COMMA : ',';
PERIOD : '.';
PIPE : '|';
BULLET : '\u00B7' | '\u2219' | '\u22c5';
SP_SEP_DASH : SP DASH SP;

SP : [ \u000B\t\r\n] -> channel(HIDDEN);

NUMBER : ([0] | [1-9] DIGIT*) ('.' DIGIT+)?;
WORD : [A-Za-z] [A-Za-z-]*;

// catch-all
OTHER : .;

1 个答案:

答案 0 :(得分:1)

问题是:

  

另一种说法:除了以一个或多个后缀结尾之外,有没有办法让未知匹配? (后缀可以在文字中出现,只要它们不在最后)

但之前,有unknown内部后缀的解析被拒绝了:

  

但是,如果没有逗号,则将整个x y z foo bar baz(以及之后的一些文本)视为未知

这似乎不一致。

从示例中,您似乎正在尝试进行自然语言解析;无论它的优点如何,ANTLR可能都不是一个好的工具。但这可能只是基于你的简化的幻想。

无论如何,原始问题的答案 - "是否可以将非终端定义为任何序列的令牌,这些令牌不会以后缀类中的一个或多个令牌结束&# 34;是的,是的,这可以写成无上下文语法"。在没有涉及ANTLR细节的情况下,这是一个简单的CFG:

wordlist: /* empty */ | wordlist non_suffix | wordlist suffix_list non_suffix ;
suffix_list: suffix | suffix_list suffix ;