1
1
use nom:: {
2
2
branch:: alt,
3
3
bytes:: complete:: tag,
4
- character:: complete:: { digit1 as digit , alphanumeric1 as alphanumeric } ,
5
- combinator:: { map_res , map } ,
4
+ character:: complete:: { alphanumeric1 as alphanumeric , digit1 as digit } ,
5
+ combinator:: { map , map_res } ,
6
6
multi:: separated_list0,
7
+ precedence:: { binary_op, precedence, unary_op, Assoc , Operation } ,
7
8
sequence:: delimited,
8
- IResult ,
9
- precedence:: { precedence, Assoc , binary_op, unary_op, Operation } ,
9
+ IResult , Parser ,
10
10
} ;
11
11
12
12
// Elements of the abstract syntax tree (ast) that represents an expression.
@@ -29,25 +29,25 @@ pub enum Expr {
29
29
30
30
// Prefix operators.
31
31
enum PrefixOp {
32
- Identity , // +
33
- Negate , // -
32
+ Identity , // +
33
+ Negate , // -
34
34
}
35
35
36
36
// Postfix operators.
37
37
enum PostfixOp {
38
38
// The function call operator. In addition to its own representation "()" it carries additional information that we need to keep here.
39
39
// Specifically the vector of expressions that make up the parameters.
40
- Call ( Vec < Expr > ) , // ()
40
+ Call ( Vec < Expr > ) , // ()
41
41
}
42
42
43
43
// Binary operators.
44
44
enum BinaryOp {
45
- Addition , // +
46
- Subtraction , // -
47
- Multiplication , // *
48
- Division , // /
45
+ Addition , // +
46
+ Subtraction , // -
47
+ Multiplication , // *
48
+ Division , // /
49
49
// The ternary operator can contain a single expression.
50
- Ternary ( Expr ) , // ?:
50
+ Ternary ( Expr ) , // ?:
51
51
}
52
52
53
53
// Parser for function calls.
@@ -57,31 +57,28 @@ fn function_call(i: &str) -> IResult<&str, PostfixOp> {
57
57
tag ( "(" ) ,
58
58
// Subexpressions are evaluated by recursing back into the expression parser.
59
59
separated_list0 ( tag ( "," ) , expression) ,
60
- tag ( ")" )
60
+ tag ( ")" ) ,
61
61
) ,
62
- |v : Vec < Expr > | PostfixOp :: Call ( v)
63
- ) ( i)
62
+ |v : Vec < Expr > | PostfixOp :: Call ( v) ,
63
+ )
64
+ . parse ( i)
64
65
}
65
66
66
67
// The ternary operator is actually just a binary operator that contains another expression. So it can be
67
68
// handled similarly to the function call operator except its in a binary position and can only contain
68
69
// a single expression.
69
- //
70
+ //
70
71
// For example the expression "a<b ? a : b" is handled similarly to the function call operator, the
71
72
// "?" is treated like an opening bracket and the ":" is treated like a closing bracket.
72
73
//
73
74
// For the outer expression the result looks like "a<b ?: b". Where "?:" is a single operator. The
74
75
// subexpression is contained within the operator in the same way that the function call operator
75
76
// contains subexpressions.
76
77
fn ternary_operator ( i : & str ) -> IResult < & str , BinaryOp > {
77
- map (
78
- delimited (
79
- tag ( "?" ) ,
80
- expression,
81
- tag ( ":" )
82
- ) ,
83
- |e : Expr | BinaryOp :: Ternary ( e)
84
- ) ( i)
78
+ map ( delimited ( tag ( "?" ) , expression, tag ( ":" ) ) , |e : Expr | {
79
+ BinaryOp :: Ternary ( e)
80
+ } )
81
+ . parse ( i)
85
82
}
86
83
87
84
// The actual expression parser .
@@ -94,65 +91,79 @@ fn expression(i: &str) -> IResult<&str, Expr> {
94
91
// Function calls are implemented as postfix unary operators.
95
92
unary_op ( 1 , function_call) ,
96
93
alt ( (
97
- binary_op ( 3 , Assoc :: Left , alt ( (
98
- map ( tag ( "*" ) , |_| BinaryOp :: Multiplication ) ,
99
- map ( tag ( "/" ) , |_| BinaryOp :: Division ) ,
100
- ) ) ) ,
101
- binary_op ( 4 , Assoc :: Left , alt ( (
102
- map ( tag ( "+" ) , |_| BinaryOp :: Addition ) ,
103
- map ( tag ( "-" ) , |_| BinaryOp :: Subtraction ) ,
104
- ) ) ) ,
94
+ binary_op (
95
+ 3 ,
96
+ Assoc :: Left ,
97
+ alt ( (
98
+ map ( tag ( "*" ) , |_| BinaryOp :: Multiplication ) ,
99
+ map ( tag ( "/" ) , |_| BinaryOp :: Division ) ,
100
+ ) ) ,
101
+ ) ,
102
+ binary_op (
103
+ 4 ,
104
+ Assoc :: Left ,
105
+ alt ( (
106
+ map ( tag ( "+" ) , |_| BinaryOp :: Addition ) ,
107
+ map ( tag ( "-" ) , |_| BinaryOp :: Subtraction ) ,
108
+ ) ) ,
109
+ ) ,
105
110
// Ternary operators are just binary operators with a subexpression.
106
111
binary_op ( 5 , Assoc :: Right , ternary_operator) ,
107
112
) ) ,
108
113
alt ( (
109
- map_res ( digit,
110
- |s : & str | match s. parse :: < i64 > ( ) {
111
- Ok ( s) => Ok ( Expr :: Num ( s) ) ,
112
- Err ( e) => Err ( e) ,
113
- }
114
- ) ,
114
+ map_res ( digit, |s : & str | match s. parse :: < i64 > ( ) {
115
+ Ok ( s) => Ok ( Expr :: Num ( s) ) ,
116
+ Err ( e) => Err ( e) ,
117
+ } ) ,
115
118
map ( alphanumeric, |s : & str | Expr :: Iden ( s. to_string ( ) ) ) ,
116
119
delimited ( tag ( "(" ) , expression, tag ( ")" ) ) ,
117
120
) ) ,
118
121
|op : Operation < PrefixOp , PostfixOp , BinaryOp , Expr > | -> Result < Expr , ( ) > {
119
122
use nom:: precedence:: Operation :: * ;
120
- use PrefixOp :: * ;
121
- use PostfixOp :: * ;
122
123
use BinaryOp :: * ;
124
+ use PostfixOp :: * ;
125
+ use PrefixOp :: * ;
123
126
match op {
124
127
// The identity operator (prefix +) is ignored.
125
128
Prefix ( Identity , e) => Ok ( e) ,
126
-
129
+
127
130
// Unary minus gets evaluated to the same representation as a multiplication with -1.
128
131
Prefix ( Negate , e) => Ok ( Expr :: Mul ( Expr :: Num ( -1 ) . into ( ) , e. into ( ) ) ) ,
129
-
132
+
130
133
// The list of parameters are taken from the operator and placed into the ast.
131
134
Postfix ( e, Call ( p) ) => Ok ( Expr :: Call ( e. into ( ) , p) ) ,
132
-
135
+
133
136
// Meaning is assigned to the expressions of the ternary operator during evaluation.
134
137
// The lhs becomes the condition, the contained expression is the true case, rhs the false case.
135
138
Binary ( lhs, Ternary ( e) , rhs) => Ok ( Expr :: Tern ( lhs. into ( ) , e. into ( ) , rhs. into ( ) ) ) ,
136
-
139
+
137
140
// Raw operators get turned into their respective ast nodes.
138
141
Binary ( lhs, Multiplication , rhs) => Ok ( Expr :: Mul ( lhs. into ( ) , rhs. into ( ) ) ) ,
139
142
Binary ( lhs, Division , rhs) => Ok ( Expr :: Div ( lhs. into ( ) , rhs. into ( ) ) ) ,
140
143
Binary ( lhs, Addition , rhs) => Ok ( Expr :: Add ( lhs. into ( ) , rhs. into ( ) ) ) ,
141
144
Binary ( lhs, Subtraction , rhs) => Ok ( Expr :: Sub ( lhs. into ( ) , rhs. into ( ) ) ) ,
142
145
}
143
- }
146
+ } ,
144
147
) ( i)
145
148
}
146
149
147
150
#[ test]
148
151
fn expression_test ( ) {
149
152
assert_eq ! (
150
153
expression( "-2*max(2,3)-2" ) . map( |( i, x) | ( i, format!( "{:?}" , x) ) ) ,
151
- Ok ( ( "" , String :: from( "Sub(Mul(Mul(Num(-1), Num(2)), Call(Iden(\" max\" ), [Num(2), Num(3)])), Num(2))" ) ) )
154
+ Ok ( (
155
+ "" ,
156
+ String :: from( "Sub(Mul(Mul(Num(-1), Num(2)), Call(Iden(\" max\" ), [Num(2), Num(3)])), Num(2))" )
157
+ ) )
158
+ ) ;
159
+
160
+ assert_eq ! (
161
+ expression( "a?2+c:-2*2" ) . map( |( i, x) | ( i, format!( "{:?}" , x) ) ) ,
162
+ Ok ( (
163
+ "" ,
164
+ String :: from(
165
+ "Tern(Iden(\" a\" ), Add(Num(2), Iden(\" c\" )), Mul(Mul(Num(-1), Num(2)), Num(2)))"
166
+ )
167
+ ) )
152
168
) ;
153
-
154
- assert_eq ! (
155
- expression( "a?2+c:-2*2" ) . map( |( i, x) | ( i, format!( "{:?}" , x) ) ) ,
156
- Ok ( ( "" , String :: from( "Tern(Iden(\" a\" ), Add(Num(2), Iden(\" c\" )), Mul(Mul(Num(-1), Num(2)), Num(2)))" ) ) )
157
- ) ;
158
169
}
0 commit comments