2014-11-01 48 views
0

我嘗試修改sqlite語法的語法(我只對where子句的變體感興趣),並且在將AND代入自己的令牌時保持奇怪的錯誤。ANTLR4令牌被取代時不被識別

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的規則出現在AND的規則之前,因此獲勝。

如果在解析器規則中寫入'和',則會隱式創建一個標識符(不是!),該標記符號位於IDENTIFIER之前,因此獲勝。

經驗法則:首先是更具體的詞法分析規則。不要在分析器規則中隱式創建新的詞法分析標記。

如果你檢查令牌類型,你會得到一個線索是怎麼回事。