mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
commit
1a88c03b95
5 changed files with 139 additions and 7 deletions
|
@ -1,6 +1,6 @@
|
||||||
use crate::ena::snapshot_vec as sv;
|
use crate::ena::snapshot_vec as sv;
|
||||||
#[cfg(feature = "persistent")]
|
#[cfg(feature = "persistent")]
|
||||||
use im::Vector;
|
use im_rc::Vector;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{self, Range};
|
use std::ops::{self, Range};
|
||||||
|
|
|
@ -3,3 +3,4 @@ pub static THEN: &str = "then";
|
||||||
pub static ELSE: &str = "else";
|
pub static ELSE: &str = "else";
|
||||||
pub static CASE: &str = "case";
|
pub static CASE: &str = "case";
|
||||||
pub static WHEN: &str = "when";
|
pub static WHEN: &str = "when";
|
||||||
|
pub static AS: &str = "as";
|
||||||
|
|
|
@ -599,7 +599,8 @@ fn reserved_keyword<'a>() -> impl Parser<'a, ()> {
|
||||||
string(keyword::THEN),
|
string(keyword::THEN),
|
||||||
string(keyword::ELSE),
|
string(keyword::ELSE),
|
||||||
string(keyword::CASE),
|
string(keyword::CASE),
|
||||||
string(keyword::WHEN)
|
string(keyword::WHEN),
|
||||||
|
string(keyword::AS)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,8 +228,10 @@ where
|
||||||
P: Parser<'a, Val>,
|
P: Parser<'a, Val>,
|
||||||
{
|
{
|
||||||
move |arena, state: State<'a>| {
|
move |arena, state: State<'a>| {
|
||||||
|
let original_state = state.clone();
|
||||||
|
|
||||||
parser.parse(arena, state).and_then(|(answer, state)| {
|
parser.parse(arena, state).and_then(|(answer, state)| {
|
||||||
let original_state = state.clone();
|
let after_parse = state.clone();
|
||||||
|
|
||||||
match by.parse(arena, state) {
|
match by.parse(arena, state) {
|
||||||
Ok((_, state)) => Err((
|
Ok((_, state)) => Err((
|
||||||
|
@ -239,7 +241,7 @@ where
|
||||||
},
|
},
|
||||||
original_state,
|
original_state,
|
||||||
)),
|
)),
|
||||||
Err(_) => Ok((answer, original_state)),
|
Err(_) => Ok((answer, after_parse)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,7 +267,21 @@ mod test_parse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 arena = Bump::new();
|
||||||
let tuple = arena.alloc((
|
let tuple = arena.alloc((
|
||||||
Located::new(0, 0, 0, 1, Int("1")),
|
Located::new(0, 0, 0, 1, Int("1")),
|
||||||
|
@ -281,7 +295,58 @@ mod test_parse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 arena = Bump::new();
|
||||||
let spaced_int = Expr::SpaceAfter(
|
let spaced_int = Expr::SpaceAfter(
|
||||||
arena.alloc(Int("3")),
|
arena.alloc(Int("3")),
|
||||||
|
@ -299,7 +364,25 @@ mod test_parse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 arena = Bump::new();
|
||||||
let spaced_int = arena
|
let spaced_int = arena
|
||||||
.alloc(Int("4"))
|
.alloc(Int("4"))
|
||||||
|
@ -315,6 +398,23 @@ mod test_parse {
|
||||||
assert_eq!(Ok(expected), actual);
|
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]
|
#[test]
|
||||||
fn comment_with_unicode() {
|
fn comment_with_unicode() {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
|
@ -450,6 +550,34 @@ mod test_parse {
|
||||||
assert_eq!(Ok(expected), actual);
|
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
|
// VAR
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue