diff options
author | Nadrieril | 2019-05-04 13:14:06 +0200 |
---|---|---|
committer | Nadrieril | 2019-05-04 13:14:06 +0200 |
commit | 68d1e5f42e3cf4cf132d1cd7d1d1775e48cf2a43 (patch) | |
tree | 99958d8729d76c9407f01ab10011f7484ad688ee | |
parent | a582338869195c83850ac0a9d9737ff1275e39e1 (diff) |
Replace pest::Span with a custom non-borrowing implementation
-rw-r--r-- | dhall_syntax/src/parser.rs | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index 12383d4..b8a7002 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -1,13 +1,14 @@ use itertools::Itertools; use pest::iterators::Pair; use pest::Parser; -pub use pest::Span; use std::borrow::Cow; use std::collections::BTreeMap; use std::path::PathBuf; +use std::rc::Rc; use dhall_generated_parser::{DhallParser, Rule}; +use crate::ExprF::*; use crate::*; // This file consumes the parse tree generated by pest and turns it into @@ -15,8 +16,6 @@ use crate::*; // their own crate because they are quite general and useful. For now they // are here and hopefully you can figure out how they work. -use crate::ExprF::*; - type ParsedExpr<'a> = Expr<Span<'a>, Import>; type ParsedSubExpr<'a> = SubExpr<Span<'a>, Import>; type ParsedText<'a> = InterpolatedText<SubExpr<Span<'a>, Import>>; @@ -31,6 +30,31 @@ fn rc(x: ParsedExpr<'_>) -> ParsedSubExpr<'_> { crate::rc(x) } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Span<'a> { + input: Rc<str>, + /// # Safety + /// + /// Must be a valid character boundary index into `input`. + start: usize, + /// # Safety + /// + /// Must be a valid character boundary index into `input`. + end: usize, + phantom: std::marker::PhantomData<&'a ()>, +} + +impl<'a> Span<'a> { + fn make(input: Rc<str>, sp: pest::Span) -> Self { + Span { + input, + start: sp.start(), + end: sp.end(), + phantom: std::marker::PhantomData, + } + } +} + fn spanned<'a>(_span: Span<'a>, x: ParsedExpr<'a>) -> ParsedExpr<'a> { x // This breaks equality testing; I need to fix that first @@ -137,19 +161,16 @@ macro_rules! make_parser { (@filter, rule_group) => (false); (@body, - $pair:expr, - $children:expr, + ($($things:tt)*), rule!( $name:ident<$o:ty>; $($args:tt)* ) ) => ( make_parser!(@body, - $pair, - $children, + ($($things)*), rule!( $name<$o> as $name; $($args)* ) ) ); (@body, - $pair:expr, - $children:expr, + ($_input:expr, $pair:expr, $_children:expr), rule!( $name:ident<$o:ty> as $group:ident; @@ -161,8 +182,7 @@ macro_rules! make_parser { Ok(ParsedValue::$group(res)) }); (@body, - $pair:expr, - $children:expr, + ($_input:expr, $_pair:expr, $children:expr), rule!( $name:ident<$o:ty> as $group:ident; @@ -181,8 +201,7 @@ macro_rules! make_parser { Ok(ParsedValue::$group(res)) }); (@body, - $pair:expr, - $children:expr, + ($input:expr, $pair:expr, $children:expr), rule!( $name:ident<$o:ty> as $group:ident; @@ -190,10 +209,9 @@ macro_rules! make_parser { $($args:tt)* ) ) => ({ - let $span = $pair.as_span(); + let $span = Span::make($input, $pair.as_span()); make_parser!(@body, - $pair, - $children, + ($input, $pair, $children), rule!( $name<$o> as $group; @@ -202,13 +220,12 @@ macro_rules! make_parser { ) }); (@body, - $pair:expr, - $children:expr, + ($($things:tt)*), token_rule!($name:ident<$o:ty>) ) => ({ Ok(ParsedValue::$name(())) }); - (@body, $pair:expr, $children:expr, rule_group!( $name:ident<$o:ty> )) => ( + (@body, ($($things:tt)*), rule_group!( $name:ident<$o:ty> )) => ( unreachable!() ); @@ -219,13 +236,16 @@ macro_rules! make_parser { $( $name($o), )* } - fn parse_any<'a>(pair: Pair<'a, Rule>, children: Vec<ParsedValue<'a>>) - -> Result<ParsedValue<'a>, String> { + fn parse_any<'a>( + input: Rc<str>, + pair: Pair<'a, Rule>, + children: Vec<ParsedValue<'a>>, + ) -> Result<ParsedValue<'a>, String> { match pair.as_rule() { $( make_parser!(@pattern, $submac, $name) if make_parser!(@filter, $submac) - => make_parser!(@body, pair, children, + => make_parser!(@body, (input, pair, children), $submac!( $name<$o> $($args)* )) , )* @@ -236,7 +256,10 @@ macro_rules! make_parser { } // Non-recursive implementation to avoid stack overflows -fn do_parse<'a>(initial_pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> { +fn do_parse<'a>( + input: Rc<str>, + initial_pair: Pair<'a, Rule>, +) -> ParseResult<ParsedValue<'a>> { enum StackFrame<'a> { Unprocessed(Pair<'a, Rule>), Processed(Pair<'a, Rule>, usize), @@ -264,7 +287,8 @@ fn do_parse<'a>(initial_pair: Pair<'a, Rule>) -> ParseResult<ParsedValue<'a>> { let mut children: Vec<_> = values_stack.split_off(values_stack.len() - n); children.reverse(); - let val = match parse_any(pair.clone(), children) { + let val = match parse_any(input.clone(), pair.clone(), children) + { Ok(v) => v, Err(msg) => Err(custom_parse_error(&pair, msg))?, }; @@ -958,7 +982,8 @@ make_parser! { pub fn parse_expr<'a>(s: &'a str) -> ParseResult<ParsedSubExpr<'a>> { let mut pairs = DhallParser::parse(Rule::final_expression, s)?; - let expr = do_parse(pairs.next().unwrap())?; + let rc_input = s.to_string().into(); + let expr = do_parse(rc_input, pairs.next().unwrap())?; assert_eq!(pairs.next(), None); match expr { ParsedValue::expression(e) => Ok(rc(e)), |