1

我正在尝试为我们的自定义规则引擎编写语法,该引擎使用 ANTLR(用于解析)和 Pentaho Kettle(用于执行规则)

解析器的有效输入将是以下类型:
(<Attribute_name> <Relational_Operator> <Value>) AND/OR (<Attribute_name> <Relational_Operator> <Value>)
即 PERSON_PHONE = 123456789

这是我的语法:

grammar RuleGrammar;
options{
language=Java;
}

prog                : condition;

condition
                                :  LHSOPERAND RELATIONOPERATOR RHSOPERAND
                                ;

LHSOPERAND
                                :  STRINGVALUE
                                ;

RHSOPERAND
                                :  NUMBERVALUE    |
                                   STRINGVALUE
                                ;


RELATIONOPERATOR
                                :   '>'    |
                                     '=>'  |
                                     '<'   |
                                     '<='  |
                                     '='   |
                                     '<>'
                                ;

fragment NUMBERVALUE
                              : '0'..'9'+
                              ;

fragment STRINGVALUE
                              :  ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_')*
                              ;


fragment LOGICALOPERATOR
                              :  'AND' |
                                 'OR'  |
                                 'NOT'
                              ;

我面临的问题是与字符串值进行比较,即 PERSON_NAME=1 将通过语法,但该值PERSON_NAME=BATMAN不起作用。我正在使用 ANTLRWorks 并且在调试时PERSON_NAME=BATMAN,我得到了MismatchTokenExceptionRHS 值。

谁能指导我哪里出错了?

4

1 回答 1

3

BATMAN正在被标记为LHSOPERAND令牌。您必须意识到词法分析器没有考虑解析器在特定时间“需要”什么。词法分析器只是尝试尽可能多地匹配,并且如果 2(或更多)规则匹配相同数量的字符(LHSOPERAND并且RHSOPERAND在您的情况下),首先定义的规则将“获胜”,这就是LHSOPERAND规则。

编辑

像这样看它:首先,词法分析器接收它转换为标记流的字符流。在创建了所有标记之后,解析器会接收这些标记,然后尝试理解这些标记。令牌不是在解析期间(在解析器规则中)创建的,而是在解析之前创建的。

快速演示如何做到这一点:

grammar RuleGrammar;

prog
 : condition EOF
 ;

condition
 : logical
 ;

logical
 : relational ((AND | OR) relational)*
 ;

relational
 : STRINGVALUE ((GT | GTEQ | LT | LTEQ | EQ | NEQ) term)?
 ;

term
 : STRINGVALUE
 | NUMBERVALUE
 | '(' condition ')'
 ;

GT          : '>';
GTEQ        : '>=';
LT          : '<';
LTEQ        : '<=';
EQ          : '=';
NEQ         : '<>';
NUMBERVALUE : '0'..'9'+;
AND         : 'AND';
OR          : 'OR';
STRINGVALUE : ('a'..'z' | 'A'..'Z' | '_')+;
SPACE       : ' ' {skip();};

(请注意,EQ并且NEQ不是真正的关系运算符......)

解析输入,如:

PERSON_NAME = BATMAN OR age <> 42

现在将导致以下解析:

在此处输入图像描述

于 2012-02-21T18:42:06.807 回答