summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall_syntax/src/parser.rs75
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)),