ANTLR似乎在混淆规则

时间:2019-02-27 20:22:40

标签: antlr4

要重现的最小语法:

grammar GeneralSearchQuery;

id : ID;
ID : ('A'[A-Z0-9]+);

anystring: ANYSTRING;

ANYSTRING: ~[ \t\r\n"\\'():^]+;

问题出在“ anystring”规则上。如果我删除任何ID / ID规则,那么奇怪的解析就会消失。

目的是匹配任何(unicode,非unicode),但某些具有含义的字符除外。

据我了解,这就是它的分解方式:

~       Negate the following pattern
[       Start of a matching group
        Match a literal space 
    \t  Tab character
    \r  Newline character
    \n  Newline character
    "   Double quote character
    \\  backslash character
    '   Single quote character
    (   Left parenthesis
    )   Right parenthesis
    :   Colon character
    ^   Caret character
]       End of a matching group
+       Match the preceeding one or more times
A - match
AA - no match (BAD!)
ASDF - no match (BAD!)
SDF - match
Asdf - match

如此看来,任何以大写字母A开头并以任何其他大写字母开头的字符串都无法解析。似乎正在将规则更改为NOT match id

关于我可能会缺少的任何想法吗?

1 个答案:

答案 0 :(得分:1)

在词法分析阶段,将根据语法中的词法规则将输入拆分为标记。此阶段不受解析器规则中发生的任何事情影响。也就是说,无论解析器执行什么操作或所需的令牌类型如何,词法分析器对于给定的输入将始终使用相同的令牌序列。

因此,要查看为给定输入生成的标记顺序,我们只需要查看语法中定义的词汇规则,其中就有两个:

ID : ('A'[A-Z0-9]+);
ANYSTRING: ~[ \t\r\n"\\'():^]+;

现在,这两个规则明显重叠:ID可以匹配的任何内容,ANYSTRING也可以匹配的任何内容。在这种情况下,将适用最大限制规则,即:

  1. 如果多个规则可以产生匹配项,则使用产生更长匹配项的规则
  2. 如果多个规则产生相同长度的匹配项,则使用语法中第一个匹配的规则。

因此,根据这些规则,任何以A开头且不包含只能由ANYSTRING匹配的字符的输入都将产生ID令牌。

如果您还希望anystring规则也匹配有效的标识符,则需要将其定义为:

anystring: ID | ANYSTRING;