2014-11-01 1 views
0

Я пытаюсь изменить грамматику синтаксиса sqlite (меня интересует только вариант предложения where), и я сохраняю странную ошибку при подстановке AND в свой собственный токен ,ANTLR4 Token не распознается при замене

grammar wtfql; 

/* 
    SQLite understands the following binary operators, in order from highest to 
    lowest precedence: 

    || 
    * / % 
    + - 
    << >> & | 
    < <= > >= 
    = != <> IS IS NOT IN LIKE GLOB MATCH REGEXP 
    AND 
    OR 
*/ 

start : expr EOF?; 

expr 
: literal_value 
    //BIND_PARAMETER 
| (table_name '.')? column_name 
| unary_operator expr 
| expr '||' expr 
| expr ('*' | '/' | '%') expr 
| expr ('+' | '-') expr 
| expr ('<' | '<=' | '>' | '>=') expr 
| expr ('=' | '<>' | K_IN) expr 
| expr K_AND expr 
| expr K_OR expr 
| function_name '(' (expr (',' expr)*)? ')' 
| '(' expr ')' 
| expr K_NOT expr 
| expr (K_NOT K_NULL) 
| expr K_NOT? K_IN ('(' (expr (',' expr)*) ')') 
; 


unary_operator 
: '-' 
| '+' 
| K_NOT 
; 

literal_value 
: NUMERIC_LITERAL 
| STRING_LITERAL 
| K_NULL 
; 

function_name 
: IDENTIFIER 
; 

table_name 
: any_name 
; 

column_name 
: any_name 
; 

any_name 
: IDENTIFIER 
| keyword 
// | '(' any_name ')' 
; 

keyword 
: K_AND 
| K_NOT 
| K_NULL 
| K_IN 
| K_OR 
; 

IDENTIFIER 
: [a-zA-Z_] [a-zA-Z_0-9]* // TODO check: needs more chars in set 
; 

NUMERIC_LITERAL 
: DIGIT+ ('.' DIGIT*)? (E [-+]? DIGIT+)? 
| '.' DIGIT+ (E [-+]? DIGIT+)? 
; 

STRING_LITERAL 
: '\"' (~'\"' | '\"\"')* '\"' 
; 

SPACES 
: [ \u000B\t\r\n] -> channel(HIDDEN) 
; 

DOT : '.'; 
OPEN_PAR : '('; 
CLOSE_PAR : ')'; 
COMMA : ','; 
STAR : '*'; 
PLUS : '+'; 
MINUS : '-'; 
TILDE : '~'; 
DIV : '/'; 
MOD : '%'; 
AMP : '&'; 
PIPE : '|'; 
LT : '<'; 
LT_EQ : '<='; 
GT : '>'; 
GT_EQ : '>='; 
EQ : '='; 
NOT_EQ2 : '<>'; 

K_AND : A N D; 
K_NOT : N O T; 
K_NULL : N U L L; 
K_OR : O R; 
K_IN : I N; 

fragment DIGIT : [0-9]; 

fragment A : [aA]; 
fragment B : [bB]; 
fragment C : [cC]; 
fragment D : [dD]; 
fragment E : [eE]; 
fragment F : [fF]; 
fragment G : [gG]; 
fragment H : [hH]; 
fragment I : [iI]; 
fragment J : [jJ]; 
fragment K : [kK]; 
fragment L : [lL]; 
fragment M : [mM]; 
fragment N : [nN]; 
fragment O : [oO]; 
fragment P : [pP]; 
fragment Q : [qQ]; 
fragment R : [rR]; 
fragment S : [sS]; 
fragment T : [tT]; 
fragment U : [uU]; 
fragment V : [vV]; 
fragment W : [wW]; 
fragment X : [xX]; 
fragment Y : [yY]; 
fragment Z : [zZ]; 

написание

| expr K_AND expr 

с входом

field1=1 and field2 = 2 

Результаты в

line 1:8 mismatched input 'and' expecting {<EOF>, '||', '*', '+', '-', '/', '%', '<', '<=', '>', '>=', '=', '<>', K_AND, K_NOT, K_OR, K_IN} 

в то время как

| expr 'and' expr 

работает как шарм:

$ antlr4 wtfql.g4 && javac -classpath /usr/local/Cellar/antlr/4.4/antlr-4.4-complete.jar wtfql*.java && cat test.txt | grun wtfql start -tree -gui 

(start (expr (expr (expr (column_name (any_name feld1))) = (expr (literal_value 1))) and (expr (expr (column_name (any_name feld2))) = (expr (literal_value 2)))) <EOF>) 

Что мне не хватает?

ответ

0

Я предполагаю, что «и» является ИДЕНТИФИКАЦИЕЙ, поскольку правило для ИДЕНТИФИКАРА приходит перед правилом для И и таким образом выигрывает.

Если вы пишете 'и' в правиле анализатора, это неявно создает токен (не И!), Который предшествует IDENTIFIER и таким образом выигрывает.

Правило большого пальца: более конкретные правила лексера. Не следует создавать новые лексеры-лексеры неявно в правилах парсера.

Если вы отметите тип токена, вы поймете, что происходит.