diff options
-rw-r--r-- | dhall_syntax/src/parser.rs | 20 | ||||
-rw-r--r-- | pest_consume/src/lib.rs | 42 |
2 files changed, 47 insertions, 15 deletions
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index 761795a..15515f0 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -21,6 +21,8 @@ type ParsedText<E> = InterpolatedText<Expr<E>>; type ParsedTextContents<E> = InterpolatedTextContents<Expr<E>>; type ParseInput<'input, 'data> = pest_consume::ParseInput<'input, 'data, Rule, Rc<str>>; +type ParseInputs<'input, 'data> = + pest_consume::ParseInputs<'input, 'data, Rule, Rc<str>>; pub type ParseError = pest::error::Error<Rule>; pub type ParseResult<T> = Result<T, ParseError>; @@ -152,6 +154,15 @@ struct Parsers; #[make_parser(Rule)] impl Parsers { + fn entrypoint<E: Clone>(input_str: &str) -> ParseResult<Expr<E>> { + let pairs = DhallParser::parse(Rule::final_expression, input_str)?; + let rc_input_str = input_str.to_string().into(); + let inputs = ParseInputs::new(input_str, pairs, &rc_input_str); + Ok(match_inputs!(inputs; + [expression(e)] => e, + )) + } + fn EOI(_input: ParseInput) -> ParseResult<()> { Ok(()) } @@ -939,6 +950,7 @@ impl Parsers { )) } + #[alias(expression)] fn final_expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> { Ok(match_inputs!(input.children(); [expression(e), EOI(_)] => e @@ -947,11 +959,5 @@ impl Parsers { } pub fn parse_expr<E: Clone>(input_str: &str) -> ParseResult<Expr<E>> { - let mut pairs = DhallParser::parse(Rule::final_expression, input_str)?; - // TODO: proper errors - let pair = pairs.next().unwrap(); - assert_eq!(pairs.next(), None); - let rc_input_str = input_str.to_string().into(); - let input = ParseInput::new(pair, &rc_input_str); - Parsers::final_expression(input) + Parsers::entrypoint(input_str) } diff --git a/pest_consume/src/lib.rs b/pest_consume/src/lib.rs index 1a7d4f2..d97c905 100644 --- a/pest_consume/src/lib.rs +++ b/pest_consume/src/lib.rs @@ -1,5 +1,5 @@ use pest::error::{Error, ErrorVariant}; -use pest::iterators::Pair; +use pest::iterators::{Pair, Pairs}; use pest::Span; pub use pest_consume_macros::{make_parser, match_inputs}; @@ -20,8 +20,9 @@ pub struct ParseInputs<'input, 'data, Rule, Data> where Rule: pest::RuleType, { - input: ParseInput<'input, 'data, Rule, Data>, - pairs: pest::iterators::Pairs<'input, Rule>, + pairs: Pairs<'input, Rule>, + span: Span<'input>, + user_data: &'data Data, } impl<'input, 'data, Rule, Data> ParseInput<'input, 'data, Rule, Data> @@ -60,8 +61,9 @@ where // (see https://github.com/rust-lang/rust/issues/61997). pub fn children(&self) -> ParseInputs<'input, 'data, Rule, Data> { ParseInputs { - input: self.clone(), pairs: self.as_pair().clone().into_inner(), + span: self.as_span(), + user_data: self.user_data(), } } @@ -92,9 +94,25 @@ impl<'input, 'data, Rule, Data> ParseInputs<'input, 'data, Rule, Data> where Rule: pest::RuleType, { + /// `input` must be the _original_ input that `pairs` is pointing to. + pub fn new( + input: &'input str, + pairs: Pairs<'input, Rule>, + user_data: &'data Data, + ) -> Self { + let span = Span::new(input, 0, input.len()).unwrap(); + ParseInputs { + pairs, + span, + user_data, + } + } /// Create an error that points to the span of the input. pub fn error(&self, message: String) -> Error<Rule> { - self.input.error(message) + Error::new_from_span( + ErrorVariant::CustomError { message }, + self.span.clone(), + ) } pub fn aliased_rules<T>(&self) -> Vec<String> where @@ -102,6 +120,13 @@ where { self.clone().map(|p| p.as_rule_alias::<T>()).collect() } + /// Reconstruct the input with a new pair, passing the user data along. + fn with_pair( + &self, + new_pair: Pair<'input, Rule>, + ) -> ParseInput<'input, 'data, Rule, Data> { + ParseInput::new(new_pair, self.user_data) + } } /// Used by the macros. @@ -120,7 +145,7 @@ where fn next(&mut self) -> Option<Self::Item> { let child_pair = self.pairs.next()?; - let child = self.input.with_pair(child_pair); + let child = self.with_pair(child_pair); Some(child) } } @@ -132,7 +157,7 @@ where { fn next_back(&mut self) -> Option<Self::Item> { let child_pair = self.pairs.next_back()?; - let child = self.input.with_pair(child_pair); + let child = self.with_pair(child_pair); Some(child) } } @@ -157,8 +182,9 @@ where { fn clone(&self) -> Self { ParseInputs { - input: self.input.clone(), pairs: self.pairs.clone(), + span: self.span.clone(), + user_data: self.user_data, } } } |