summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2019-09-10 14:51:37 +0200
committerNadrieril2019-09-10 14:51:37 +0200
commit9f41dc5a4680cba3697c64da28855c8d4f437191 (patch)
treee190bdf29be0a6cf094b8789d0567a12c43ba5b2
parent97f163475294a12f485a6c398df648ad0eeeca8c (diff)
Implement parsing in PestConsumer
-rw-r--r--dhall_syntax/src/parser.rs14
-rw-r--r--pest_consume/src/lib.rs23
-rw-r--r--pest_consume_macros/src/make_parser.rs19
3 files changed, 48 insertions, 8 deletions
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index a83b8d0..a783f77 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -2,11 +2,10 @@ use itertools::Itertools;
use pest::iterators::Pair;
use pest::prec_climber as pcl;
use pest::prec_climber::PrecClimber;
-use pest::Parser;
use std::rc::Rc;
use dhall_generated_parser::{DhallParser, Rule};
-use pest_consume::{make_parser, match_inputs};
+use pest_consume::{make_parser, match_inputs, PestConsumer};
use crate::map::{DupTreeMap, DupTreeSet};
use crate::ExprF::*;
@@ -21,8 +20,6 @@ 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,13 +149,16 @@ lazy_static::lazy_static! {
struct Parsers;
-#[make_parser(Rule)]
+#[make_parser(DhallParser, Rule)]
impl Parsers {
#[entrypoint]
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);
+ let inputs = Self::parse_with_userdata(
+ Rule::final_expression,
+ input_str,
+ &rc_input_str,
+ )?;
Ok(match_inputs!(inputs;
[expression(e)] => e,
))
diff --git a/pest_consume/src/lib.rs b/pest_consume/src/lib.rs
index 8f882a9..1579f81 100644
--- a/pest_consume/src/lib.rs
+++ b/pest_consume/src/lib.rs
@@ -1,9 +1,12 @@
use pest::error::{Error, ErrorVariant};
use pest::iterators::{Pair, Pairs};
+use pest::Parser as PestParser;
use pest::{RuleType, Span};
pub use pest_consume_macros::{make_parser, match_inputs};
+static UNIT: () = ();
+
/// Carries a pest Pair alongside custom user data.
#[derive(Debug)]
pub struct ParseInput<'input, 'data, Rule: RuleType, Data> {
@@ -76,6 +79,7 @@ impl<'i, 'd, R: RuleType, D> ParseInput<'i, 'd, R, D> {
pub fn as_rule_alias<C>(&self) -> String
where
C: PestConsumer<Rule = R>,
+ <C as PestConsumer>::Parser: PestParser<R>,
{
C::rule_alias(self.as_rule())
}
@@ -101,6 +105,7 @@ impl<'i, 'd, R: RuleType, D> ParseInputs<'i, 'd, R, D> {
pub fn aliased_rules<C>(&self) -> Vec<String>
where
C: PestConsumer<Rule = R>,
+ <C as PestConsumer>::Parser: PestParser<R>,
{
self.clone().map(|p| p.as_rule_alias::<C>()).collect()
}
@@ -113,8 +118,26 @@ impl<'i, 'd, R: RuleType, D> ParseInputs<'i, 'd, R, D> {
/// Used by the macros.
pub trait PestConsumer {
type Rule: RuleType;
+ type Parser: PestParser<Self::Rule>;
fn rule_alias(rule: Self::Rule) -> String;
fn allows_shortcut(rule: Self::Rule) -> bool;
+
+ fn parse_with_userdata<'i, 'd, D>(
+ rule: Self::Rule,
+ input_str: &'i str,
+ user_data: &'d D,
+ ) -> Result<ParseInputs<'i, 'd, Self::Rule, D>, Error<Self::Rule>> {
+ let pairs = Self::Parser::parse(rule, input_str)?;
+ Ok(ParseInputs::new(input_str, pairs, user_data))
+ }
+
+ fn parse<'i>(
+ rule: Self::Rule,
+ input_str: &'i str,
+ ) -> Result<ParseInputs<'i, 'static, Self::Rule, ()>, Error<Self::Rule>>
+ {
+ Self::parse_with_userdata(rule, input_str, &UNIT)
+ }
}
impl<'i, 'd, R: RuleType, D> Iterator for ParseInputs<'i, 'd, R, D> {
diff --git a/pest_consume_macros/src/make_parser.rs b/pest_consume_macros/src/make_parser.rs
index 9de2f6f..0638c19 100644
--- a/pest_consume_macros/src/make_parser.rs
+++ b/pest_consume_macros/src/make_parser.rs
@@ -13,6 +13,11 @@ mod kw {
syn::custom_keyword!(shortcut);
}
+struct MakeParserAttrs {
+ parser: Ident,
+ rule_enum: Ident,
+}
+
struct AliasArgs {
target: Ident,
is_shortcut: bool,
@@ -39,6 +44,15 @@ struct ParsedFn<'a> {
alias_srcs: Vec<AliasSrc>,
}
+impl Parse for MakeParserAttrs {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let parser = input.parse()?;
+ let _: Token![,] = input.parse()?;
+ let rule_enum = input.parse()?;
+ Ok(MakeParserAttrs { parser, rule_enum })
+ }
+}
+
impl Parse for AliasArgs {
fn parse(input: ParseStream) -> Result<Self> {
let target = input.parse()?;
@@ -244,7 +258,9 @@ pub fn make_parser(
attrs: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> Result<proc_macro2::TokenStream> {
- let rule_enum: Ident = syn::parse(attrs)?;
+ let attrs: MakeParserAttrs = syn::parse(attrs)?;
+ let parser = &attrs.parser;
+ let rule_enum = &attrs.rule_enum;
let mut imp: ItemImpl = syn::parse(input)?;
let mut alias_map = collect_aliases(&mut imp)?;
@@ -322,6 +338,7 @@ pub fn make_parser(
Ok(quote!(
impl #impl_generics pest_consume::PestConsumer for #ty #where_clause {
type Rule = #rule_enum;
+ type Parser = #parser;
fn rule_alias(rule: Self::Rule) -> String {
match rule {
#(#rule_alias_branches)*