@@ -13,9 +13,11 @@ type ParseResult<'a, T> = IResult<&'a str, T, Error<&'a str>>;
1313
1414const KEYWORDS : & [ & str ] = & [
1515 "if" ,
16+ "in" ,
1617 "else" ,
1718 "def" ,
1819 "while" ,
20+ "for" ,
1921 "val" ,
2022 "var" ,
2123 "return" ,
@@ -101,6 +103,7 @@ fn statement(input: &str) -> IResult<&str, Statement> {
101103 alt ( (
102104 function_def,
103105 if_statement,
106+ for_statement,
104107 return_statement,
105108 assignment,
106109 declaration,
@@ -421,6 +424,29 @@ fn if_statement(input: &str) -> IResult<&str, Statement> {
421424 ) )
422425}
423426
427+ // A 'for' statement parser.
428+ // A basic 'for' statement in Python has the following
429+ // syntax:
430+ //
431+ // > for <var> in <exp>:
432+ // > <stmt>
433+ fn for_statement ( input : & str ) -> IResult < & str , Statement > {
434+ let ( input, _) = tag ( "for" ) ( input) ?;
435+ let ( input, _) = space1 ( input) ?;
436+ let ( input, var) = identifier ( input) ?;
437+ let ( input, _) = space1 ( input) ?;
438+ let ( input, _) = tag ( "in" ) ( input) ?;
439+ let ( input, _) = space1 ( input) ?;
440+ let ( input, exp) = expression ( input) ?;
441+ let ( input, _) = space0 ( input) ?;
442+ let ( input, _) = char ( ':' ) ( input) ?;
443+ let ( input, block) = indented_block ( input) ?;
444+ Ok ( (
445+ input,
446+ Statement :: For ( var, Box :: new ( exp) , Box :: new ( Statement :: Block ( block) ) ) ,
447+ ) )
448+ }
449+
424450fn declaration ( input : & str ) -> IResult < & str , Statement > {
425451 let ( input, keyword) = alt ( ( tag ( "var" ) , tag ( "val" ) ) ) ( input) ?;
426452 let ( input, _) = space1 ( input) ?;
@@ -442,19 +468,7 @@ fn assignment(input: &str) -> IResult<&str, Statement> {
442468 let ( input, _) = delimited ( space0, char ( '=' ) , space0) ( input) ?;
443469 let ( input, expr) = expression ( input) ?;
444470
445- // Infer type from expression
446- let inferred_type = match & expr {
447- Expression :: CInt ( _) => Some ( Type :: TInteger ) ,
448- Expression :: CReal ( _) => Some ( Type :: TReal ) ,
449- Expression :: CString ( _) => Some ( Type :: TString ) ,
450- Expression :: CTrue | Expression :: CFalse => Some ( Type :: TBool ) ,
451- _ => None ,
452- } ;
453-
454- Ok ( (
455- input,
456- Statement :: Assignment ( name, Box :: new ( expr) , inferred_type) ,
457- ) )
471+ Ok ( ( input, Statement :: Assignment ( name, Box :: new ( expr) ) ) )
458472}
459473
460474fn parse_type ( type_name : & str ) -> Type {
@@ -647,7 +661,7 @@ mod tests {
647661 let ( rest, stmt) = assignment ( input) . unwrap ( ) ;
648662 assert_eq ! ( rest, "" ) ;
649663 match stmt {
650- Statement :: Assignment ( name, expr, _type ) => {
664+ Statement :: Assignment ( name, expr) => {
651665 // Added _type
652666 assert_eq ! ( name, "x" ) ;
653667 match * expr {
@@ -674,7 +688,7 @@ mod tests {
674688 assert_eq ! ( rest, "" ) ;
675689
676690 match & stmts[ 0 ] {
677- Statement :: Assignment ( name, expr, _type ) => {
691+ Statement :: Assignment ( name, expr) => {
678692 // Added _type
679693 assert_eq ! ( name, "x" ) ;
680694 match * * expr {
@@ -695,7 +709,7 @@ mod tests {
695709
696710 // Verify first statement is assignment
697711 match & stmts[ 0 ] {
698- Statement :: Assignment ( name, expr, _type ) => {
712+ Statement :: Assignment ( name, expr) => {
699713 // Added _type
700714 assert_eq ! ( name, "x" ) ;
701715 assert ! ( matches!( * * expr, Expression :: CInt ( 10 ) ) ) ;
@@ -714,7 +728,7 @@ mod tests {
714728 Statement :: Block ( ref stmts) => {
715729 assert_eq ! ( stmts. len( ) , 1 ) ;
716730 match & stmts[ 0 ] {
717- Statement :: Assignment ( name, expr, _type ) => {
731+ Statement :: Assignment ( name, expr) => {
718732 assert_eq ! ( name, "y" ) ;
719733 assert ! ( matches!( * * expr, Expression :: CInt ( 1 ) ) ) ;
720734 }
@@ -730,7 +744,7 @@ mod tests {
730744 Statement :: Block ( ref stmts) => {
731745 assert_eq ! ( stmts. len( ) , 1 ) ;
732746 match & stmts[ 0 ] {
733- Statement :: Assignment ( name, expr, _type ) => {
747+ Statement :: Assignment ( name, expr) => {
734748 assert_eq ! ( name, "y" ) ;
735749 assert ! ( matches!( * * expr, Expression :: CInt ( 2 ) ) ) ;
736750 }
@@ -762,7 +776,7 @@ mod tests {
762776 Statement :: Block ( ref stmts) => {
763777 assert_eq ! ( stmts. len( ) , 1 ) ;
764778 match & stmts[ 0 ] {
765- Statement :: Assignment ( name, expr, _type ) => {
779+ Statement :: Assignment ( name, expr) => {
766780 assert_eq ! ( name, "y" ) ;
767781 assert ! ( matches!( * * expr, Expression :: CInt ( 1 ) ) ) ;
768782 }
@@ -778,7 +792,7 @@ mod tests {
778792 Statement :: Block ( ref stmts) => {
779793 assert_eq ! ( stmts. len( ) , 1 ) ;
780794 match & stmts[ 0 ] {
781- Statement :: Assignment ( name, expr, _type ) => {
795+ Statement :: Assignment ( name, expr) => {
782796 assert_eq ! ( name, "y" ) ;
783797 assert ! ( matches!( * * expr, Expression :: CInt ( 2 ) ) ) ;
784798 }
@@ -813,7 +827,7 @@ mod tests {
813827 Statement :: Block ( ref stmts) => {
814828 assert_eq ! ( stmts. len( ) , 1 ) ;
815829 match & stmts[ 0 ] {
816- Statement :: Assignment ( name, expr, _type ) => {
830+ Statement :: Assignment ( name, expr) => {
817831 assert_eq ! ( name, "y" ) ;
818832 assert ! ( matches!( * * expr, Expression :: CInt ( 1 ) ) ) ;
819833 }
@@ -829,7 +843,7 @@ mod tests {
829843 Statement :: Block ( ref stmts) => {
830844 assert_eq ! ( stmts. len( ) , 1 ) ;
831845 match & stmts[ 0 ] {
832- Statement :: Assignment ( name, expr, _type ) => {
846+ Statement :: Assignment ( name, expr) => {
833847 assert_eq ! ( name, "y" ) ;
834848 assert ! ( matches!( * * expr, Expression :: CInt ( 2 ) ) ) ;
835849 }
@@ -845,6 +859,28 @@ mod tests {
845859 }
846860 }
847861
862+ #[ test]
863+ fn test_for_statement ( ) {
864+ let input = "for x in range:\n x = x+1" ;
865+ let ( rest, stmt) = statement ( input) . unwrap ( ) ;
866+ let expected = Statement :: For (
867+ "x" . to_string ( ) ,
868+ Box :: new ( Expression :: Var ( "range" . to_string ( ) ) ) ,
869+ Box :: new ( Statement :: Block (
870+ [ Statement :: Assignment (
871+ "x" . to_string ( ) ,
872+ Box :: new ( Expression :: Add (
873+ Box :: new ( Expression :: Var ( "x" . to_string ( ) ) ) ,
874+ Box :: new ( Expression :: CInt ( 1 ) ) ,
875+ ) ) ,
876+ ) ]
877+ . to_vec ( ) ,
878+ ) ) ,
879+ ) ;
880+ assert_eq ! ( rest, "" ) ;
881+ assert_eq ! ( stmt, expected)
882+ }
883+
848884 #[ test]
849885 fn test_multiline_parse ( ) {
850886 let input = "x = 42\n y = 10" ;
@@ -853,7 +889,7 @@ mod tests {
853889 assert_eq ! ( stmts. len( ) , 2 ) ;
854890
855891 match & stmts[ 0 ] {
856- Statement :: Assignment ( name, expr, _type ) => {
892+ Statement :: Assignment ( name, expr) => {
857893 assert_eq ! ( & * * name, "x" ) ;
858894 match * * expr {
859895 Expression :: CInt ( 42 ) => ( ) ,
@@ -864,7 +900,7 @@ mod tests {
864900 }
865901
866902 match & stmts[ 1 ] {
867- Statement :: Assignment ( name, expr, _type ) => {
903+ Statement :: Assignment ( name, expr) => {
868904 assert_eq ! ( & * * name, "y" ) ;
869905 match * * expr {
870906 Expression :: CInt ( 10 ) => ( ) ,
@@ -921,7 +957,7 @@ mod tests {
921957 let ( rest, stmt) = assignment ( input) . unwrap ( ) ;
922958 assert_eq ! ( rest, "" ) ;
923959 match stmt {
924- Statement :: Assignment ( name, expr, _type ) => {
960+ Statement :: Assignment ( name, expr) => {
925961 assert_eq ! ( name, "result" ) ;
926962 match * expr {
927963 Expression :: FuncCall ( func_name, args) => {
@@ -1326,17 +1362,15 @@ mod tests {
13261362 [
13271363 Statement :: Assignment (
13281364 String :: from( "x" ) ,
1329- Box :: new( Expression :: COk ( Box :: new( Expression :: CTrue ) ) ) ,
1330- None
1365+ Box :: new( Expression :: COk ( Box :: new( Expression :: CTrue ) ) )
13311366 ) ,
13321367 Statement :: IfThenElse (
13331368 Box :: new( Expression :: Unwrap ( Box :: new( Expression :: Var ( String :: from(
13341369 "x"
13351370 ) ) ) ) ) ,
13361371 Box :: new( Statement :: Block ( vec![ Statement :: Assignment (
13371372 String :: from( "y" ) ,
1338- Box :: new( Expression :: CInt ( 1 ) ) ,
1339- Some ( Type :: TInteger )
1373+ Box :: new( Expression :: CInt ( 1 ) )
13401374 ) ] ) ) ,
13411375 None
13421376 ) ,
@@ -1346,8 +1380,7 @@ mod tests {
13461380 ) ) ) ) ,
13471381 Box :: new( Statement :: Block ( vec![ Statement :: Assignment (
13481382 String :: from( "y" ) ,
1349- Box :: new( Expression :: CInt ( 1 ) ) ,
1350- Some ( Type :: TInteger )
1383+ Box :: new( Expression :: CInt ( 1 ) )
13511384 ) ] ) ) ,
13521385 None
13531386 )
0 commit comments