2014-11-01 51 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之前,因此获胜。

经验法则:首先是更具体的词法分析规则。不要在分析器规则中隐式创建新的词法分析标记。

如果你检查令牌类型,你会得到一个线索是怎么回事。