【问题标题】:ANTLR4 Token is not recognized when substitutedANTLR4 令牌在替换时无法识别
【发布时间】:2014-11-01 08:19:02
【问题描述】:

我尝试修改 sqlite 语法的语法(我只对 where 子句的变体感兴趣)并且在将 AND 替换为它自己的标记时,我一直遇到一个奇怪的错误。

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>)

我错过了什么?

【问题讨论】:

    标签: antlr antlr4 ebnf


    【解决方案1】:

    我认为“and”是一个 IDENTIFIER,因为 IDENTIFIER 规则在 AND 规则之前,因此获胜。

    如果您在解析器规则中写入“和”,这会隐式创建一个标记(不是 AND!),它位于 IDENTIFIER 之前并因此获胜。

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

    如果您检查令牌类型,您就会知道发生了什么。

    【讨论】:

      猜你喜欢
      • 2022-12-09
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 2016-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多