antlr4:对空白处理感到困惑

时间:2014-11-13 12:00:10

标签: whitespace antlr4 lexical-analysis

我知道这个问题以前或多或少都有过同样的问题,但没有一个答案对我有用:

grammar Problem;
top: (IDENT | INT)*;
IDENT: (ALPHA|'_') (ALPHA|DIGIT|'_')*;
INT: DEC_INT | HEX_INT;
DEC_INT: (ZERO | (NZERO_DIGIT DIGIT*));
HEX_INT: ZERO X HEX+;
ZERO: '0';
NZERO_DIGIT: '1'..'9';
DIGIT: '0'..'9';
ALPHA: [a-zA-Z];
HEX: [0-9a-fA-F];
X: [xX];
WS: [ \t\r\n]+ -> skip;

当我将此输入提供给解析器时:

0xFF ZZ123

后跟换行符和ctrl-D,它被解析为:

(top 0xFF ZZ123)

这是预期的行为。

但是,当我将此输入提供给解析器时:

0xFFZZ123

后跟换行符和ctrl-D,它被解析为:

(top 0xFF ZZ123)

这完全没有意图。我希望这会触发词法分析器错误,将其视为拼写错误的HEX_INT。

如果我禁用空格跳过,我仍然会得到相同的词法分析器行为(将一组字符解析为两个标记),但是由于现在向解析器报告了WS标记,因此出现以下错误:

0XFFZZ123
line 1:9 extraneous input '\n' expecting {<EOF>, IDENT, INT}
(top 0XFF ZZ123 \n)

另外我不能再输入空格分隔的标记了(正常,因为top没有提到WS):

0XFF ZZ123
line 1:4 extraneous input ' ' expecting {<EOF>, IDENT, INT}
(top 0XFF   ZZ123)

我试图通过禁用空格跳过并将顶级规则更改为:

来修复语法
top: WS* (IDENT | INT) (WS+ (IDENT|INT))* WS*;

但是,如果我将以下流输入解析器,

0xFF ZZ123 0XFFZZ123                                              

我收到此错误:

line 1:20 extraneous input 'ZZ123' expecting {<EOF>, WS}                                        
(top     0xFF   ZZ123     0xFF ZZ123 \n)

你仍然可以看到最后一个输入标记已经被分割为OxFF和ZZ123,而我真的会在这里触发一个lexing错误,而不是必须明确处理解析器中的空格。

那么我必须使用哪些技巧组合来获得所需的行为?

1 个答案:

答案 0 :(得分:1)

您可以编写一个接受错误令牌(如0XFFZZ123)的令牌,并将其置于WS之前。例如:

grammar SandBox;
top: (IDENT | INT)*;
IDENT: (ALPHA|'_') (ALPHA|DIGIT|'_')*;
INT: DEC_INT | HEX_INT;
DEC_INT: (ZERO | (NZERO_DIGIT DIGIT*));
HEX_INT: ZERO X HEX+;
ZERO: '0';
NZERO_DIGIT: '1'..'9';
DIGIT: '0'..'9';
ALPHA: [a-zA-Z];
HEX: [0-9a-fA-F];
X: [xX];

ERROR_TOKEN: (~[ \t\r\n])+;

WS: [ \t\r\n]+ -> skip;

以下是发生的事情。如果你输入0xFF ZZ123,那么INT和IDENT因为它们的位置而获胜。如果输入0XFFZZ123,则ERROR_TOKEN因长度(长度优先于位置)而获胜。由于ERROR_TOKEN不是&#34; top&#34;的一部分,因此会引发错误。

我希望这能解决问题。