使用ANTLR4解析具有多个AND和OR的规则?

时间:2019-02-14 00:09:04

标签: antlr4

我是ANTLR4的新手,我试图使用它来解析从外部规则生成器获得的规则字符串。 规则的格式为[属性运算符值]多次AND和OR。

我能够解析更简单的代码,例如:-

[divison3__c == ('AH Marketing', 'Asset Protection Solutions')]  OR  [hrstatus__c == ('Active')]

但是,一旦我遇到了那些AND和OR混合的问题,例如:-

[[divison3__c == ('AH Marketing', 'Asset Protection Solutions')] OR  [hrstatus__c == ('Active')]] AND [[hiredate__c > ('2000-01-01')] OR [custom10__c == ('ABCD')]]

下面将介绍我的适用于简单规则的语法。我真的很感谢在解析由复合AND和OR组成的规则方面需要做什么的所有提示。

// Our grammar is called Rules.
grammar Rules;

// Rules
start: grouprules;

grouprules: grouprule (andor grouprule)* EOF;

grouprule: L_SB expression R_SB;

expression: USERATTRIBUTE operator values;

operator: EQ | NE | GE | GT | LE | LT;

values: '(' value  (','  value )* ')';

value: STRING | date;

date: '\'' DATE '\'';

andor: AND | OR;

// Tokens
EQ: '==';
NE: '!=';
GT:  '>';
GE: '>=';
LT:  '<';
LE: '<=';
L_SB: '[';
R_SB: ']';
AND: [aA][nN][dD];
OR: [oO][rR];
NUMBER: [0-9]+;

USERATTRIBUTE: [a-zA-Z][a-zA-Z0-9_]*;

STRING:  '\'' ~('"')* '\'' ;

// Not perfect
DATE: [0-9][0-9][0-9][0-9][-][0-1][0-9][-][0-3][0-9] ;

// WS represents a whitespace, which is ignored entirely by skip.
WS: [ \t\u000C\r\n]+ -> skip;

规则:

[divison3__c == ('AH Marketing', 'Asset Protection Solutions')]  OR  [hrstatus__c == ('Active')]

成功的结果:

(grouprules (grouprule [ [ hiredate__c (operator >) (values ( (value '2000-01-01')] AND [divison3__c == ('AH Marketing', 'Asset Protection Solutions') )) ]) ] <EOF>)

复合规则:

[[divison3__c == ('AH Marketing', 'Asset Protection Solutions')] OR  [hrstatus__c == ('Active')]] AND [[hiredate__c > ('2000-01-01')] OR [custom10__c == ('ABCD')]]

失败的结果:

line 1:1 extraneous input '[' expecting USERATTRIBUTE
line 1:162 extraneous input ']' expecting {<EOF>, AND, OR}
(grouprules (grouprule [ (expression [ divison3__c (operator ==) (values ( (value 'AH Marketing', 'Asset Protection Solutions')] OR  [hrstatus__c == ('Active')]] AND [[hiredate__c > ('2000-01-01')] OR [custom10__c == ('ABCD') ))) ]) ] <EOF>)

2 个答案:

答案 0 :(得分:0)

您的问题不是您有多个运算符和/或运算符(像[...] AND [...] OR [...]这样的语法可以很好地解析),而是有嵌套的括号([[)。目前,您的语法仅允许USERATTRIBUTE operator values放在方括号内,而不允许其他括号或AND / OR

为此,您应该添加grouprules作为expression的替代,因此表达式不仅可以具有USERATTRIBUTE operator values的形式,而且可以是{{1 }}和/或AND运算符。

要执行此操作,您首先需要将OREOF移到grouprules,尽管您不想将其应用于嵌套在括号内的start(因为这些将在后面加上一个右括号,而不是文件的末尾(显然只出现一次)。

答案 1 :(得分:0)

关于您的语法的几点评论:

  • 您的STRING应该包含~('\'')*而不是~('"')*
  • '2018-12-31'这样的
  • 输入将不会(部分)与您的DATE规则匹配:由于它周围带有引号,因此您的STRING规则将与之匹配。 DATE应该被删除
  • 由于上一句话,您的date应该被删除

这应该可以解决问题:

grammar Grammar;

start
 : expr EOF
 ;

expr
 : USERATTRIBUTE ( EQ | NE | GE | GT | LE | LT ) expr
 | expr ( AND | OR ) expr
 | '[' expr ']'
 | list
 ;

list
 : '(' STRING  (','  STRING )* ')'
 ;

EQ : '==';
NE : '!=';
GT :  '>';
GE : '>=';
LT :  '<';
LE : '<=';
L_SB : '[';
R_SB : ']';
AND : [aA][nN][dD];
OR : [oO][rR];
NUMBER : [0-9]+;
USERATTRIBUTE : [a-zA-Z][a-zA-Z0-9_]*;
STRING : '\'' ~('\'')* '\'' ;
WS : [ \t\u000C\r\n]+ -> skip;

您的输入[divison3__c == ('AH Marketing', 'Asset Protection Solutions')] OR [hrstatus__c == ('Active')]的解析如下:

enter image description here

[[divison3__c == ('AH Marketing', 'Asset Protection Solutions')] OR [hrstatus__c == ('Active')]] AND [[hiredate__c > ('2000-01-01')] OR [custom10__c == ('ABCD')]]这样:

enter image description here