diff options
author | Nadrieril | 2019-09-10 14:51:37 +0200 |
---|---|---|
committer | Nadrieril | 2019-09-10 14:51:37 +0200 |
commit | 9f41dc5a4680cba3697c64da28855c8d4f437191 (patch) | |
tree | e190bdf29be0a6cf094b8789d0567a12c43ba5b2 | |
parent | 97f163475294a12f485a6c398df648ad0eeeca8c (diff) |
Implement parsing in PestConsumer
-rw-r--r-- | dhall_syntax/src/parser.rs | 14 | ||||
-rw-r--r-- | pest_consume/src/lib.rs | 23 | ||||
-rw-r--r-- | pest_consume_macros/src/make_parser.rs | 19 |
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)* |