2017-07-27 94 views
0

我编写了下面的应检查条件表达式的语法。下面 例子是我想用这个语法要达到什么:如何在Antlr中强制执行某些规则

test无效
test = 1有效
test = 1 and another_test>=0.2有效
test = 1 kasd y = 1无效(两个条件都必须通过分离和/或)
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

是和否。

您可以将语法更改为仅允许在同一比较和逻辑运算表达式:

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

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

问题来,如果你想允许布尔变量或函数 - 你需要的功能分类/ vars在你的词法分析器中,并且每个都有一个不同的终端,这是棘手和容易出错的。

相反,它是一般最好不要做这种在解析器检查 - 有了解析器是宽容和接受任何表情状,并为它生成一个表达式树。然后有一个单独的遍历树(称为类型检查器)来检查操作的操作数的类型和函数的参数。

后一种方法(与单独的类型检查器)通常最终被简单得多,更清晰,更灵活,并给出了更好的错误信息(而不是仅仅“语法错误”)。

+0

谢谢。接受一切,然后抛出错误似乎是一个更好的方法。但是,我不能得到它的树:http://imgur.com/a/68RWI – NEO

+0

在这个例子中,你有一个语法错误的'lals',因为没有办法做出来的表情它,不论什么类型 –