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

Parsing 在ANTLR4解析器中向后匹配子规则,parsing,antlr4,Parsing,Antlr4,我有一部分ANTLR4规则,我想向后解析。我怀疑这不是真正的解决方案,所以我可能遗漏了一些东西 我的问题的症结在于我的表达中有一部分是我想提出来的。然而,如果可能的话,这部分有一些(定义的)后缀,我真的很想单独提取。这些后缀可以用逗号分隔,也可以不用逗号;语法可以使用逗号,但如果缺少逗号,则会将整个部分视为未知,即使后缀存在 我已经把我的语法简化成一个小例子,可以在这篇文章的底部看到 给定字符串为什么你好,x y z foo bar baz等等,再见,我的语法将把xyzfoobarbaz解析为短

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

我的问题的症结在于我的表达中有一部分是我想提出来的。然而,如果可能的话,这部分有一些(定义的)后缀,我真的很想单独提取。这些后缀可以用逗号分隔,也可以不用逗号;语法可以使用逗号,但如果缺少逗号,则会将整个部分视为
未知
,即使后缀存在

我已经把我的语法简化成一个小例子,可以在这篇文章的底部看到

给定字符串
为什么你好,x y z foo bar baz等等,再见,我的语法将把
xyzfoobarbaz
解析为
短语
。我想将
xyz
匹配为
unknown
foobarbaz
作为后缀。如果有一个逗号(
xyz,foo-bar-baz
),它可以工作:

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

我尝试将
unknown
更改为nongredy(
+?
),但这也是不可取的,因为
短语
只使用一个令牌:

是否有办法强制
短语
规则在返回到
未知
之前先尝试从右开始匹配后缀?

另一种说法是:
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 : .;
问题是:

另一种说法是:除了以一个或多个后缀结尾外,有没有一种方法可以让未知匹配任何东西?(后缀可以出现在文本中,只要它们不在末尾)

但在此之前,使用内部后缀解析
未知
,被拒绝:

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

这似乎前后矛盾

从这个例子来看,您似乎正在尝试进行自然语言解析;无论ANTLR有什么优点,它都可能不是一个很好的工具。但根据你的简化,这可能只是一种幻想

在任何情况下,对您的原始问题——“是否可以将非终结符定义为不以后缀类中的一个或多个标记结尾的任何标记序列”的答案是“是的,可以编写为上下文无关语法”。在不涉及ANTLR细节的情况下,这里有一个简单的CFG:

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

胡乱猜测:
短语:未知逗号?(后缀+)*而不是
短语:未知(逗号?后缀+)*
@500 InternalServerError:当然
(后缀+*
后缀*
相同,但我想真正需要的是
后缀+
,可能中间有逗号。IOW:
逗号?(后缀+逗号)*后缀+
。但我不认为这是这里的根本问题。我的观点是,
短语
似乎只接受
后缀
,如果
逗号
也存在。对,
短语
(逗号?后缀+*
来支持
x y z,foo,bar,baz
这样的短语。后缀并不总是存在,因此
*
而不是
+
。FWIW,如果我忽略多个逗号的情况,
unknown逗号?后缀*
表现出同样的问题。当我说“但是,如果没有逗号,它会将整个x y z foo bar baz(以及后面的一些文本)视为未知”时,我的意思是这就是正在发生的事情,尽管这是不希望发生的。在这种情况下,我希望
未知
后缀
未知
。不过,我可以看出这可能很难理解,除非它以某种方式被向后解析(或者这是我的想法)。谢谢你的建议。我会把这当作一个起点来处理。@NickAldwin:我明白。但是在您的需求中,您说如果unknown不在末尾,那么它可以包含后缀(在我的引用中突出显示)。然后你抱怨你的语法接受了不在结尾的后缀的未知。这就是矛盾。如果您希望后缀被解析为后缀,而不管它们出现在哪里,那么语法是很简单的。如果你有其他的期望,你需要对它们更加精确。明白了,解析器无法理解
未知
后缀
未知
未知(后缀在中间)
@NickAldwin:不理解这种差异的不仅仅是解析器。我不明白其中的区别:)