1
1
using System ;
2
+ using System . Linq ;
2
3
using System . Linq . Expressions ;
3
4
using Sprache ;
4
5
5
6
namespace LinqyCalculator
6
7
{
7
8
static class ExpressionParser
8
9
{
9
- public static Expression < Func < decimal > > ParseExpression ( string text )
10
+ public static Expression < Func < double > > ParseExpression ( string text )
10
11
{
11
12
return Lambda . Parse ( text ) ;
12
13
}
@@ -20,23 +21,52 @@ static Parser<ExpressionType> Operator(string op, ExpressionType opType)
20
21
static readonly Parser < ExpressionType > Subtract = Operator ( "-" , ExpressionType . SubtractChecked ) ;
21
22
static readonly Parser < ExpressionType > Multiply = Operator ( "*" , ExpressionType . MultiplyChecked ) ;
22
23
static readonly Parser < ExpressionType > Divide = Operator ( "/" , ExpressionType . Divide ) ;
24
+ static readonly Parser < ExpressionType > Modulo = Operator ( "%" , ExpressionType . Modulo ) ;
25
+ static readonly Parser < ExpressionType > Power = Operator ( "^" , ExpressionType . Power ) ;
26
+
27
+ static readonly Parser < Expression > Function =
28
+ from name in Parse . Letter . AtLeastOnce ( ) . Text ( )
29
+ from lparen in Parse . Char ( '(' )
30
+ from expr in Parse . Ref ( ( ) => Expr ) . DelimitedBy ( Parse . Char ( ',' ) . Token ( ) )
31
+ from rparen in Parse . Char ( ')' )
32
+ select CallFunction ( name , expr . ToArray ( ) ) ;
33
+
34
+ static Expression CallFunction ( string name , Expression [ ] parameters )
35
+ {
36
+ var methodInfo = typeof ( Math ) . GetMethod ( name , parameters . Select ( e => e . Type ) . ToArray ( ) ) ;
37
+ if ( methodInfo == null )
38
+ throw new ParseException ( string . Format ( "Function '{0}({1})' does not exist." , name ,
39
+ string . Join ( "," , parameters . Select ( e => e . Type . Name ) ) ) ) ;
40
+
41
+ return Expression . Call ( methodInfo , parameters ) ;
42
+ }
23
43
24
44
static readonly Parser < Expression > Constant =
25
- ( from d in Parse . Decimal . Token ( )
26
- select ( Expression ) Expression . Constant ( decimal . Parse ( d ) ) ) . Named ( "number" ) ;
45
+ Parse . Decimal
46
+ . Select ( x => Expression . Constant ( double . Parse ( x ) ) )
47
+ . Named ( "number" ) ;
27
48
28
49
static readonly Parser < Expression > Factor =
29
- ( ( from lparen in Parse . Char ( '(' )
50
+ ( from lparen in Parse . Char ( '(' )
30
51
from expr in Parse . Ref ( ( ) => Expr )
31
52
from rparen in Parse . Char ( ')' )
32
53
select expr ) . Named ( "expression" )
33
- . XOr ( Constant ) ) . Token ( ) ;
54
+ . XOr ( Constant )
55
+ . XOr ( Function ) ;
34
56
35
- static readonly Parser < Expression > Term = Parse . ChainOperator ( Multiply . Or ( Divide ) , Factor , Expression . MakeBinary ) ;
57
+ static readonly Parser < Expression > Operand =
58
+ ( ( from sign in Parse . Char ( '-' )
59
+ from factor in Factor
60
+ select Expression . Negate ( factor )
61
+ ) . XOr ( Factor ) ) . Token ( ) ;
62
+
63
+ static readonly Parser < Expression > InnerTerm = Parse . ChainOperator ( Power , Operand , Expression . MakeBinary ) ;
64
+
65
+ static readonly Parser < Expression > Term = Parse . ChainOperator ( Multiply . Or ( Divide ) . Or ( Modulo ) , InnerTerm , Expression . MakeBinary ) ;
36
66
37
67
static readonly Parser < Expression > Expr = Parse . ChainOperator ( Add . Or ( Subtract ) , Term , Expression . MakeBinary ) ;
38
-
39
- static readonly Parser < Expression < Func < decimal > > > Lambda =
40
- Expr . End ( ) . Select ( body => Expression . Lambda < Func < decimal > > ( body ) ) ;
68
+
69
+ static readonly Parser < Expression < Func < double > > > Lambda =
70
+ Expr . End ( ) . Select ( body => Expression . Lambda < Func < double > > ( body ) ) ;
41
71
}
42
72
}
0 commit comments