我正在使用ANTLR来创建和/或解析器+评估器。表达式的格式如下:
x eq 1 && y eq 10
(x lt 10 && x gt 1) OR x eq -1
我正在阅读ANTLR Looking for advice on project. Parsing logical expression中关于逻辑表达式的这篇文章,我发现那里的语法有一个良好的开端:
grammar Logic;
parse
: expression EOF
;
expression
: implication
;
implication
: or ('->' or)*
;
or
: and ('&&' and)*
;
and
: not ('||' not)*
;
not
: '~' atom
| atom
;
atom
: ID
| '(' expression ')'
;
ID : ('a'..'z' | 'A'..'Z')+;
Space : (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
但是,从解析器获取树时,对于变量只是一个字符的表达式(即"(A || B) AND C"
),我很难适应我的情况(在示例{{1}中)我希望有一个"x eq 1 && y eq 10"
个父母和两个孩子"AND"
和"x eq 1"
,请参阅下面的测试用例。)
"y eq 10"
我认为这与@Test
public void simpleAndEvaluation() throws RecognitionException{
String src = "1 eq 1 && B";
LogicLexer lexer = new LogicLexer(new ANTLRStringStream(src));
LogicParser parser = new LogicParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
assertEquals("&&",tree.getText());
assertEquals("1 eq 1",tree.getChild(0).getText());
assertEquals("a neq a",tree.getChild(1).getText());
}
有关。正确的语法是什么?
答案 0 :(得分:2)
对于那些感兴趣的人,我在语法文件中做了一些改进(见下文)
目前的限制:
仅适用于&& / ||,而非AND / OR(不是很有问题)
括号和&& / ||之间不能有空格(我通过在提供词法分析器之前在源字符串中将“(”with“)”和“)”替换为“)”来解决这个问题。
语法逻辑;
options {
output = AST;
}
tokens {
AND = '&&';
OR = '||';
NOT = '~';
}
// parser/production rules start with a lower case letter
parse
: expression EOF! // omit the EOF token
;
expression
: or
;
or
: and (OR^ and)* // make `||` the root
;
and
: not (AND^ not)* // make `&&` the root
;
not
: NOT^ atom // make `~` the root
| atom
;
atom
: ID
| '('! expression ')'! // omit both `(` and `)`
;
// lexer/terminal rules start with an upper case letter
ID
:
(
'a'..'z'
| 'A'..'Z'
| '0'..'9' | ' '
| SYMBOL
)+
;
SYMBOL
:
('+'|'-'|'*'|'/'|'_')
;
答案 1 :(得分:0)
ID : ('a'..'z' | 'A'..'Z')+;
声明标识符是一个或多个字母的序列,但不允许任何数字。尝试
ID : ('a'..'z' | 'A'..'Z' | '0'..'9')+;
允许例如abc
,123
,12ab
和ab12
。如果你不想要后者的类型,你将不得不重新调整规则(留下挑战......)
为了接受任意多个标识符,您可以将atom
定义为ID+
而不是ID
。
此外,您可能需要指定AND
,OR
,->
和~
作为代币,以便像@Bart Kiers所说的那样,前两个赢了' t被归类为ID
,因此后两者将被识别。