diff --git a/src/ena/unify/backing_vec.rs b/src/ena/unify/backing_vec.rs index 0430336c4a..dc7a113701 100644 --- a/src/ena/unify/backing_vec.rs +++ b/src/ena/unify/backing_vec.rs @@ -1,6 +1,6 @@ use crate::ena::snapshot_vec as sv; #[cfg(feature = "persistent")] -use im::Vector; +use im_rc::Vector; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::{self, Range}; diff --git a/src/parse/keyword.rs b/src/parse/keyword.rs index 4be15a1315..f856cee785 100644 --- a/src/parse/keyword.rs +++ b/src/parse/keyword.rs @@ -3,3 +3,4 @@ pub static THEN: &str = "then"; pub static ELSE: &str = "else"; pub static CASE: &str = "case"; pub static WHEN: &str = "when"; +pub static AS: &str = "as"; diff --git a/src/parse/mod.rs b/src/parse/mod.rs index c9e63bc821..d11f8aeee2 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -599,7 +599,8 @@ fn reserved_keyword<'a>() -> impl Parser<'a, ()> { string(keyword::THEN), string(keyword::ELSE), string(keyword::CASE), - string(keyword::WHEN) + string(keyword::WHEN), + string(keyword::AS) ) } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 659045e078..46221955fc 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -228,8 +228,10 @@ where P: Parser<'a, Val>, { move |arena, state: State<'a>| { + let original_state = state.clone(); + parser.parse(arena, state).and_then(|(answer, state)| { - let original_state = state.clone(); + let after_parse = state.clone(); match by.parse(arena, state) { Ok((_, state)) => Err(( @@ -239,7 +241,7 @@ where }, original_state, )), - Err(_) => Ok((answer, original_state)), + Err(_) => Ok((answer, after_parse)), } }) } diff --git a/tests/test_parse.rs b/tests/test_parse.rs index 5a3a57b0c9..3acec4f8b9 100644 --- a/tests/test_parse.rs +++ b/tests/test_parse.rs @@ -267,7 +267,21 @@ mod test_parse { } #[test] - fn ops_with_spaces() { + fn one_minus_two() { + let arena = Bump::new(); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Int("1")), + Located::new(0, 0, 1, 2, Minus), + Located::new(0, 0, 2, 3, Int("2")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "1-2"); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn add_with_spaces() { let arena = Bump::new(); let tuple = arena.alloc(( Located::new(0, 0, 0, 1, Int("1")), @@ -281,7 +295,58 @@ mod test_parse { } #[test] - fn newline_before_op() { + fn sub_with_spaces() { + let arena = Bump::new(); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Int("1")), + Located::new(0, 0, 3, 4, Minus), + Located::new(0, 0, 7, 8, Int("2")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "1 - 2"); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn add_var_with_spaces() { + // This is a regression test! It used to break with subtraction and work + // with other arithmetic operatos. + // + // Subtraction is special when it comes to parsing, because of unary negation. + + let arena = Bump::new(); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Var(&[], "x")), + Located::new(0, 0, 2, 3, Plus), + Located::new(0, 0, 4, 5, Int("2")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "x + 2"); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn sub_var_with_spaces() { + // This is a regression test! It used to break with subtraction and work + // with other arithmetic operatos. + // + // Subtraction is special when it comes to parsing, because of unary negation. + let arena = Bump::new(); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Var(&[], "x")), + Located::new(0, 0, 2, 3, Minus), + Located::new(0, 0, 4, 5, Int("2")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "x - 2"); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn newline_before_add() { let arena = Bump::new(); let spaced_int = Expr::SpaceAfter( arena.alloc(Int("3")), @@ -299,7 +364,25 @@ mod test_parse { } #[test] - fn newline_after_op() { + fn newline_before_sub() { + let arena = Bump::new(); + let spaced_int = Expr::SpaceAfter( + arena.alloc(Int("3")), + bumpalo::vec![in &arena; Newline].into_bump_slice(), + ); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, spaced_int), + Located::new(1, 1, 0, 1, Minus), + Located::new(1, 1, 2, 3, Int("4")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "3 \n- 4"); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn newline_after_mul() { let arena = Bump::new(); let spaced_int = arena .alloc(Int("4")) @@ -315,6 +398,23 @@ mod test_parse { assert_eq!(Ok(expected), actual); } + #[test] + fn newline_after_sub() { + let arena = Bump::new(); + let spaced_int = arena + .alloc(Int("4")) + .before(bumpalo::vec![in &arena; Newline].into_bump_slice()); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Int("3")), + Located::new(0, 0, 3, 4, Minus), + Located::new(1, 1, 2, 3, spaced_int), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "3 -\n 4"); + + assert_eq!(Ok(expected), actual); + } + #[test] fn comment_with_unicode() { let arena = Bump::new(); @@ -450,6 +550,34 @@ mod test_parse { assert_eq!(Ok(expected), actual); } + #[test] + fn equals() { + let arena = Bump::new(); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Var(&[], "x")), + Located::new(0, 0, 1, 3, Equals), + Located::new(0, 0, 3, 4, Var(&[], "y")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "x==y"); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn equals_with_spaces() { + let arena = Bump::new(); + let tuple = arena.alloc(( + Located::new(0, 0, 0, 1, Var(&[], "x")), + Located::new(0, 0, 2, 4, Equals), + Located::new(0, 0, 5, 6, Var(&[], "y")), + )); + let expected = BinOp(tuple); + let actual = parse_with(&arena, "x == y"); + + assert_eq!(Ok(expected), actual); + } + // VAR #[test]