diff options
author | Nadrieril | 2019-03-24 21:05:01 +0100 |
---|---|---|
committer | Nadrieril | 2019-03-24 21:05:01 +0100 |
commit | d0978c35d88811462de5c448a24770f73b321e70 (patch) | |
tree | 670eaefdf8489eac4a0cf9f48a702366f42ae4b6 /dhall | |
parent | a6f61ec4843f4ec91eb9651b79c8b843fb995b46 (diff) |
Parse multiline strings correctly
Closes #24
Diffstat (limited to '')
m--------- | dhall-lang | 0 | ||||
-rw-r--r-- | dhall/Cargo.toml | 4 | ||||
-rw-r--r-- | dhall/build.rs | 36 | ||||
-rw-r--r-- | dhall/tests/normalization.rs | 8 | ||||
-rw-r--r-- | dhall_core/src/parser.rs | 68 | ||||
-rw-r--r-- | dhall_core/src/text.rs | 2 |
6 files changed, 75 insertions, 43 deletions
diff --git a/dhall-lang b/dhall-lang -Subproject 55abd1d97a21bab45a533ea8279e28722d380a6 +Subproject e6e500d3243d6b091c6d1220dd6567a262d2e2a diff --git a/dhall/Cargo.toml b/dhall/Cargo.toml index 234daa4..e898cde 100644 --- a/dhall/Cargo.toml +++ b/dhall/Cargo.toml @@ -22,3 +22,7 @@ dhall_generator = { path = "../dhall_generator" } [dev-dependencies] pretty_assertions = "0.6.1" + +[build-dependencies] +walkdir = "2" + diff --git a/dhall/build.rs b/dhall/build.rs index c8ad6ad..cc62a97 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -1,23 +1,28 @@ use std::env; use std::ffi::OsString; -use std::fs::{self, File}; +use std::fs::File; use std::io::Write; use std::path::Path; +use walkdir::WalkDir; fn dhall_files_in_dir<'a>(dir: &'a Path) -> impl Iterator<Item = String> + 'a { - fs::read_dir(dir).unwrap().filter_map(move |path| { - let path = path.unwrap().path(); - let path = path.strip_prefix(dir).unwrap(); - if path.extension() != Some(&OsString::from("dhall")) { - return None; - } - let path = path.to_string_lossy(); - let path = path[..path.len() - 6].to_owned(); - Some(path) - }) + WalkDir::new(dir) + .into_iter() + .filter_map(|e| e.ok()) + .filter_map(move |path| { + let path = path.path(); + let path = path.strip_prefix(dir).unwrap(); + if path.extension() != Some(&OsString::from("dhall")) { + return None; + } + let path = path.to_string_lossy(); + let path = path[..path.len() - 6].to_owned(); + Some(path) + }) } fn main() -> std::io::Result<()> { + println!("cargo:rerun-if-changed=../dhall-lang/.git"); let out_dir = env::var("OUT_DIR").unwrap(); let tests_dir = Path::new("../dhall-lang/tests/"); @@ -25,17 +30,18 @@ fn main() -> std::io::Result<()> { let mut file = File::create(parser_tests_path)?; for path in dhall_files_in_dir(&tests_dir.join("parser/success/")) { - let name = &path[..path.len() - 1]; + let path = &path[..path.len() - 1]; + let name = path.replace("/", "_"); // Skip this test; parser is way too slow indebug mode if name == "largeExpression" { continue; } - writeln!(file, r#"make_spec_test!(ParserSuccess, spec_parser_success_{0}, "{0}");"#, name)?; + writeln!(file, r#"make_spec_test!(ParserSuccess, spec_parser_success_{}, "{}");"#, name, path)?; } for path in dhall_files_in_dir(&tests_dir.join("parser/failure/")) { - let name = &path; - writeln!(file, r#"make_spec_test!(ParserFailure, spec_parser_failure_{0}, "{0}");"#, name)?; + let name = path.replace("/", "_"); + writeln!(file, r#"make_spec_test!(ParserFailure, spec_parser_failure_{}, "{}");"#, name, path)?; } Ok(()) diff --git a/dhall/tests/normalization.rs b/dhall/tests/normalization.rs index 5df46a6..d2db38d 100644 --- a/dhall/tests/normalization.rs +++ b/dhall/tests/normalization.rs @@ -14,14 +14,6 @@ norm!(spec_normalization_success_haskell_tutorial_access_0, "haskell-tutorial/ac // norm!(spec_normalization_success_haskell_tutorial_combineTypes_1, "haskell-tutorial/combineTypes/1"); // norm!(spec_normalization_success_haskell_tutorial_prefer_0, "haskell-tutorial/prefer/0"); norm!(spec_normalization_success_haskell_tutorial_projection_0, "haskell-tutorial/projection/0"); -// norm!(spec_normalization_success_multiline_escape, "multiline/escape"); -// norm!(spec_normalization_success_multiline_hangingIndent, "multiline/hangingIndent"); -// norm!(spec_normalization_success_multiline_interesting, "multiline/interesting"); -// norm!(spec_normalization_success_multiline_interiorIndent, "multiline/interiorIndent"); -// norm!(spec_normalization_success_multiline_interpolation, "multiline/interpolation"); -// norm!(spec_normalization_success_multiline_preserveComment, "multiline/preserveComment"); -// norm!(spec_normalization_success_multiline_singleLine, "multiline/singleLine"); -// norm!(spec_normalization_success_multiline_twoLines, "multiline/twoLines"); norm!(spec_normalization_success_prelude_Bool_and_0, "prelude/Bool/and/0"); diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 3d5a761..fb119b1 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use pest::iterators::Pair; use pest::Parser; use std::collections::BTreeMap; @@ -321,8 +322,24 @@ make_parser! { rule!(end_of_line<()>; captured_str!(_) => ()); rule!(single_quote_literal<ParsedText>; children!( - [end_of_line(eol), single_quote_continue(contents)] => { - contents.into_iter().rev().collect::<ParsedText>() + [end_of_line(eol), single_quote_continue(lines)] => { + let space = InterpolatedTextContents::Text(" ".to_owned()); + let newline = InterpolatedTextContents::Text("\n".to_owned()); + let min_indent = lines + .iter() + .map(|l| { + l.iter().rev().take_while(|c| **c == space).count() + }) + .min() + .unwrap(); + + lines + .into_iter() + .rev() + .map(|mut l| { l.split_off(l.len() - min_indent); l }) + .intersperse(vec![newline]) + .flat_map(|x| x.into_iter().rev()) + .collect::<ParsedText>() } )); rule!(single_quote_char<&'a str>; @@ -338,25 +355,38 @@ make_parser! { [expression(e)] => e )); - rule!(single_quote_continue<Vec<ParsedTextContents>>; children!( - [interpolation(c), single_quote_continue(rest)] => { - let mut rest = rest; - rest.push(InterpolatedTextContents::Expr(c)); rest - }, - [escaped_quote_pair(c), single_quote_continue(rest)] => { - let mut rest = rest; - rest.push(InterpolatedTextContents::Text(c.to_owned())); rest - }, - [escaped_interpolation(c), single_quote_continue(rest)] => { - let mut rest = rest; - rest.push(InterpolatedTextContents::Text(c.to_owned())); rest - }, - [single_quote_char(c), single_quote_continue(rest)] => { - let mut rest = rest; - rest.push(InterpolatedTextContents::Text(c.to_owned())); rest + rule!(single_quote_continue<Vec<Vec<ParsedTextContents>>>; children!( + [interpolation(c), single_quote_continue(lines)] => { + let c = InterpolatedTextContents::Expr(c); + let mut lines = lines; + lines.last_mut().unwrap().push(c); + lines + }, + [escaped_quote_pair(c), single_quote_continue(lines)] => { + let c = InterpolatedTextContents::Text(c.to_owned()); + let mut lines = lines; + lines.last_mut().unwrap().push(c); + lines + }, + [escaped_interpolation(c), single_quote_continue(lines)] => { + let c = InterpolatedTextContents::Text(c.to_owned()); + let mut lines = lines; + lines.last_mut().unwrap().push(c); + lines + }, + [single_quote_char("\n"), single_quote_continue(lines)] => { + let mut lines = lines; + lines.push(vec![]); + lines + }, + [single_quote_char(c), single_quote_continue(lines)] => { + let c = InterpolatedTextContents::Text(c.to_owned()); + let mut lines = lines; + lines.last_mut().unwrap().push(c); + lines }, [] => { - vec![] + vec![vec![]] }, )); diff --git a/dhall_core/src/text.rs b/dhall_core/src/text.rs index 2a468d2..d377877 100644 --- a/dhall_core/src/text.rs +++ b/dhall_core/src/text.rs @@ -29,7 +29,7 @@ impl<N, E> From<String> for InterpolatedText<N, E> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum InterpolatedTextContents<Note, Embed> { Text(String), Expr(SubExpr<Note, Embed>), |