I've defined a grammar, which I have to parse in C# and evaluate the resulted "constraints" on a list of dictionaries. The grammar is mainly boolean algebra.
Here you can check it:
grammar Constraint;
expr
: implyExpr
;
implyExpr
: orExpr
| leftOp=orExpr IMPLY rightOp=orExpr
;
orExpr
: andExpr
| leftOp=andExpr OR rightOp=andExpr
;
andExpr
: primaryExpr
| leftOp=primaryExpr AND rightOp=primaryExpr
;
primaryExpr
: trueExpr
| falseExpr
| parenExpr
| notParenExpr
| statement
;
trueExpr
: TRUE
;
falseExpr
: FALSE
;
parenExpr
: LPAREN expr RPAREN
;
notParenExpr
: NOT LPAREN expr RPAREN
;
statement
: eqValStatement
| notEqValStatement
| inListStatement
| notInListStatement
;
eqValStatement
: key=STR EQ value=val
;
notEqValStatement
: key=STR NEQ value=val
;
inListStatement
: key=STR EQ list=lst
;
notInListStatement
: key=STR NEQ list=lst
;
lst
: LBRACK values+=val (COMMA values+=val)* RBRACK
;
val
: strVal
| nullVal
;
strVal
: value=STR
;
nullVal
: NULL
;
// Lexer
IMPLY: '->';
OR: '|';
AND: '&';
TRUE: 'true';
FALSE: 'false';
LPAREN: '(';
RPAREN: ')';
NOT: '!';
EQ: '=';
NEQ: '!=';
LBRACK: '[';
RBRACK: ']';
COMMA: ',';
NULL: 'null';
STR: [a-zA-Z0-9-_]+;
WS: [ \t\n\r]+ -> skip;
My question is that could I use this namespace for my goal or shall I use different delegates, which would take 2 delegates as parameters and would return with a bool value according to the implemented behaviour?
I'm still at the design phase, what I've done already is the grammar definition and generating the listenerbase class for it.
I solved the problem by using delegates in the end. I generated a Predicate for each expression and combined them together. I've also integrated the recognition of the grammar into the listener class, in this way providing a simple interface for getting a predicate from an expression.
Here's the most of it:
In the end I used List of ConfigurationItems, which have Key and Value properties, bc. of the domain requirements of my application.