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_core | |
parent | a6f61ec4843f4ec91eb9651b79c8b843fb995b46 (diff) |
Parse multiline strings correctly
Closes #24
Diffstat (limited to 'dhall_core')
-rw-r--r-- | dhall_core/src/parser.rs | 68 | ||||
-rw-r--r-- | dhall_core/src/text.rs | 2 |
2 files changed, 50 insertions, 20 deletions
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>), |