如何在Antlr

时间:2017-07-27 00:22:25

标签: parsing conditional antlr antlr4

我写了下面的语法,应该检查条件表达式。 下面的例子是我想用这个语法实现的目标:

test无效
test = 1有效的 test = 1 and another_test>=0.2有效的 test = 1 kasd y = 1无效(两个条件必须用AND / OR分隔)
a = 1 or (b=1 and c)无效(不能有像'c'这样孤独的字符。它应该总是一个三元组。即文字运算符字面意思

grammar expression;

expr
 : literal_value
 | expr ( '='|'<>'| '<' | '<=' | '>' | '>=' ) expr
 | expr K_AND expr
 | expr K_OR expr
 | function_name '(' ( expr ( ',' expr )* | '*' )? ')'
 | '(' expr ')'
 ;

literal_value
 : NUMERIC_LITERAL
 | STRING_LITERAL
 | IDENTIFIER
 ;


keyword
 : K_AND
 | K_OR
;

name
 : any_name
 ;

function_name
 : any_name
 ;

database_name
 : any_name
 ;

table_name
 : any_name
 ;

column_name
 : any_name
 ;

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


K_AND : A N D;
K_OR : O R;

IDENTIFIER
 : '"' (~'"' | '""')* '"'
 | '`' (~'`' | '``')* '`'
 | '[' ~']'* ']'
 | [a-zA-Z_] [a-zA-Z_0-9]*
 ;

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

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


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];

WS: [ \n\t\r]+ -> skip;

所以我的问题是,如何让语法适用于上面提到的例子?我们可以在两个三元组之间强制使用某些单词(文字运算符字面值)吗?从某种意义上说,我只是想让一个解析器来验证where子句条件,但只允许简单的条件和函数。我还想让一个访问者在Java中检索函数,括号,任何文字等值,如何实现呢?

1 个答案:

答案 0 :(得分:1)

是和否。

您可以将语法更改为仅允许相同的表达式和逻辑运算:

expr
 : term ( '='|'<>'| '<' | '<=' | '>' | '>=' ) term
 | expr K_AND expr
 | expr K_OR expr
 | '(' expr ')'
 ;

term
 : literal_value
 | function_name '(' ( expr ( ',' expr )* | '*' )? ')'
 ;

如果你想允许布尔变量或函数,问题就出现了 - 你需要对词法分析器中的函数/变量进行分类,并为每个变量分配一个不同的终端,这很棘手且容易出错。

相反,通常最好不要在解析器中进行这种检查 - 让你的解析器允许并接受类似表达式的任何东西,并为它生成表达式树。然后在树上有一个单独的传递(称为类型检查器),它检查操作操作数的类型和函数的参数。

后一种方法(使用单独的类型检查器)通常最简单,更清晰,更灵活,并提供更好的错误消息(而不仅仅是语法错误&#39;)。