summaryrefslogtreecommitdiff
path: root/dhall
diff options
context:
space:
mode:
authorNadrieril2019-03-02 22:21:43 +0100
committerNadrieril2019-03-02 22:25:38 +0100
commit54d3f23e68bf6e769d8a96e40a2b0c4426e38507 (patch)
tree60024b9d191aff4dd21d5f3489c786088a07f52c /dhall
parent48d89a280838919c1fba9e0acf1e090d3286c470 (diff)
Add parser/failure tests from spec
Diffstat (limited to 'dhall')
-rw-r--r--dhall/src/main.rs2
-rw-r--r--dhall/src/parser.rs163
-rw-r--r--dhall/tests/macros.rs8
-rw-r--r--dhall/tests/tests.rs10
4 files changed, 100 insertions, 83 deletions
diff --git a/dhall/src/main.rs b/dhall/src/main.rs
index cdab3c0..58826bb 100644
--- a/dhall/src/main.rs
+++ b/dhall/src/main.rs
@@ -52,7 +52,7 @@ fn print_error(message: &str, source: &str, start: usize, end: usize) {
fn main() {
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer).unwrap();
- let expr = match parser::parse_expr(&buffer) {
+ let expr = match parser::parse_expr_lalrpop(&buffer) {
Ok(e) => e,
Err(lalrpop_util::ParseError::User { error: lexer::LexicalError::Error(pos, e) }) => {
print_error(&format!("Unexpected token {:?}", e), &buffer, pos, pos);
diff --git a/dhall/src/parser.rs b/dhall/src/parser.rs
index 0acfe39..9259dfd 100644
--- a/dhall/src/parser.rs
+++ b/dhall/src/parser.rs
@@ -7,7 +7,7 @@ use crate::core::{bx, Expr, V};
pub type ParseError<'i> = lalrpop_util::ParseError<usize, Tok<'i>, LexicalError>;
-pub fn parse_expr(s: &str) -> Result<BoxExpr, ParseError> {
+pub fn parse_expr_lalrpop(s: &str) -> Result<BoxExpr, ParseError> {
grammar::ExprParser::new().parse(Lexer::new(s))
}
@@ -48,80 +48,81 @@ fn debug_pair(pair: Pair<Rule>) {
aux(0, "".into(), pair)
}
-pub fn parse_expr_pest(s: &str) -> Result<BoxExpr, Error<Rule>> {
- let parsed_expr = DhallParser::parse(Rule::final_expression, s)?.next().unwrap();
- debug_pair(parsed_expr.clone());
- // println!("{}", parsed_expr.clone());
-
- fn parse_binop<'a, F>(pair: Pair<'a, Rule>, mut f: F) -> BoxExpr<'a>
- where F: FnMut(BoxExpr<'a>, BoxExpr<'a>) -> ParsedExpr<'a> {
- let mut inner = pair.into_inner().map(parse_expression);
- let first_expr = inner.next().unwrap();
- inner.fold(first_expr, |acc, e| bx(f(acc, e)))
- }
+fn parse_binop<'a, F>(pair: Pair<'a, Rule>, mut f: F) -> BoxExpr<'a>
+where F: FnMut(BoxExpr<'a>, BoxExpr<'a>) -> ParsedExpr<'a> {
+ let mut inner = pair.into_inner().map(parse_expression);
+ let first_expr = inner.next().unwrap();
+ inner.fold(first_expr, |acc, e| bx(f(acc, e)))
+}
- fn skip_expr(pair: Pair<Rule>) -> BoxExpr {
- let mut inner = pair.into_inner().map(parse_expression);
- inner.next().unwrap()
- }
+fn skip_expr(pair: Pair<Rule>) -> BoxExpr {
+ let mut inner = pair.into_inner().map(parse_expression);
+ inner.next().unwrap()
+}
- fn parse_str(pair: Pair<Rule>) -> &str {
- pair.as_str().trim()
- }
+fn parse_str(pair: Pair<Rule>) -> &str {
+ pair.as_str().trim()
+}
- fn parse_natural(pair: Pair<Rule>) -> Result<usize, std::num::ParseIntError> {
- parse_str(pair).parse()
- }
+fn parse_natural(pair: Pair<Rule>) -> Result<usize, std::num::ParseIntError> {
+ parse_str(pair).parse()
+}
- fn parse_expression(pair: Pair<Rule>) -> BoxExpr {
- match pair.as_rule() {
- Rule::natural_literal_raw => bx(Expr::NaturalLit(parse_natural(pair).unwrap())),
-
- Rule::annotated_expression => { parse_binop(pair, Expr::Annot) }
- Rule::import_alt_expression => { skip_expr(pair) }
- Rule::or_expression => { parse_binop(pair, Expr::BoolOr) }
- Rule::plus_expression => { parse_binop(pair, Expr::NaturalPlus) }
- Rule::text_append_expression => { parse_binop(pair, Expr::TextAppend) }
- Rule::list_append_expression => { skip_expr(pair) }
- Rule::and_expression => { parse_binop(pair, Expr::BoolAnd) }
- Rule::combine_expression => { skip_expr(pair) }
- Rule::prefer_expression => { skip_expr(pair) }
- Rule::combine_types_expression => { skip_expr(pair) }
- Rule::times_expression => { parse_binop(pair, Expr::NaturalTimes) }
- Rule::equal_expression => { parse_binop(pair, Expr::BoolEQ) }
- Rule::not_equal_expression => { parse_binop(pair, Expr::BoolNE) }
- Rule::application_expression => { parse_binop(pair, Expr::App) }
-
- Rule::selector_expression_raw => {
- let mut inner = pair.into_inner();
- let first_expr = parse_expression(inner.next().unwrap());
- inner.fold(first_expr, |acc, e| bx(Expr::Field(acc, e.as_str())))
- }
+fn parse_expression(pair: Pair<Rule>) -> BoxExpr {
+ match pair.as_rule() {
+ Rule::natural_literal_raw => bx(Expr::NaturalLit(parse_natural(pair).unwrap())),
+
+ Rule::annotated_expression => { parse_binop(pair, Expr::Annot) }
+ Rule::import_alt_expression => { skip_expr(pair) }
+ Rule::or_expression => { parse_binop(pair, Expr::BoolOr) }
+ Rule::plus_expression => { parse_binop(pair, Expr::NaturalPlus) }
+ Rule::text_append_expression => { parse_binop(pair, Expr::TextAppend) }
+ Rule::list_append_expression => { skip_expr(pair) }
+ Rule::and_expression => { parse_binop(pair, Expr::BoolAnd) }
+ Rule::combine_expression => { skip_expr(pair) }
+ Rule::prefer_expression => { skip_expr(pair) }
+ Rule::combine_types_expression => { skip_expr(pair) }
+ Rule::times_expression => { parse_binop(pair, Expr::NaturalTimes) }
+ Rule::equal_expression => { parse_binop(pair, Expr::BoolEQ) }
+ Rule::not_equal_expression => { parse_binop(pair, Expr::BoolNE) }
+ Rule::application_expression => { parse_binop(pair, Expr::App) }
+
+ Rule::selector_expression_raw => {
+ let mut inner = pair.into_inner();
+ let first_expr = parse_expression(inner.next().unwrap());
+ inner.fold(first_expr, |acc, e| bx(Expr::Field(acc, e.as_str())))
+ }
- Rule::identifier_raw => {
- let mut inner = pair.into_inner();
- let name = parse_str(inner.next().unwrap());
- let idx = inner.next().map(parse_natural).unwrap_or(Ok(0)).unwrap();
- bx(Expr::Var(V(name, idx)))
- }
+ Rule::identifier_raw => {
+ let mut inner = pair.into_inner();
+ let name = parse_str(inner.next().unwrap());
+ let idx = inner.next().map(parse_natural).unwrap_or(Ok(0)).unwrap();
+ bx(Expr::Var(V(name, idx)))
+ }
- // Rule::record_type_or_literal => {
- // let mut inner = pair.into_inner();
- // let first_expr = parse_expression(inner.next().unwrap());
- // inner.fold(first_expr, |acc, e| bx(Expr::Field(acc, e.as_str())))
- // }
+ // Rule::record_type_or_literal => {
+ // let mut inner = pair.into_inner();
+ // let first_expr = parse_expression(inner.next().unwrap());
+ // inner.fold(first_expr, |acc, e| bx(Expr::Field(acc, e.as_str())))
+ // }
- // r => panic!("{:?}", r),
- // _ => bx(Expr::BoolLit(false)),
+ // r => panic!("{:?}", r),
+ // _ => bx(Expr::BoolLit(false)),
- _ => {
- let rulename = format!("{:?}", pair.as_rule());
- let mut inner = pair.into_inner().map(parse_expression).map(|x| *x);
- bx(Expr::FailedParse(rulename, inner.collect()))
- }
+ _ => {
+ let rulename = format!("{:?}", pair.as_rule());
+ let mut inner = pair.into_inner().map(parse_expression).map(|x| *x);
+ bx(Expr::FailedParse(rulename, inner.collect()))
}
}
+}
+
+pub fn parse_expr_pest(s: &str) -> Result<BoxExpr, Error<Rule>> {
+ let parsed_expr = DhallParser::parse(Rule::final_expression, s)?.next().unwrap();
+ debug_pair(parsed_expr.clone());
+ // println!("{}", parsed_expr.clone());
+
Ok(parse_expression(parsed_expr))
}
@@ -133,7 +134,7 @@ fn test_parse() {
// let expr = r#"{ x = "foo", y = 4 }.x"#;
// let expr = r#"(1 + 2) * 3"#;
let expr = r#"if True then 1 + 3 * 5 else 2"#;
- println!("{:?}", parse_expr(expr));
+ println!("{:?}", parse_expr_lalrpop(expr));
match parse_expr_pest(expr) {
Err(e) => {
println!("{:?}", e);
@@ -144,27 +145,27 @@ fn test_parse() {
// assert_eq!(parse_expr_pest(expr).unwrap(), parse_expr(expr).unwrap());
assert!(false);
- println!("test {:?}", parse_expr("3 + 5 * 10"));
- assert!(parse_expr("22").is_ok());
- assert!(parse_expr("(22)").is_ok());
- assert_eq!(parse_expr("3 + 5 * 10").ok(),
+ println!("test {:?}", parse_expr_lalrpop("3 + 5 * 10"));
+ assert!(parse_expr_lalrpop("22").is_ok());
+ assert!(parse_expr_lalrpop("(22)").is_ok());
+ assert_eq!(parse_expr_lalrpop("3 + 5 * 10").ok(),
Some(Box::new(NaturalPlus(Box::new(NaturalLit(3)),
Box::new(NaturalTimes(Box::new(NaturalLit(5)),
Box::new(NaturalLit(10))))))));
// The original parser is apparently right-associative
- assert_eq!(parse_expr("2 * 3 * 4").ok(),
+ assert_eq!(parse_expr_lalrpop("2 * 3 * 4").ok(),
Some(Box::new(NaturalTimes(Box::new(NaturalLit(2)),
Box::new(NaturalTimes(Box::new(NaturalLit(3)),
Box::new(NaturalLit(4))))))));
- assert!(parse_expr("((((22))))").is_ok());
- assert!(parse_expr("((22)").is_err());
- println!("{:?}", parse_expr("\\(b : Bool) -> b == False"));
- assert!(parse_expr("\\(b : Bool) -> b == False").is_ok());
- println!("{:?}", parse_expr("foo.bar"));
- assert!(parse_expr("foo.bar").is_ok());
- assert!(parse_expr("[] : List Bool").is_ok());
-
- // println!("{:?}", parse_expr("< Left = True | Right : Natural >"));
- // println!("{:?}", parse_expr(r#""bl${42}ah""#));
- // assert!(parse_expr("< Left = True | Right : Natural >").is_ok());
+ assert!(parse_expr_lalrpop("((((22))))").is_ok());
+ assert!(parse_expr_lalrpop("((22)").is_err());
+ println!("{:?}", parse_expr_lalrpop("\\(b : Bool) -> b == False"));
+ assert!(parse_expr_lalrpop("\\(b : Bool) -> b == False").is_ok());
+ println!("{:?}", parse_expr_lalrpop("foo.bar"));
+ assert!(parse_expr_lalrpop("foo.bar").is_ok());
+ assert!(parse_expr_lalrpop("[] : List Bool").is_ok());
+
+ // println!("{:?}", parse_expr_lalrpop("< Left = True | Right : Natural >"));
+ // println!("{:?}", parse_expr_lalrpop(r#""bl${42}ah""#));
+ // assert!(parse_expr_lalrpop("< Left = True | Right : Natural >").is_ok());
}
diff --git a/dhall/tests/macros.rs b/dhall/tests/macros.rs
index 5ad2ab3..6031a34 100644
--- a/dhall/tests/macros.rs
+++ b/dhall/tests/macros.rs
@@ -18,7 +18,13 @@ macro_rules! run_spec_test {
};
(parser, $path:expr) => {
let expr_str = include_test_str!(concat!($path, "A"));
- parser::parse_expr(&expr_str).unwrap();
+ parser::parse_expr_pest(&expr_str).map_err(|e| println!("{}", e)).unwrap();
+ // parser::parse_expr(&expr_str).unwrap();
+ };
+ (parser_failure, $path:expr) => {
+ let expr_str = include_test_str!($path);
+ parser::parse_expr_pest(&expr_str).map_err(|e| println!("{}", e)).unwrap_err();
+ // parser::parse_expr(&expr_str).unwrap();
};
}
diff --git a/dhall/tests/tests.rs b/dhall/tests/tests.rs
index 6a2ada8..0e097b2 100644
--- a/dhall/tests/tests.rs
+++ b/dhall/tests/tests.rs
@@ -211,3 +211,13 @@ make_spec_test!(parser, spec_parser_success_union, "parser/success/union");
make_spec_test!(parser, spec_parser_success_urls, "parser/success/urls");
make_spec_test!(parser, spec_parser_success_whitespace, "parser/success/whitespace");
make_spec_test!(parser, spec_parser_success_whitespaceBuffet, "parser/success/whitespaceBuffet");
+
+make_spec_test!(parser_failure, spec_parser_failure_annotation, "parser/failure/annotation");
+// make_spec_test!(parser_failure, spec_parser_failure_doubleBoundsNeg, "parser/failure/doubleBoundsNeg");
+// make_spec_test!(parser_failure, spec_parser_failure_doubleBoundsPos, "parser/failure/doubleBoundsPos");
+make_spec_test!(parser_failure, spec_parser_failure_importAccess, "parser/failure/importAccess");
+make_spec_test!(parser_failure, spec_parser_failure_incompleteIf, "parser/failure/incompleteIf");
+make_spec_test!(parser_failure, spec_parser_failure_mandatoryNewline, "parser/failure/mandatoryNewline");
+make_spec_test!(parser_failure, spec_parser_failure_missingSpace, "parser/failure/missingSpace");
+make_spec_test!(parser_failure, spec_parser_failure_spaceAfterListAppend, "parser/failure/spaceAfterListAppend");
+// make_spec_test!(parser_failure, spec_parser_failure_boundBuiltin, "parser/failure/boundBuiltin");