测试以下简单语法。
grammar SQL;
selectStatement: SELECT selectElements EOF;
selectElements: (star='*' | ID ) (',' ID)*;
ID: ID_LITERAL;
WS: [ \t\r\n]+ -> channel(HIDDEN);
fragment ID_LITERAL: [A-Z_$0-9]*? [A-Z_$]+? [A-Z_$0-9]*;
SELECT: 'SELECT';
给出输入SELECT *
会产生以下错误:
line 1:0 missing 'SELECT' at 'SELECT'
line 1:7 extraneous input '*' expecting <EOF>
在SELECT
中将selectStatement
标识符更改为内联文字时,将产生以下语法,该语法将解析相同的输入而不会出错。为什么?
grammar SQL;
selectStatement: 'SELECT' selectElements EOF;
selectElements: (star='*' | ID ) (',' ID)*;
ID: ID_LITERAL;
WS: [ \t\r\n]+ -> channel(HIDDEN);
fragment ID_LITERAL: [A-Z_$0-9]*? [A-Z_$]+? [A-Z_$0-9]*;
答案 0 :(得分:0)
模式[A-Z_$0-9]*? [A-Z_$]+? [A-Z_$0-9]*
和'SELECT'
在输入SELECT *
上都匹配,并且它们都产生相同长度的匹配(即,它们都匹配SELECT
,然后离开{ {1}}作为其余输入)。在这种情况下,ANTLR(像大多数词法生成器一样)将应用语法中的第一条规则。在您的第一个语法中,*
。因此ID
的词法是SELECT *
,而不是ID, WS, '*'
。
如果将规则SELECT, WS, '*'
移到SELECT: 'SELECT';
的定义之前,它将按您的意愿运行。