Parsing and/or逻辑的Antlr解析器-如何在逻辑运算符之间获得表达式?
我正在使用ANTLR创建和/或解析器+计算器。表达式的格式如下:Parsing and/or逻辑的Antlr解析器-如何在逻辑运算符之间获得表达式?,parsing,antlr,antlr3,Parsing,Antlr,Antlr3,我正在使用ANTLR创建和/或解析器+计算器。表达式的格式如下: x等式1和&y等式10 (x lt 10&x gt 1)或x eq-1 我正在阅读这篇关于ANTLR中逻辑表达式的文章,我发现这里发布的语法是一个很好的开端: grammar Logic; parse : expression EOF ; expression : implication ; implication : or ('->' or)* ; or : and ('&a
x等式1和&y等式10
(x lt 10&x gt 1)或x eq-1
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)和C)的表达式,我很难适应我的情况(在示例“x eq 1和&y eq 10”
中,我希望有一个“和”
父项和两个子项,“x eq 1”
和“y eq 10”
,请参见下面的测试用例)
我相信这与“ID”
有关。正确的语法是什么
ID : ('a'..'z' | 'A'..'Z')+;
表示标识符是一个或多个字母的序列,但不允许有任何数字。请重试
ID : ('a'..'z' | 'A'..'Z' | '0'..'9')+;
这将允许例如abc
、123
、12ab
和ab12
。如果您不想要后一种类型,则必须稍微重新构造规则(留作挑战…)
为了接受任意多个标识符,您可以将atom
定义为ID+
而不是ID
此外,您可能需要指定
和
,或
,->
和~
作为标记,这样,正如@Bart Kiers所说,前两个将不会被归类为ID
,后两个将被完全识别。对于那些感兴趣的人,我在我的语法文件中做了一些改进(见下文)
目前的限制:
- 仅适用于&&/| |,不适用于和/或(问题不大)
- 括号和&&/| |之间不能有空格(在输入lexer之前,我通过替换源字符串中的“(“with”)”和“)“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 : ('+'|'-'|'*'|'/'|'_') ;
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
:
('+'|'-'|'*'|'/'|'_')
;