上周末尝试使用Antlr生成C#语言的表达式引擎,目前已经可以支持基本运算.主要思路是把表达式解析成操作数和函数(操作符也作为函数看待)两种类型节点,主要部分类图如下:
GrandExpr.g文件内容如下:
grammar GrandExpr;
options {
output=AST;
ASTLabelType=CommonTree;
// language=CSharp;
}
tokens
{
INDEX;
MEMBERACCESS;
CALL;
}
expr
: logicalOrExpr
;
logicalOrExpr
: logicalAndExpr (OR logicalAndExpr)*
;
logicalAndExpr
: equalityExpr (AND equalityExpr)*
;
equalityExpr
: relationalExpr ((EQUALS|NOTEQUALS)^ relationalExpr)*
;
relationalExpr
: additiveExpr ((LT|LTEQ|GT|GTEQ)^ additiveExpr)?
;
additiveExpr
: multiplyExpr ((PLUS|MINUS)^ multiplyExpr)*
;
multiplyExpr
: powExpr ((a=MUL| a=DIV | a=MOD) powExpr)*
;
powExpr
: unaryExpr (POWER unaryExpr)?
;
unaryExpr
: (PLUS | MINUS | NOT) unaryExpr
| memberExpr
;
memberExpr
: basicExpr (memberAccessExpr)* (indexerExpr)?
;
basicExpr
: parenExpr | literal | memberFunctionExpr;
parenExpr
: LPAREN! expr RPAREN!
;
literal
: numbericLiteral
| stringLiteral
;
numbericLiteral
: INTEGER_LITERAL
| DECIMAL_LITERAL
| DATETIME_LITERAL
;
stringLiteral
: STRING_LITERAL
;
memberAccessExpr
: '.' memberFunctionExpr -> ^(MEMBERACCESS memberFunctionExpr)
;
memberFunctionExpr
: fieldPropertyExpr | methodExpr
;
fieldPropertyExpr
: IDENTIFIER
;
methodExpr
: IDENTIFIER LPAREN (argument (COMMA argument)*)? RPAREN -> ^(CALL IDENTIFIER argument*)
;
indexerExpr
: LBRACKET argument (COMMA argument)* RBRACKET -> ^(INDEX argument+)
;
argument
: expr
;
AND
: 'and'
;
OR
: 'or'
;
NOT
: 'not'
;
COMMA
: ','
;
PLUS
: '+'
;
MINUS
: '-'
;
MUL
: '*'
;
DIV
: '/'
;
MOD
: '%'
;
POWER
: '^'
;
EQUALS : '=';
NOTEQUALS
: '!=' | '<>';
LT : '<';
LTEQ : '<=';
GT : '>';
GTEQ : '>=';
LPAREN
: '('
;
RPAREN : ')'
;
LBRACKET
: '['
;
RBRACKET
: ']'
;
DATETIME_LITERAL
: '\'' STRING_LITERAL '\''
;
STRING_LITERAL
: '"' (~'"')* '"'
;
IDENTIFIER
: LETTER (LETTER|Digit)*
;
fragment
LETTER
: 'A'..'Z'|'a'..'z'|'_'
;
DECIMAL_LITERAL
: (INTEGER_LITERAL)? '.' Digit* Exponent?
;
fragment
Exponent
: ('e'|'E') INTEGER_LITERAL
;
INTEGER_LITERAL
: Digit+
;
fragment
Digit
: '0'..'9'
;
/* Ignore white spaces */
WS
: (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
;
欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]