上周末尝试使用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)* ; fragmentLETTER : 'A'..'Z'|'a'..'z'|'_' ;DECIMAL_LITERAL : (INTEGER_LITERAL)? '.' Digit* Exponent? ;fragmentExponent : ('e'|'E') INTEGER_LITERAL ;INTEGER_LITERAL : Digit+ ; fragmentDigit : '0'..'9' ;/* Ignore white spaces */ WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} ;
欢迎转载,转载请注明:转载自 [ ]