summaryrefslogtreecommitdiff
path: root/dhall
diff options
context:
space:
mode:
Diffstat (limited to 'dhall')
-rw-r--r--dhall/src/core.rs5
-rw-r--r--dhall/src/parser.rs127
2 files changed, 108 insertions, 24 deletions
diff --git a/dhall/src/core.rs b/dhall/src/core.rs
index 473a6a6..ccaf0f5 100644
--- a/dhall/src/core.rs
+++ b/dhall/src/core.rs
@@ -179,6 +179,8 @@ pub enum Expr<'i, S, A> {
Note(S, Box<Expr<'i, S, A>>),
/// `Embed path ~ path`
Embed(A),
+
+ FailedParse(String, Vec<Expr<'i, S, A>>),
}
/// Built-in types
@@ -698,6 +700,7 @@ pub fn shift<'i, S, T, A: Clone>(d: isize, v: V, e: &Expr<'i, S, A>) -> Expr<'i,
// The Dhall compiler enforces that all embedded values are closed expressions
// and `shift` does nothing to a closed expression
Embed(ref p) => Embed(p.clone()),
+ FailedParse(_, _) => unreachable!(),
}
}
@@ -795,6 +798,7 @@ pub fn subst<'i, S, T, A>(v: V<'i>, e: &Expr<'i, S, A>, b: &Expr<'i, T, A>) -> E
Field(ref a, b) => Field(bx(subst(v, e, a)), b),
Note(_, ref b) => subst(v, e, b),
Embed(ref p) => Embed(p.clone()),
+ FailedParse(_, _) => unreachable!(),
}
}
@@ -1040,6 +1044,7 @@ pub fn normalize<'i, S, T, A>(e: &Expr<'i, S, A>) -> Expr<'i, T, A>
},
Note(_, ref e) => normalize(e),
Embed(ref a) => Embed(a.clone()),
+ FailedParse(_, _) => unreachable!(),
}
}
diff --git a/dhall/src/parser.rs b/dhall/src/parser.rs
index 057fce2..0acfe39 100644
--- a/dhall/src/parser.rs
+++ b/dhall/src/parser.rs
@@ -1,9 +1,9 @@
use lalrpop_util;
use crate::grammar;
-use crate::grammar_util::BoxExpr;
+use crate::grammar_util::{BoxExpr, ParsedExpr};
use crate::lexer::{Lexer, LexicalError, Tok};
-use crate::core::{bx, Expr};
+use crate::core::{bx, Expr, V};
pub type ParseError<'i> = lalrpop_util::ParseError<usize, Tok<'i>, LexicalError>;
@@ -14,55 +14,134 @@ pub fn parse_expr(s: &str) -> Result<BoxExpr, ParseError> {
use pest::Parser;
use pest::error::Error;
use pest::iterators::Pair;
-use crate::generated_parser::{DhallParser, Rule};
+use dhall_parser::{DhallParser, Rule};
fn debug_pair(pair: Pair<Rule>) {
- fn aux(indent: usize, pair: Pair<Rule>) {
+ fn aux(indent: usize, prefix: String, pair: Pair<Rule>) {
let indent_str = "| ".repeat(indent);
- println!(r#"{}{:?}: "{}""#, indent_str, pair.as_rule(), pair.as_str());
- for p in pair.into_inner() {
- aux(indent+1, p);
+ let rule = pair.as_rule();
+ let contents = pair.as_str().clone();
+ let mut inner = pair.into_inner();
+ let mut first = true;
+ while let Some(p) = inner.next() {
+ if first {
+ first = false;
+ let last = inner.peek().is_none();
+ if last && p.as_str() == contents {
+ let prefix = format!("{}{:?} > ", prefix, rule);
+ aux(indent, prefix, p);
+ continue;
+ } else {
+ println!(r#"{}{}{:?}: "{}""#, indent_str, prefix, rule, contents);
+ }
+ }
+ aux(indent+1, "".into(), p);
+ }
+ if first {
+ println!(r#"{}{}{:?}: "{}""#, indent_str, prefix, rule, contents);
}
+ // println!(r#"{}{}{:?}: "{}""#, indent_str, prefix, rule, contents);
+ // for p in inner {
+ // aux(indent+1, "".into(), p);
+ // }
}
- aux(0, pair)
+ aux(0, "".into(), pair)
}
pub fn parse_expr_pest(s: &str) -> Result<BoxExpr, Error<Rule>> {
- let parsed_expr = DhallParser::parse(Rule::complete_expression, s)?.next().unwrap();
+ let parsed_expr = DhallParser::parse(Rule::final_expression, s)?.next().unwrap();
debug_pair(parsed_expr.clone());
// println!("{}", parsed_expr.clone());
- fn parse_pair(pair: Pair<Rule>) -> BoxExpr {
+ 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 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_expression(pair: Pair<Rule>) -> BoxExpr {
match pair.as_rule() {
- Rule::natural_literal => bx(Expr::NaturalLit(str::parse(pair.as_str().trim()).unwrap())),
- Rule::plus_expression => {
- let mut inner = pair.into_inner().map(parse_pair);
- let first_expr = inner.next().unwrap();
- inner.fold(first_expr, |acc, e| bx(Expr::NaturalPlus(acc, e)))
+ 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::times_expression => {
- let mut inner = pair.into_inner().map(parse_pair);
- let first_expr = inner.next().unwrap();
- inner.fold(first_expr, |acc, e| bx(Expr::NaturalTimes(acc, e)))
+
+
+ // 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)),
+
+ _ => {
+ let rulename = format!("{:?}", pair.as_rule());
+ let mut inner = pair.into_inner().map(parse_expression).map(|x| *x);
+ bx(Expr::FailedParse(rulename, inner.collect()))
}
- r => panic!("{:?}", r),
}
}
- Ok(parse_pair(parsed_expr))
+ Ok(parse_expression(parsed_expr))
}
#[test]
fn test_parse() {
use crate::core::Expr::*;
- let expr = "((22 + 3) * 10)";
+ // 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));
match parse_expr_pest(expr) {
- Err(e) => println!("{}", e),
+ Err(e) => {
+ println!("{:?}", e);
+ println!("{}", e);
+ },
ok => println!("{:?}", ok),
}
- assert_eq!(parse_expr_pest(expr).unwrap(), parse_expr(expr).unwrap());
+ // assert_eq!(parse_expr_pest(expr).unwrap(), parse_expr(expr).unwrap());
assert!(false);
println!("test {:?}", parse_expr("3 + 5 * 10"));