简体   繁体   中英

ANTLR Grammar for a recursive expression

I have problem where I need to validate a set of inputs against a business rule.

The set of inputs can be represented by a class like

public class RuleInput{
    public String payType;
    public String bank;
    public String brand;

    //....Getters and setters
}

My system client can configure many rules in my system. To configure rule i have defined a DSL like below

RULE1 - payType in ('NB,'CC') and bank in ('HDFC', 'CITI')
RULE2 - payType in ('NB') and (bank in ('HDFC','AXIS') or brand in ('VISA'))

Now Given ruleInput = RuleInput(NB,HDFC, VISA) and function

public boolean validateAgainstRule(String ruleId, RuleInput input);

Calling this like validateAgainstRule("RULE2" , ruleInput) should return true;

I am thinking of using ANTLR for the same(But I am very new to it). I tried to build a grammar like this

expression : 
    primary_expression
    | expression OR expression
    | expression AND expression
    | LPAREN expression RPAREN
    ;

primary_expression : //A simple expression
    simple
    ;

simple : TAG_EXPR | BIN_EXPR ;

TAG : 'payment_type' | 'issuer' | 'brand' ;
BIN_TAG : 'bins' ;

BIN_EXPR : BIN_TAG IN BIN_LIST ;
TAG_EXPR : TAG IN LIST ;

LIST : LPAREN TEXT (COMMA TEXT)* RPAREN ;
BIN_LIST :  LPAREN BIN (COMMA BIN)* RPAREN ;

IN : 'in' ;
OR : 'or' ;
AND : 'and' ;

LPAREN : '(' ;
RPAREN : ')' ;

COMMA : ',' ;
TEXT : [A-Z]+ ;
BIN : [0-9][0-9][0-9][0-9][0-9][0-9] ;

WS  : [ \t\r\n]+ -> skip ;

Can somebody help me to write the grammar for my requirement. I think I need even to use actions in the grammar for accepting inputs.

Note : I even thought of using drools, but I only have a single kind of rules, it will be heavy to use drools for this kind of a small problem. So thought of going with ANTLR only.

There are a couple things I don't understand in your grammar - it doesn't seem to match your DSL...

Here, try this instead:

rule : ID '-' expression ;

expression : '(' expression ')'           # parensExpr
           | expression 'and' expression  # andExpr
           | expression 'or' expression   # orExpr
           | simpleExpr                   # clauseExpr
           ;

simpleExpr : TAG 'in' '(' stringList ')' ;

stringList : STRING (',' STRING)* ;

TAG : 'payType' | 'bank' | 'brand';
STRING : '\'' [A-Za-z0-9]* '\\';
ID: [A-Za-z0-9]+;
WS: [ \t\r\n]+ -> skip ;

ANTLR will generate a base tree visitor class for you, use this to check your expression, or build an AST and check against that (this approach is better but longer to implement).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM