@@ -19,7 +19,7 @@ use nom::{
1919/// In this case, we want something tree-like
2020
2121/// Starting from the most basic, we define some built-in functions that our lisp has
22- #[ derive( Debug , PartialEq , Clone , Copy ) ]
22+ #[ derive( Debug , Eq , PartialEq , Clone , Copy ) ]
2323pub enum BuiltIn {
2424 Plus ,
2525 Minus ,
@@ -32,7 +32,7 @@ pub enum BuiltIn {
3232/// We now wrap this type and a few other primitives into our Atom type.
3333/// Remember from before that Atoms form one half of our language.
3434
35- #[ derive( Debug , PartialEq , Clone ) ]
35+ #[ derive( Debug , Eq , PartialEq , Clone ) ]
3636pub enum Atom {
3737 Num ( i32 ) ,
3838 Keyword ( String ) ,
@@ -50,7 +50,7 @@ pub enum Atom {
5050/// structure that we can deal with programmatically. Thus any valid expression
5151/// is also a valid data structure in Lisp itself.
5252
53- #[ derive( Debug , PartialEq , Clone ) ]
53+ #[ derive( Debug , Eq , PartialEq , Clone ) ]
5454pub enum Expr {
5555 Constant ( Atom ) ,
5656 /// (func-name arg1 arg2)
@@ -65,7 +65,7 @@ pub enum Expr {
6565
6666/// Continuing the trend of starting from the simplest piece and building up,
6767/// we start by creating a parser for the built-in operator functions.
68- fn parse_builtin_op < ' a > ( i : & ' a str ) -> IResult < & ' a str , BuiltIn , VerboseError < & ' a str > > {
68+ fn parse_builtin_op ( i : & str ) -> IResult < & str , BuiltIn , VerboseError < & str > > {
6969 // one_of matches one of the characters we give it
7070 let ( i, t) = one_of ( "+-*/=" ) ( i) ?;
7171
@@ -84,7 +84,7 @@ fn parse_builtin_op<'a>(i: &'a str) -> IResult<&'a str, BuiltIn, VerboseError<&'
8484 ) )
8585}
8686
87- fn parse_builtin < ' a > ( i : & ' a str ) -> IResult < & ' a str , BuiltIn , VerboseError < & ' a str > > {
87+ fn parse_builtin ( i : & str ) -> IResult < & str , BuiltIn , VerboseError < & str > > {
8888 // alt gives us the result of first parser that succeeds, of the series of
8989 // parsers we give it
9090 alt ( (
@@ -96,7 +96,7 @@ fn parse_builtin<'a>(i: &'a str) -> IResult<&'a str, BuiltIn, VerboseError<&'a s
9696}
9797
9898/// Our boolean values are also constant, so we can do it the same way
99- fn parse_bool < ' a > ( i : & ' a str ) -> IResult < & ' a str , Atom , VerboseError < & ' a str > > {
99+ fn parse_bool ( i : & str ) -> IResult < & str , Atom , VerboseError < & str > > {
100100 alt ( (
101101 map ( tag ( "#t" ) , |_| Atom :: Boolean ( true ) ) ,
102102 map ( tag ( "#f" ) , |_| Atom :: Boolean ( false ) ) ,
@@ -109,7 +109,7 @@ fn parse_bool<'a>(i: &'a str) -> IResult<&'a str, Atom, VerboseError<&'a str>> {
109109///
110110/// Put plainly: `preceded(tag(":"), cut(alpha1))` means that once we see the `:`
111111/// character, we have to see one or more alphabetic chararcters or the input is invalid.
112- fn parse_keyword < ' a > ( i : & ' a str ) -> IResult < & ' a str , Atom , VerboseError < & ' a str > > {
112+ fn parse_keyword ( i : & str ) -> IResult < & str , Atom , VerboseError < & str > > {
113113 map (
114114 context ( "keyword" , preceded ( tag ( ":" ) , cut ( alpha1) ) ) ,
115115 |sym_str : & str | Atom :: Keyword ( sym_str. to_string ( ) ) ,
@@ -118,20 +118,20 @@ fn parse_keyword<'a>(i: &'a str) -> IResult<&'a str, Atom, VerboseError<&'a str>
118118
119119/// Next up is number parsing. We're keeping it simple here by accepting any number (> 1)
120120/// of digits but ending the program if it doesn't fit into an i32.
121- fn parse_num < ' a > ( i : & ' a str ) -> IResult < & ' a str , Atom , VerboseError < & ' a str > > {
121+ fn parse_num ( i : & str ) -> IResult < & str , Atom , VerboseError < & str > > {
122122 alt ( (
123123 map_res ( digit1, |digit_str : & str | {
124124 digit_str. parse :: < i32 > ( ) . map ( Atom :: Num )
125125 } ) ,
126126 map ( preceded ( tag ( "-" ) , digit1) , |digit_str : & str | {
127- Atom :: Num ( -1 * digit_str. parse :: < i32 > ( ) . unwrap ( ) )
127+ Atom :: Num ( -digit_str. parse :: < i32 > ( ) . unwrap ( ) )
128128 } ) ,
129129 ) ) ( i)
130130}
131131
132132/// Now we take all these simple parsers and connect them.
133133/// We can now parse half of our language!
134- fn parse_atom < ' a > ( i : & ' a str ) -> IResult < & ' a str , Atom , VerboseError < & ' a str > > {
134+ fn parse_atom ( i : & str ) -> IResult < & str , Atom , VerboseError < & str > > {
135135 alt ( (
136136 parse_num,
137137 parse_bool,
@@ -141,8 +141,8 @@ fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Atom, VerboseError<&'a str>> {
141141}
142142
143143/// We then add the Expr layer on top
144- fn parse_constant < ' a > ( i : & ' a str ) -> IResult < & ' a str , Expr , VerboseError < & ' a str > > {
145- map ( parse_atom, |atom| Expr :: Constant ( atom ) ) ( i)
144+ fn parse_constant ( i : & str ) -> IResult < & str , Expr , VerboseError < & str > > {
145+ map ( parse_atom, Expr :: Constant ) ( i)
146146}
147147
148148/// Before continuing, we need a helper function to parse lists.
@@ -172,7 +172,7 @@ where
172172///
173173/// `tuple` is used to sequence parsers together, so we can translate this directly
174174/// and then map over it to transform the output into an `Expr::Application`
175- fn parse_application < ' a > ( i : & ' a str ) -> IResult < & ' a str , Expr , VerboseError < & ' a str > > {
175+ fn parse_application ( i : & str ) -> IResult < & str , Expr , VerboseError < & str > > {
176176 let application_inner = map ( tuple ( ( parse_expr, many0 ( parse_expr) ) ) , |( head, tail) | {
177177 Expr :: Application ( Box :: new ( head) , tail)
178178 } ) ;
@@ -186,7 +186,7 @@ fn parse_application<'a>(i: &'a str) -> IResult<&'a str, Expr, VerboseError<&'a
186186///
187187/// In fact, we define our parser as if `Expr::If` was defined with an Option in it,
188188/// we have the `opt` combinator which fits very nicely here.
189- fn parse_if < ' a > ( i : & ' a str ) -> IResult < & ' a str , Expr , VerboseError < & ' a str > > {
189+ fn parse_if ( i : & str ) -> IResult < & str , Expr , VerboseError < & str > > {
190190 let if_inner = context (
191191 "if expression" ,
192192 map (
@@ -218,19 +218,19 @@ fn parse_if<'a>(i: &'a str) -> IResult<&'a str, Expr, VerboseError<&'a str>> {
218218/// This example doesn't have the symbol atom, but by adding variables and changing
219219/// the definition of quote to not always be around an S-expression, we'd get them
220220/// naturally.
221- fn parse_quote < ' a > ( i : & ' a str ) -> IResult < & ' a str , Expr , VerboseError < & ' a str > > {
221+ fn parse_quote ( i : & str ) -> IResult < & str , Expr , VerboseError < & str > > {
222222 // this should look very straight-forward after all we've done:
223223 // we find the `'` (quote) character, use cut to say that we're unambiguously
224224 // looking for an s-expression of 0 or more expressions, and then parse them
225225 map (
226226 context ( "quote" , preceded ( tag ( "'" ) , cut ( s_exp ( many0 ( parse_expr) ) ) ) ) ,
227- |exprs| Expr :: Quote ( exprs ) ,
227+ Expr :: Quote ,
228228 ) ( i)
229229}
230230
231231/// We tie them all together again, making a top-level expression parser!
232232
233- fn parse_expr < ' a > ( i : & ' a str ) -> IResult < & ' a str , Expr , VerboseError < & ' a str > > {
233+ fn parse_expr ( i : & str ) -> IResult < & str , Expr , VerboseError < & str > > {
234234 preceded (
235235 multispace0,
236236 alt ( ( parse_constant, parse_application, parse_if, parse_quote) ) ,
@@ -291,7 +291,7 @@ fn eval_expression(e: Expr) -> Option<Expr> {
291291 let reduced_head = eval_expression ( * head) ?;
292292 let reduced_tail = tail
293293 . into_iter ( )
294- . map ( |expr| eval_expression ( expr ) )
294+ . map ( eval_expression)
295295 . collect :: < Option < Vec < Expr > > > ( ) ?;
296296 if let Expr :: Constant ( Atom :: BuiltIn ( bi) ) = reduced_head {
297297 Some ( Expr :: Constant ( match bi {
@@ -361,7 +361,7 @@ fn eval_expression(e: Expr) -> Option<Expr> {
361361fn eval_from_str ( src : & str ) -> Result < Expr , String > {
362362 parse_expr ( src)
363363 . map_err ( |e : nom:: Err < VerboseError < & str > > | format ! ( "{:#?}" , e) )
364- . and_then ( |( _, exp) | eval_expression ( exp) . ok_or ( "Eval failed" . to_string ( ) ) )
364+ . and_then ( |( _, exp) | eval_expression ( exp) . ok_or_else ( || "Eval failed" . to_string ( ) ) )
365365}
366366
367367fn main ( ) {
0 commit comments