11use nom:: {
22 branch:: alt,
33 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 } ,
66 multi:: separated_list0,
7+ precedence:: { binary_op, precedence, unary_op, Assoc , Operation } ,
78 sequence:: delimited,
8- IResult ,
9- precedence:: { precedence, Assoc , binary_op, unary_op, Operation } ,
9+ IResult , Parser ,
1010} ;
1111
1212// Elements of the abstract syntax tree (ast) that represents an expression.
@@ -29,25 +29,25 @@ pub enum Expr {
2929
3030// Prefix operators.
3131enum PrefixOp {
32- Identity , // +
33- Negate , // -
32+ Identity , // +
33+ Negate , // -
3434}
3535
3636// Postfix operators.
3737enum PostfixOp {
3838 // The function call operator. In addition to its own representation "()" it carries additional information that we need to keep here.
3939 // Specifically the vector of expressions that make up the parameters.
40- Call ( Vec < Expr > ) , // ()
40+ Call ( Vec < Expr > ) , // ()
4141}
4242
4343// Binary operators.
4444enum BinaryOp {
45- Addition , // +
46- Subtraction , // -
47- Multiplication , // *
48- Division , // /
45+ Addition , // +
46+ Subtraction , // -
47+ Multiplication , // *
48+ Division , // /
4949 // The ternary operator can contain a single expression.
50- Ternary ( Expr ) , // ?:
50+ Ternary ( Expr ) , // ?:
5151}
5252
5353// Parser for function calls.
@@ -57,31 +57,28 @@ fn function_call(i: &str) -> IResult<&str, PostfixOp> {
5757 tag ( "(" ) ,
5858 // Subexpressions are evaluated by recursing back into the expression parser.
5959 separated_list0 ( tag ( "," ) , expression) ,
60- tag ( ")" )
60+ tag ( ")" ) ,
6161 ) ,
62- |v : Vec < Expr > | PostfixOp :: Call ( v)
63- ) ( i)
62+ |v : Vec < Expr > | PostfixOp :: Call ( v) ,
63+ )
64+ . parse ( i)
6465}
6566
6667// The ternary operator is actually just a binary operator that contains another expression. So it can be
6768// handled similarly to the function call operator except its in a binary position and can only contain
6869// a single expression.
69- //
70+ //
7071// For example the expression "a<b ? a : b" is handled similarly to the function call operator, the
7172// "?" is treated like an opening bracket and the ":" is treated like a closing bracket.
7273//
7374// For the outer expression the result looks like "a<b ?: b". Where "?:" is a single operator. The
7475// subexpression is contained within the operator in the same way that the function call operator
7576// contains subexpressions.
7677fn 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)
8582}
8683
8784// The actual expression parser .
@@ -94,65 +91,79 @@ fn expression(i: &str) -> IResult<&str, Expr> {
9491 // Function calls are implemented as postfix unary operators.
9592 unary_op ( 1 , function_call) ,
9693 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+ ) ,
105110 // Ternary operators are just binary operators with a subexpression.
106111 binary_op ( 5 , Assoc :: Right , ternary_operator) ,
107112 ) ) ,
108113 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+ } ) ,
115118 map ( alphanumeric, |s : & str | Expr :: Iden ( s. to_string ( ) ) ) ,
116119 delimited ( tag ( "(" ) , expression, tag ( ")" ) ) ,
117120 ) ) ,
118121 |op : Operation < PrefixOp , PostfixOp , BinaryOp , Expr > | -> Result < Expr , ( ) > {
119122 use nom:: precedence:: Operation :: * ;
120- use PrefixOp :: * ;
121- use PostfixOp :: * ;
122123 use BinaryOp :: * ;
124+ use PostfixOp :: * ;
125+ use PrefixOp :: * ;
123126 match op {
124127 // The identity operator (prefix +) is ignored.
125128 Prefix ( Identity , e) => Ok ( e) ,
126-
129+
127130 // Unary minus gets evaluated to the same representation as a multiplication with -1.
128131 Prefix ( Negate , e) => Ok ( Expr :: Mul ( Expr :: Num ( -1 ) . into ( ) , e. into ( ) ) ) ,
129-
132+
130133 // The list of parameters are taken from the operator and placed into the ast.
131134 Postfix ( e, Call ( p) ) => Ok ( Expr :: Call ( e. into ( ) , p) ) ,
132-
135+
133136 // Meaning is assigned to the expressions of the ternary operator during evaluation.
134137 // The lhs becomes the condition, the contained expression is the true case, rhs the false case.
135138 Binary ( lhs, Ternary ( e) , rhs) => Ok ( Expr :: Tern ( lhs. into ( ) , e. into ( ) , rhs. into ( ) ) ) ,
136-
139+
137140 // Raw operators get turned into their respective ast nodes.
138141 Binary ( lhs, Multiplication , rhs) => Ok ( Expr :: Mul ( lhs. into ( ) , rhs. into ( ) ) ) ,
139142 Binary ( lhs, Division , rhs) => Ok ( Expr :: Div ( lhs. into ( ) , rhs. into ( ) ) ) ,
140143 Binary ( lhs, Addition , rhs) => Ok ( Expr :: Add ( lhs. into ( ) , rhs. into ( ) ) ) ,
141144 Binary ( lhs, Subtraction , rhs) => Ok ( Expr :: Sub ( lhs. into ( ) , rhs. into ( ) ) ) ,
142145 }
143- }
146+ } ,
144147 ) ( i)
145148}
146149
147150#[ test]
148151fn expression_test ( ) {
149152 assert_eq ! (
150153 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+ ) )
152168 ) ;
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- ) ;
158169}
0 commit comments