Merge pull request #46 from rtfeldman/fix-parser-bug

Fix parser bug
This commit is contained in:
Richard Feldman 2019-12-05 19:44:58 -05:00 committed by GitHub
commit 1a88c03b95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 139 additions and 7 deletions

View file

@ -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};

View file

@ -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";

View file

@ -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)
)
}

View file

@ -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)),
}
})
}

View file

@ -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]