summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall_syntax/src/parser.rs72
-rw-r--r--pest_consume/src/lib.rs95
-rw-r--r--pest_consume_macros/src/parse_children.rs27
3 files changed, 139 insertions, 55 deletions
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index 6c47de4..d86e35a 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -168,7 +168,7 @@ impl Parsers {
fn double_quote_literal<E: Clone>(
input: ParseInput,
) -> ParseResult<ParsedText<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[double_quote_chunk(chunks)..] => {
chunks.collect()
}
@@ -178,7 +178,7 @@ impl Parsers {
fn double_quote_chunk<E: Clone>(
input: ParseInput,
) -> ParseResult<ParsedTextContents<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(e)] => {
InterpolatedTextContents::Expr(e)
},
@@ -265,7 +265,7 @@ impl Parsers {
fn single_quote_literal<E: Clone>(
input: ParseInput,
) -> ParseResult<ParsedText<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[single_quote_continue(lines)] => {
let newline: ParsedText<E> = "\n".to_string().into();
@@ -308,7 +308,7 @@ impl Parsers {
fn single_quote_continue<E: Clone>(
input: ParseInput,
) -> ParseResult<Vec<Vec<ParsedTextContents<E>>>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(e), single_quote_continue(lines)] => {
let c = InterpolatedTextContents::Expr(e);
let mut lines = lines;
@@ -393,7 +393,7 @@ impl Parsers {
#[alias(expression, shortcut = true)]
fn identifier<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[variable(v)] => {
spanned(input, Var(v))
},
@@ -402,7 +402,7 @@ impl Parsers {
}
fn variable(input: ParseInput) -> ParseResult<V<Label>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(l), natural_literal(idx)] => {
V(l, idx)
},
@@ -444,7 +444,7 @@ impl Parsers {
.collect())
}
fn path(input: ParseInput) -> ParseResult<Vec<String>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[path_component(components)..] => {
components.collect()
}
@@ -455,7 +455,7 @@ impl Parsers {
fn local<E: Clone>(
input: ParseInput,
) -> ParseResult<ImportLocation<Expr<E>>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[local_path((prefix, p))] => ImportLocation::Local(prefix, p),
))
}
@@ -464,19 +464,19 @@ impl Parsers {
fn parent_path(
input: ParseInput,
) -> ParseResult<(FilePrefix, Vec<String>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[path(p)] => (FilePrefix::Parent, p)
))
}
#[alias(local_path)]
fn here_path(input: ParseInput) -> ParseResult<(FilePrefix, Vec<String>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[path(p)] => (FilePrefix::Here, p)
))
}
#[alias(local_path)]
fn home_path(input: ParseInput) -> ParseResult<(FilePrefix, Vec<String>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[path(p)] => (FilePrefix::Home, p)
))
}
@@ -484,7 +484,7 @@ impl Parsers {
fn absolute_path(
input: ParseInput,
) -> ParseResult<(FilePrefix, Vec<String>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[path(p)] => (FilePrefix::Absolute, p)
))
}
@@ -498,7 +498,7 @@ impl Parsers {
}
fn http_raw<E: Clone>(input: ParseInput) -> ParseResult<URL<Expr<E>>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[scheme(sch), authority(auth), path(p)] => URL {
scheme: sch,
authority: auth,
@@ -528,7 +528,7 @@ impl Parsers {
fn http<E: Clone>(
input: ParseInput,
) -> ParseResult<ImportLocation<Expr<E>>> {
- Ok(ImportLocation::Remote(parse_children!(input;
+ Ok(ImportLocation::Remote(parse_children!(input.children();
[http_raw(url)] => url,
[http_raw(url), expression(e)] => URL { headers: Some(e), ..url },
)))
@@ -538,7 +538,7 @@ impl Parsers {
fn env<E: Clone>(
input: ParseInput,
) -> ParseResult<ImportLocation<Expr<E>>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[environment_variable(v)] => ImportLocation::Env(v),
))
}
@@ -548,7 +548,7 @@ impl Parsers {
}
#[alias(environment_variable)]
fn posix_environment_variable(input: ParseInput) -> ParseResult<String> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[posix_environment_variable_character(chars)..] => {
chars.collect()
},
@@ -593,7 +593,7 @@ impl Parsers {
) -> ParseResult<crate::Import<Expr<E>>> {
use crate::Import;
let mode = ImportMode::Code;
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[import_type(location)] => Import { mode, location, hash: None },
[import_type(location), hash(h)] => Import { mode, location, hash: Some(h) },
))
@@ -611,7 +611,7 @@ impl Parsers {
#[alias(expression)]
fn import<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
use crate::Import;
- let import = parse_children!(input;
+ let import = parse_children!(input.children();
[import_hashed(imp)] => {
Import { mode: ImportMode::Code, ..imp }
},
@@ -646,13 +646,13 @@ impl Parsers {
#[alias(expression)]
fn empty_list_literal<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(e)] => spanned(input, EmptyListLit(e)),
))
}
fn expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[lambda(()), label(l), expression(typ),
arrow(()), expression(body)] => {
spanned(input, Lam(l, typ, body))
@@ -699,7 +699,7 @@ impl Parsers {
fn let_binding<E: Clone>(
input: ParseInput,
) -> ParseResult<(Label, Option<Expr<E>>, Expr<E>, Span)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(name), expression(annot), expression(expr)] =>
(name, Some(annot), expr, input_to_span(input)),
[label(name), expression(expr)] =>
@@ -749,7 +749,7 @@ impl Parsers {
fn application_expression<E: Clone>(
input: ParseInput,
) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(e)] => e,
[expression(first), expression(rest)..] => {
rest.fold(
@@ -770,7 +770,7 @@ impl Parsers {
fn first_application_expression<E: Clone>(
input: ParseInput,
) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[Some_(()), expression(e)] => {
spanned(input, SomeLit(e))
},
@@ -788,7 +788,7 @@ impl Parsers {
fn selector_expression<E: Clone>(
input: ParseInput,
) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(e)] => e,
[expression(first), selector(rest)..] => {
rest.fold(
@@ -811,7 +811,7 @@ impl Parsers {
fn selector(
input: ParseInput,
) -> ParseResult<(Either<Label, DupTreeSet<Label>>, Span)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(l)] => (Either::Left(l), input_to_span(input)),
[labels(ls)] => (Either::Right(ls), input_to_span(input)),
// [expression(_e)] => unimplemented!("selection by expression"), // TODO
@@ -819,7 +819,7 @@ impl Parsers {
}
fn labels(input: ParseInput) -> ParseResult<DupTreeSet<Label>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(ls)..] => ls.collect(),
))
}
@@ -828,7 +828,7 @@ impl Parsers {
fn primitive_expression<E: Clone>(
input: ParseInput,
) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[double_literal(n)] => spanned(input, DoubleLit(n)),
[natural_literal(n)] => spanned(input, NaturalLit(n)),
[integer_literal(n)] => spanned(input, IntegerLit(n)),
@@ -854,7 +854,7 @@ impl Parsers {
fn non_empty_record_type_or_literal<E: Clone>(
input: ParseInput,
) -> ParseResult<Expr<E>> {
- let e = parse_children!(input;
+ let e = parse_children!(input.children();
[label(first_label), non_empty_record_type(rest)] => {
let (first_expr, mut map) = rest;
map.insert(first_label, first_expr);
@@ -872,7 +872,7 @@ impl Parsers {
fn non_empty_record_type<E: Clone>(
input: ParseInput,
) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(expr), record_type_entry(entries)..] => {
(expr, entries.collect())
}
@@ -882,7 +882,7 @@ impl Parsers {
fn record_type_entry<E: Clone>(
input: ParseInput,
) -> ParseResult<(Label, Expr<E>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(name), expression(expr)] => (name, expr)
))
}
@@ -890,7 +890,7 @@ impl Parsers {
fn non_empty_record_literal<E: Clone>(
input: ParseInput,
) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(expr), record_literal_entry(entries)..] => {
(expr, entries.collect())
}
@@ -900,14 +900,14 @@ impl Parsers {
fn record_literal_entry<E: Clone>(
input: ParseInput,
) -> ParseResult<(Label, Expr<E>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(name), expression(expr)] => (name, expr)
))
}
#[alias(expression)]
fn union_type<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
- let map = parse_children!(input;
+ let map = parse_children!(input.children();
[empty_union_type(_)] => Default::default(),
[union_type_entry(entries)..] => entries.collect(),
);
@@ -921,7 +921,7 @@ impl Parsers {
fn union_type_entry<E: Clone>(
input: ParseInput,
) -> ParseResult<(Label, Option<Expr<E>>)> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[label(name), expression(expr)] => (name, Some(expr)),
[label(name)] => (name, None),
))
@@ -931,7 +931,7 @@ impl Parsers {
fn non_empty_list_literal<E: Clone>(
input: ParseInput,
) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(items)..] => spanned(
input,
NEListLit(items.collect())
@@ -940,7 +940,7 @@ impl Parsers {
}
fn final_expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
+ Ok(parse_children!(input.children();
[expression(e), EOI(_)] => e
))
}
diff --git a/pest_consume/src/lib.rs b/pest_consume/src/lib.rs
index 6e4b2e3..70aee56 100644
--- a/pest_consume/src/lib.rs
+++ b/pest_consume/src/lib.rs
@@ -5,7 +5,7 @@ use pest::Span;
pub use pest_consume_macros::{make_parser, parse_children};
/// Carries a pest Pair alongside custom user data.
-#[derive(Debug, Clone)]
+#[derive(Debug)]
pub struct ParseInput<'input, 'data, Rule, Data>
where
Rule: pest::RuleType,
@@ -14,6 +14,16 @@ where
user_data: &'data Data,
}
+/// Iterator over `ParseInput`s. It is created by `ParseInput::children`.
+#[derive(Debug)]
+pub struct ParseInputs<'input, 'data, Rule, Data>
+where
+ Rule: pest::RuleType,
+{
+ input: ParseInput<'input, 'data, Rule, Data>,
+ pairs: pest::iterators::Pairs<'input, Rule>,
+}
+
impl<'input, 'data, Rule, Data> ParseInput<'input, 'data, Rule, Data>
where
Rule: pest::RuleType,
@@ -50,6 +60,15 @@ where
}
None
}
+ /// Return an iterator over the children of this input
+ // Can't use `-> impl Iterator` because of weird lifetime limitations
+ // (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(),
+ }
+ }
pub fn user_data(&self) -> &'data Data {
self.user_data
@@ -66,6 +85,28 @@ where
pub fn as_rule(&self) -> Rule {
self.pair.as_rule()
}
+ pub fn as_rule_alias<T>(&self) -> String
+ where
+ T: PestConsumer<Rule = Rule>,
+ {
+ T::rule_alias(self.as_rule())
+ }
+}
+
+impl<'input, 'data, Rule, Data> ParseInputs<'input, 'data, Rule, Data>
+where
+ Rule: pest::RuleType,
+{
+ /// Create an error that points to the span of the input.
+ pub fn error(&self, message: String) -> Error<Rule> {
+ self.input.error(message)
+ }
+ pub fn aliased_rules<T>(&self) -> Vec<String>
+ where
+ T: PestConsumer<Rule = Rule>,
+ {
+ self.clone().map(|p| p.as_rule_alias::<T>()).collect()
+ }
}
/// Used by the macros.
@@ -121,3 +162,55 @@ fn debug_pair<Rule: pest::RuleType>(pair: Pair<Rule>) -> String {
aux(&mut s, 0, "".into(), pair);
s
}
+
+impl<'input, 'data, Rule, Data> Iterator
+ for ParseInputs<'input, 'data, Rule, Data>
+where
+ Rule: pest::RuleType,
+{
+ type Item = ParseInput<'input, 'data, Rule, Data>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let child_pair = self.pairs.next()?;
+ let child = self.input.with_pair(child_pair);
+ Some(child)
+ }
+}
+
+impl<'input, 'data, Rule, Data> DoubleEndedIterator
+ for ParseInputs<'input, 'data, Rule, Data>
+where
+ Rule: pest::RuleType,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ let child_pair = self.pairs.next_back()?;
+ let child = self.input.with_pair(child_pair);
+ Some(child)
+ }
+}
+
+// Manual impl to avoid stupid `Data: Clone` trait bound
+impl<'input, 'data, Rule, Data> Clone for ParseInput<'input, 'data, Rule, Data>
+where
+ Rule: pest::RuleType,
+{
+ fn clone(&self) -> Self {
+ ParseInput {
+ pair: self.pair.clone(),
+ user_data: self.user_data,
+ }
+ }
+}
+
+// Manual impl to avoid stupid `Data: Clone` trait bound
+impl<'input, 'data, Rule, Data> Clone for ParseInputs<'input, 'data, Rule, Data>
+where
+ Rule: pest::RuleType,
+{
+ fn clone(&self) -> Self {
+ ParseInputs {
+ input: self.input.clone(),
+ pairs: self.pairs.clone(),
+ }
+ }
+}
diff --git a/pest_consume_macros/src/parse_children.rs b/pest_consume_macros/src/parse_children.rs
index d6474a7..8feef03 100644
--- a/pest_consume_macros/src/parse_children.rs
+++ b/pest_consume_macros/src/parse_children.rs
@@ -175,7 +175,7 @@ pub fn parse_children(
) -> Result<proc_macro2::TokenStream> {
let input: ParseChildrenInput = syn::parse(input)?;
- let i_children_rules = Ident::new("___children_rules", Span::call_site());
+ let i_input_rules = Ident::new("___input_rules", Span::call_site());
let i_inputs = Ident::new("___inputs", Span::call_site());
let input_expr = &input.input_expr;
@@ -186,29 +186,20 @@ pub fn parse_children(
.collect::<Result<Vec<_>>>()?;
Ok(quote!({
- let #i_children_rules: Vec<_> = #input_expr.as_pair()
- .clone()
- .into_inner()
- .map(|p| p.as_rule())
- .map(<Self as pest_consume::PestConsumer>::rule_alias)
- .collect();
- let #i_children_rules: Vec<&str> = #i_children_rules
+ #[allow(unused_mut)]
+ let mut #i_inputs = #input_expr;
+
+ let #i_input_rules = #i_inputs.aliased_rules::<Self>();
+ let #i_input_rules: Vec<&str> = #i_input_rules
.iter()
.map(String::as_str)
.collect();
- #[allow(unused_mut)]
- let mut #i_inputs = #input_expr
- .as_pair()
- .clone()
- .into_inner()
- .map(|p| #input_expr.with_pair(p));
-
#[allow(unreachable_code)]
- match #i_children_rules.as_slice() {
+ match #i_input_rules.as_slice() {
#(#branches,)*
- [..] => return Err(#input_expr.error(
- format!("Unexpected children: {:?}", #i_children_rules)
+ [..] => return Err(#i_inputs.error(
+ format!("Unexpected children: {:?}", #i_input_rules)
)),
}
}))