roc/tests/test_parse.rs
Richard Feldman 0bf66a9911 wip
2019-09-07 09:43:19 -04:00

313 lines
8.8 KiB
Rust

#[macro_use]
extern crate pretty_assertions;
#[macro_use]
extern crate indoc;
extern crate bumpalo;
extern crate combine; // OBSOLETE
extern crate roc;
mod helpers;
#[cfg(test)]
mod test_parser {
use bumpalo::Bump;
use helpers::located;
use roc::parse;
use roc::parse::ast::Attempting;
use roc::parse::ast::Expr::{self, *};
use roc::parse::parser::{Parser, State};
use roc::parse::problems::Problem;
use roc::region::Located;
fn assert_parses_to<'a>(input: &'a str, expected_expr: Expr<'a>) {
let state = State::new(&input, Attempting::Expression);
let arena = Bump::new();
let parser = parse::expr();
let answer = parser.parse(&arena, state);
let actual = answer.map(|(expr, _)| expr);
assert_eq!(Ok(expected_expr), actual);
}
fn assert_malformed_str<'a>(input: &'a str, expected_probs: Vec<Located<Problem>>) {
let state = State::new(&input, Attempting::Expression);
let arena = Bump::new();
let parser = parse::expr();
let answer = parser.parse(&arena, state);
let actual = answer.map(|(expr, _)| expr);
assert_eq!(
Ok(Expr::MalformedStr(expected_probs.into_boxed_slice())),
actual
);
}
/* fn raw(string: &str) -> Ident { */
/* Ident::Unqualified(string.to_string()) */
/* } */
// STRING LITERALS
fn expect_parsed_str(input: &str, expected: &str) {
assert_parses_to(expected, Str(input.into()));
}
#[test]
fn empty_string() {
assert_parses_to(
indoc!(
r#"
""
"#
),
EmptyStr,
);
}
#[test]
fn one_char_list() {
assert_parses_to(
indoc!(
r#"
"x"
"#
),
Str("x".into()),
);
}
#[test]
fn multi_char_list() {
assert_parses_to(
indoc!(
r#"
"foo"
"#
),
Str("foo".into()),
);
}
#[test]
fn string_without_escape() {
expect_parsed_str("a", r#""a""#);
expect_parsed_str("ab", r#""ab""#);
expect_parsed_str("abc", r#""abc""#);
expect_parsed_str("123", r#""123""#);
expect_parsed_str("abc123", r#""abc123""#);
expect_parsed_str("123abc", r#""123abc""#);
expect_parsed_str("123 abc 456 def", r#""123 abc 456 def""#);
}
#[test]
fn string_with_special_escapes() {
expect_parsed_str(r#"x\x"#, r#""x\\x""#);
expect_parsed_str(r#"x"x"#, r#""x\"x""#);
expect_parsed_str("x\tx", r#""x\tx""#);
expect_parsed_str("x\rx", r#""x\rx""#);
expect_parsed_str("x\nx", r#""x\nx""#);
}
#[test]
fn string_with_escaped_interpolation() {
assert_parses_to(
// This should NOT be string interpolation, because of the \\
indoc!(
r#"
"abcd\\(efg)hij"
"#
),
Str(r#"abcd\(efg)hij"#.into()),
);
}
#[test]
fn string_with_single_quote() {
// This shoud NOT be escaped in a string.
expect_parsed_str("x'x", r#""x'x""#);
}
#[test]
fn string_with_valid_unicode_escapes() {
expect_parsed_str("x\u{00A0}x", r#""x\u{00A0}x""#);
expect_parsed_str("x\u{101010}x", r#""x\u{101010}x""#);
}
#[test]
fn string_with_too_large_unicode_escape() {
// Should be too big - max size should be 10FFFF.
// (Rust has this restriction. I assume it's a good idea.)
assert_malformed_str(
r#""abc\u{110000}def""#,
vec![located(0, 7, 0, 12, Problem::UnicodeCodePointTooLarge)],
);
}
#[test]
fn string_with_no_unicode_digits() {
// No digits specified
assert_malformed_str(
r#""blah\u{}foo""#,
vec![located(0, 5, 0, 8, Problem::NoUnicodeDigits)],
);
}
#[test]
fn string_with_no_unicode_opening_brace() {
// No opening curly brace. It can't be sure if the closing brace
// was intended to be a closing brace for the unicode escape, so
// report that there were no digits specified.
assert_malformed_str(
r#""abc\u00A0}def""#,
vec![located(0, 4, 0, 5, Problem::NoUnicodeDigits)],
);
}
#[test]
fn string_with_no_unicode_closing_brace() {
// No closing curly brace
assert_malformed_str(
r#""blah\u{stuff""#,
vec![located(0, 5, 0, 12, Problem::MalformedEscapedUnicode)],
);
}
#[test]
fn string_with_no_unicode_braces() {
// No curly braces
assert_malformed_str(
r#""zzzz\uzzzzz""#,
vec![located(0, 5, 0, 6, Problem::NoUnicodeDigits)],
);
}
/* #[test] */
/* fn string_with_interpolation_at_start() { */
/* assert_fully_parses( */
/* indoc!( */
/* r#" */
/* "\(abc)defg" */
/* "# */
/* ), */
/* InterpolatedStr(vec![("".to_string(), loc(raw("abc")))], "defg".to_string()), */
/* ); */
/* } */
/* #[test] */
/* fn string_with_interpolation_at_end() { */
/* assert_fully_parses( */
/* indoc!( */
/* r#" */
/* "abcd\(efg)" */
/* "# */
/* ), */
/* InterpolatedStr(vec![("abcd".to_string(), loc(raw("efg")))], "".to_string()), */
/* ); */
/* } */
/* #[test] */
/* fn string_with_interpolation_in_middle() { */
/* assert_fully_parses( */
/* indoc!( */
/* r#" */
/* "abcd\(efg)hij" */
/* "# */
/* ), */
/* InterpolatedStr( */
/* vec![("abcd".to_string(), loc(raw("efg")))], */
/* "hij".to_string(), */
/* ), */
/* ); */
/* } */
/* #[test] */
/* fn string_with_multiple_interpolation() { */
/* panic!("TODO start, middle, middle again, *and*, end"); */
/* assert_fully_parses( */
/* indoc!( */
/* r#" */
/* "abcd\(efg)hij" */
/* "# */
/* ), */
/* InterpolatedStr( */
/* vec![("abcd".to_string(), loc(raw("efg")))], */
/* "hij".to_string(), */
/* ), */
/* ); */
/* } */
// TODO test for \t \r and \n in string literals *outside* unicode escape sequence!
//
// TODO verify that when a string literal contains a newline before the
// closing " it correctly updates both the line *and* column in the State.
//
// TODO verify that exceeding maximum line length does NOT panic
// TODO verify that exceeding maximum line count does NOT panic
// NUMBER LITERALS
#[test]
fn positive_int() {
assert_parses_to("1", Int(1));
assert_parses_to("42", Int(42));
assert_parses_to(&std::i64::MAX.to_string(), Int(std::i64::MAX));
}
#[test]
fn negative_int() {
assert_parses_to("-1", Int(-1));
assert_parses_to("-42", Int(-42));
assert_parses_to(&std::i64::MIN.to_string(), Int(std::i64::MIN));
}
// fn expect_parsed_float<'a>(expected: f64, actual: &str) {
// assert_eq!(
// Ok((Float(expected), "".to_string())),
// parse_without_loc(actual)
// );
// }
// fn expect_parsed_int<'a>(expected: i64, actual: &str) {
// assert_eq!(
// Ok((Int(expected), "".to_string())),
// parse_without_loc(actual)
// );
// }
// #[test]
// fn positive_int() {
// expect_parsed_int(1234, "1234");
// }
// #[test]
// fn negative_int() {
// expect_parsed_int(-1234, "-1234");
// }
// #[test]
// fn positive_float() {
// expect_parsed_float(123.45, "123.45");
// expect_parsed_float(42.00, "42.00");
// }
// #[test]
// fn negative_float() {
// expect_parsed_float(-1234.567, "-1234.567");
// expect_parsed_float(-192.0, "-192.0");
// }
// #[test]
// fn ints_with_underscores() {
// expect_parsed_int(987654321, "987_6_5_432_1");
// expect_parsed_int(-1234567890, "-1_234_567_890");
// }
// #[test]
// fn fracs_with_spaces() {
// expect_parsed_float(-1234.567, "-1_23_4.567");
// expect_parsed_float(-192.0, "-19_2.0");
// expect_parsed_float(123.45, "1_2_3.45");
// expect_parsed_float(42.00, "4_2.00");
// }
}