编写 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;
在这种语言中,这两个字符串是合法的:
seven as 7 eight as 8
seven as 7eight as8
这正是我告诉它要做的,但不是我想要的。因为 ID 和 AS 都是字母串,中间需要白色 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
规则比 ID
和 NUMBER
单独匹配更多。但是你必须把它放在这两条规则之后,才能使用另一个词法分析规则:“如果两个词法分析器规则匹配相同的输入,选择第一个。”。通过这种方式,您可以获得 ID
和 NUMBER
.
单次出现的正确标记
这是一个虚拟示例,我的实际语言更复杂:
grammar wordasnumber;
WS: [ \t\n] -> skip;
AS: [Aa] [Ss];
ID: [A-Za-z]+;
NUMBER: [0-9]+;
wordAsNumber: (ID AS NUMBER)* EOF;
在这种语言中,这两个字符串是合法的:
seven as 7 eight as 8
seven as 7eight as8
这正是我告诉它要做的,但不是我想要的。因为 ID 和 AS 都是字母串,中间需要白色 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
规则比 ID
和 NUMBER
单独匹配更多。但是你必须把它放在这两条规则之后,才能使用另一个词法分析规则:“如果两个词法分析器规则匹配相同的输入,选择第一个。”。通过这种方式,您可以获得 ID
和 NUMBER
.