编写 antlr 语法,其中空格有时很重要

writing an antlr grammar where whitespace is sometimes significant

这是一个虚拟示例,我的实际语言更复杂:

grammar wordasnumber;

WS: [ \t\n] -> skip;
AS: [Aa] [Ss];
ID: [A-Za-z]+;
NUMBER: [0-9]+;

wordAsNumber: (ID AS NUMBER)* EOF;

在这种语言中,这两个字符串是合法的:

这正是我告诉它要做的,但不是我想要的。因为 IDAS 都是字母串,中间需要白色 space ,我想要第二个短语 成为语法错误。我可以添加一些其他规则来尝试匹配这些混搭的东西......

fragment LETTER: [A-Za-z];
fragment DIGIT: [0-9];
BAD_THING: ( LETTER+ DIGIT (LETTER|DIGIT)* ) | ( DIGIT+ LETTER (LETTER|DIGIT)* );
ID: LETTER+;
NUMBER: DIGIT+;

... 使词法分析器 return 成为这些粉碎的东西的不同标记,但这感觉就像一个奇怪的创可贴,有点意外地发现了需要,如果我真的盯着看,也许还有更多非常仔细地检查我的词法分析器。

有更好的方法吗?我的实际语法要大得多,因此,例如,不跳过 WS 并将其显式放置在需要它的标记之间是非启动器。

这个列表上有一个较旧的问题,我找不到,我认为这是同一个问题,在那种情况下,解析白色 space 分隔数字的人感到惊讶 1.2.3 被解析为 1.2.3 而不是语法错误。

为错误的输入添加另一条规则,但不要在您的解析器中使用它。然后在匹配的时候会导致语法错误:

INVALID: (ID | NUMBER)+;

此附加规则会将问题输入的解析树输出更改为:

这个技巧之所以有效,是因为 ANTLR4 的词法分析方法试图匹配正在进行中的最长输入,并且 INVALID 规则比 IDNUMBER 单独匹配更多。但是你必须把它放在这两条规则之后,才能使用另一个词法分析规则:“如果两个词法分析器规则匹配相同的输入,选择第一个。”。通过这种方式,您可以获得 IDNUMBER.

单次出现的正确标记