@@ -10,6 +10,8 @@ use winnow::seq;
10
10
use winnow:: stream:: AsChar ;
11
11
use winnow:: token:: { one_of, take_while} ;
12
12
13
+ const KEYWORDS : [ & str ; 7 ] = [ "fun" , "if" , "else" , "true" , "false" , "int" , "bool" ] ;
14
+
13
15
fn ws < ' a , F , O , E : ParserError < & ' a str > > ( inner : F ) -> impl Parser < & ' a str , O , E >
14
16
where
15
17
F : Parser < & ' a str , O , E > ,
@@ -23,7 +25,7 @@ fn parse_ident(input: &mut &'_ str) -> PResult<String> {
23
25
take_while ( 0 .., |c : char | c. is_alphanum ( ) || c == '_' ) ,
24
26
)
25
27
. recognize ( )
26
- . verify ( |i : & str | ![ "fun" , "if" , "else" , "true" , "false" , "int" , "bool" ] . contains ( & i) ) )
28
+ . verify ( |i : & str | !KEYWORDS . contains ( & i) ) )
27
29
. context ( StrContext :: Label ( "parse ident" ) )
28
30
. parse_next ( input)
29
31
. map ( |i| i. to_string ( ) )
@@ -63,7 +65,6 @@ fn parse_base_expr(input: &mut &'_ str) -> PResult<Expr> {
63
65
alt ( (
64
66
parse_int. map ( Expr :: IntLit ) ,
65
67
parse_bool. map ( Expr :: BoolLit ) ,
66
- parse_ident. map ( Expr :: Ident ) ,
67
68
seq ! {
68
69
_: ws( "if" ) ,
69
70
parse_expr,
@@ -85,6 +86,7 @@ fn parse_base_expr(input: &mut &'_ str) -> PResult<Expr> {
85
86
_: ws( ")" )
86
87
}
87
88
. map ( |( function_name, args) | Expr :: FunCall ( function_name, args) ) ,
89
+ parse_ident. map ( Expr :: Ident ) , // must come after funcall
88
90
parse_bracketed,
89
91
) )
90
92
. context ( StrContext :: Label ( "parse base expr" ) )
@@ -190,7 +192,7 @@ pub fn parse_program(input: &mut &'_ str) -> PResult<Program> {
190
192
}
191
193
192
194
pub fn parse ( mut input : & str ) -> PResult < Program > {
193
- terminated ( parse_program, eof) . parse_next ( & mut input)
195
+ terminated ( ws ( parse_program) , eof) . parse_next ( & mut input)
194
196
}
195
197
196
198
pub fn parse_trace ( mut input : & str ) -> PResult < Program > {
@@ -208,7 +210,7 @@ mod test {
208
210
209
211
use crate :: {
210
212
parse:: { parse, parse_arith_expr, parse_base_expr, parse_cmp_expr, parse_ident} ,
211
- Expr ,
213
+ Expr , Type ,
212
214
} ;
213
215
214
216
use super :: { parse_args, parse_expr, parse_function, parse_trace} ;
@@ -328,15 +330,57 @@ mod test {
328
330
. is_err( ) ) ;
329
331
}
330
332
333
+ #[ test]
334
+ pub fn parse_funcall_no_args ( ) {
335
+ let mut input = "foo()" ;
336
+ assert_eq ! (
337
+ Expr :: FunCall ( "foo" . into( ) , vec![ ] , ) ,
338
+ trace( "parse expr" , parse_expr)
339
+ . parse_next( & mut input)
340
+ . unwrap( ) ,
341
+ ) ;
342
+ }
343
+
344
+ #[ test]
345
+ pub fn parse_if_in_if ( ) {
346
+ let mut input = "if a { if b < f(42, false) { c + 2 } else { d(true) } } else { f : int }" ;
347
+ assert_eq ! (
348
+ Expr :: IfThenElse (
349
+ Expr :: Ident ( "a" . into( ) ) . into( ) ,
350
+ Expr :: IfThenElse (
351
+ Expr :: Lt (
352
+ Expr :: Ident ( "b" . into( ) ) . into( ) ,
353
+ Expr :: FunCall ( "f" . into( ) , vec![ Expr :: IntLit ( 42 ) , Expr :: BoolLit ( false ) , ] )
354
+ . into( ) ,
355
+ )
356
+ . into( ) ,
357
+ Expr :: Plus ( Expr :: Ident ( "c" . into( ) ) . into( ) , Expr :: IntLit ( 2 ) . into( ) , ) . into( ) ,
358
+ Expr :: FunCall ( "d" . into( ) , vec![ Expr :: BoolLit ( true ) , ] ) . into( ) ,
359
+ )
360
+ . into( ) ,
361
+ Expr :: Ascribe ( Expr :: Ident ( "f" . into( ) ) . into( ) , Type :: IntT , ) . into( ) ,
362
+ ) ,
363
+ parse_expr( & mut input) . unwrap( )
364
+ ) ;
365
+ }
366
+
331
367
#[ test]
332
368
pub fn parse_all_constructs ( ) {
333
369
let program = "
334
370
fun tt() = true;
335
- fun lt(i1, i2) = (1 < 2);
336
- fun and(b1, b2: bool): bool =
337
- if b1 { b2: int } else { false };
338
-
339
- $ tt()
371
+ fun not(b) = if b { false } else { true };
372
+ fun and(b1: bool, b2): bool =
373
+ if b1 {
374
+ if b2 {
375
+ true
376
+ } else {
377
+ false
378
+ }
379
+ } else {
380
+ false
381
+ };
382
+
383
+ $ and(not(false), tt())
340
384
" ;
341
385
342
386
assert ! ( parse_trace( program) . is_ok( ) ) ;
0 commit comments