From 3c44943a108c9a1aa6378d398b8b1ed4f0bb9fbb Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 17:36:10 +0800 Subject: [PATCH 01/15] Update NeverFailedTypedNode --- pest/src/typed/template/mod.rs | 10 +++++++++- pest/src/typed/template/repetition.rs | 2 +- pest/src/typed/traits.rs | 12 +++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/pest/src/typed/template/mod.rs b/pest/src/typed/template/mod.rs index afa5246..e460d5f 100644 --- a/pest/src/typed/template/mod.rs +++ b/pest/src/typed/template/mod.rs @@ -12,7 +12,7 @@ use super::{ tracker::Tracker, traits::{EmptyPairContainer, PairContainer}, wrapper::String as StringWrapper, - RuleType, TypedNode, + NeverFailedTypedNode, RuleType, TypedNode, }; use crate::{Position, Span, Stack}; use core::{ @@ -412,6 +412,14 @@ impl<'i, R: RuleType> TypedNode<'i, R> for Empty { Some((input, Self)) } } +impl<'i, R: RuleType> NeverFailedTypedNode<'i, R> for Empty { + fn parse_with_partial( + input: Position<'i>, + _stack: &mut Stack>, + ) -> (Position<'i>, Self) { + (input, Self) + } +} impl EmptyPairContainer for Empty {} /// Match the start of input. diff --git a/pest/src/typed/template/repetition.rs b/pest/src/typed/template/repetition.rs index 15a209b..23f6828 100644 --- a/pest/src/typed/template/repetition.rs +++ b/pest/src/typed/template/repetition.rs @@ -37,7 +37,7 @@ impl< > NeverFailedTypedNode<'i, R> for RepMinMax { #[inline] - fn parse_with(mut input: Position<'i>, stack: &mut Stack>) -> (Position<'i>, Self) { + fn parse_with_partial(mut input: Position<'i>, stack: &mut Stack>) -> (Position<'i>, Self) { let mut vec = Vec::new(); let mut tracker = Tracker::new(input); diff --git a/pest/src/typed/traits.rs b/pest/src/typed/traits.rs index 5797de4..b1d81ae 100644 --- a/pest/src/typed/traits.rs +++ b/pest/src/typed/traits.rs @@ -167,7 +167,13 @@ pub trait NeverFailedTypedNode<'i, R: RuleType> where Self: Sized + Debug + Clone + PartialEq + Default, { - /// Create typed node. - /// `ATOMIC` refers to the external status, and it can be overriden by rule definition. - fn parse_with(input: Position<'i>, stack: &mut Stack>) -> (Position<'i>, Self); + /// Parse leading part of given input into a typed node. + fn parse_with_partial(input: Position<'i>, stack: &mut Stack>) + -> (Position<'i>, Self); + /// Parse leading part of given input into a typed node. + fn parse_partial(input: &'i str) -> (Position<'i>, Self) { + let input = Position::from_start(input); + let mut stack = Stack::new(); + Self::parse_with_partial(input, &mut stack) + } } From 235fe044990f5b0ca71cea218e40bf1bdbea0e6f Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 17:40:25 +0800 Subject: [PATCH 02/15] Add doc comments. --- generator/tests/syntax.pest | 2 ++ meta/tests/pest3sample.pest | 7 +++++++ pest/src/choice.rs | 15 ++++++++++++++- pest/src/formatter.rs | 3 +++ pest/src/lib.rs | 3 +++ pest/src/sequence.rs | 10 ++++++++++ pest/src/typed/mod.rs | 2 ++ pest/src/typed/traits.rs | 12 ++++++++++++ pest/src/typed/wrapper.rs | 8 ++++++++ 9 files changed, 61 insertions(+), 1 deletion(-) diff --git a/generator/tests/syntax.pest b/generator/tests/syntax.pest index d081471..253d29f 100644 --- a/generator/tests/syntax.pest +++ b/generator/tests/syntax.pest @@ -1,3 +1,5 @@ +//! For compatibility. + /// Regular rule. Regular = ('0'..'9')+ diff --git a/meta/tests/pest3sample.pest b/meta/tests/pest3sample.pest index 87c541e..b0c0a33 100644 --- a/meta/tests/pest3sample.pest +++ b/meta/tests/pest3sample.pest @@ -1,3 +1,4 @@ +//! This is a grammar test written by [Tomas Tauber](https://github.com/tomtau). string = "abc" insensitive = i"abc" range = '0'..'9' @@ -79,7 +80,13 @@ emoji() = pest::unicode::emoji+ whitespace = " " comment = "$"+ +/// Rule `~` has almost the same behaviour with `^`, +/// except where they are used. +/// For example, +/// `a ~ b` and `a~*` uses rule `~`, +/// while `a ^ b` and `a^*` uses rule `^`. ~ = (whitespace | comment)* +/// See rule `~`. ^ = (whitespace | comment)* // Line comment diff --git a/pest/src/choice.rs b/pest/src/choice.rs index 1d7ab53..fd83c54 100644 --- a/pest/src/choice.rs +++ b/pest/src/choice.rs @@ -1,11 +1,24 @@ +//! A [macro](crate::choice_type) to generate choice type +//! and generated choice types that has 2 to 15 variants. + // TODO: peek to decide matched choice when possible. +/// Generate choice type. +/// +/// ## Example +/// +/// ```rust +/// pest::choice_type!(Choice2, (Variant0, T0), (Variant1, T1)); +/// ``` #[macro_export] macro_rules! choice_type { ( $name:ident, $( ( $variant:ident, $type:ident ) ),* $(,)? ) => { /// Choice type generated by `pest::choice_type!`. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum $name<$( $type ),*> { - $( $variant($type) ),* + $( + #[doc = ::core::stringify!(A choice for $type.)] + $variant($type) + ),* } impl<'i, R, $($type, )*> $crate::typed::TypedNode<'i, R> for $name<$($type, )*> diff --git a/pest/src/formatter.rs b/pest/src/formatter.rs index b164312..ac97959 100644 --- a/pest/src/formatter.rs +++ b/pest/src/formatter.rs @@ -112,8 +112,11 @@ impl<'i> Partition<'i> { /// Formatter options for [Span](crate::Span). pub struct FormatOption { + /// Formatter for characters in span. pub span_formatter: SpanFormatter, + /// Formatter for position marker. pub marker_formatter: MarkerFormatter, + /// Formatter for line numbers and column numbers of start and end. pub number_formatter: NumberFormatter, } diff --git a/pest/src/lib.rs b/pest/src/lib.rs index f743ae8..7879711 100644 --- a/pest/src/lib.rs +++ b/pest/src/lib.rs @@ -1,3 +1,5 @@ +//! Core part of pest3. + // #![no_std] #![warn(rust_2018_idioms, rust_2021_compatibility, missing_docs)] @@ -15,6 +17,7 @@ pub use pest2::{error, RuleType, Stack}; pub use position::Position; pub use span::Span; +/// Re-exported items from [std]. pub mod std { pub use std::boxed::Box; pub use std::ops::FnMut; diff --git a/pest/src/sequence.rs b/pest/src/sequence.rs index 950b31a..5c45f32 100644 --- a/pest/src/sequence.rs +++ b/pest/src/sequence.rs @@ -1,3 +1,13 @@ +//! A [macro](crate::sequence_type) to generate sequence type +//! and generated sequence types that has 2 to 15 fields. + +/// Generate choice type. +/// +/// ## Example +/// +/// ```rust +/// pest::sequence_type!(Sequence2, (element_0, T0, TRIVIA_0), (element_1, T1, TRIVIA_1)); +/// ``` #[macro_export] macro_rules! sequence_type { ( $name:ident, $( ( $variant:ident, $type:ident, $trivia:ident ) ),* $(,)? ) => { diff --git a/pest/src/typed/mod.rs b/pest/src/typed/mod.rs index 190ad98..5e6175e 100644 --- a/pest/src/typed/mod.rs +++ b/pest/src/typed/mod.rs @@ -1,3 +1,5 @@ +//! Definitions related to typed syntax tree. + pub mod template; mod tracker; mod traits; diff --git a/pest/src/typed/traits.rs b/pest/src/typed/traits.rs index b1d81ae..d9f18b9 100644 --- a/pest/src/typed/traits.rs +++ b/pest/src/typed/traits.rs @@ -72,11 +72,15 @@ pub trait TypedNode<'i, R: RuleType>: Sized { // const FIRST: &'static [char]; } +/// A container of pairs. pub trait PairContainer { + /// for `Self` as a pair if it is, otherwise for each child pair. fn for_self_or_for_each_child_pair(&self, f: &mut impl FnMut(Pair)) { self.for_each_child_pair(f) } + /// For each child pair. fn for_each_child_pair(&self, f: &mut impl FnMut(Pair)); + /// Convert children pairs into a [Vec]. fn vec_children_pairs(&self) -> Vec> { let mut vec = vec![]; self.for_each_child_pair(&mut |token| vec.push(token)); @@ -98,8 +102,11 @@ impl PairContainer for T { fn for_each_child_pair(&self, _f: &mut impl FnMut(Pair)) {} } +/// A pair that can be converted to a pair tree. pub trait PairTree: PairContainer + wrapper::Rule { + /// Get pair span. fn get_span(&self) -> (usize, usize); + /// Convert `Self` to a pair tree. fn as_pair_tree(&self) -> Pair { let rule = Self::RULE; let (start, end) = self.get_span(); @@ -133,7 +140,9 @@ impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Option { } } +/// Parser that can produce typed syntax tree. pub trait TypedParser { + /// See [TypedNode::try_parse_with]. #[inline] fn try_parse_with<'i, T: TypedNode<'i, R>>( input: Position<'i>, @@ -142,6 +151,7 @@ pub trait TypedParser { ) -> Option { T::try_parse_with(input, stack, tracker) } + /// See [TypedNode::try_parse_with_partial]. #[inline] fn try_parse_with_partial<'i, T: TypedNode<'i, R>>( input: Position<'i>, @@ -150,10 +160,12 @@ pub trait TypedParser { ) -> Option<(Position<'i>, T)> { T::try_parse_with_partial(input, stack, tracker) } + /// See [TypedNode::try_parse]. #[inline] fn try_parse<'i, T: TypedNode<'i, R>>(input: &'i str) -> Result> { T::try_parse(input) } + /// See [TypedNode::try_parse_partial]. #[inline] fn try_parse_partial<'i, T: TypedNode<'i, R>>( input: &'i str, diff --git a/pest/src/typed/wrapper.rs b/pest/src/typed/wrapper.rs index 02af4c7..ff6d7b2 100644 --- a/pest/src/typed/wrapper.rs +++ b/pest/src/typed/wrapper.rs @@ -1,13 +1,21 @@ +//! Wrapper. use pest2::RuleType; /// A wrapper for string constant. pub trait String { + /// String content. const CONTENT: &'static str; + /// Get content. + fn get_const(&self) -> &'static str { + Self::CONTENT + } } /// A wrapper for string constant. pub trait Rule { + /// Should be the type of wrapped rule. type Rule: RuleType; + /// Wrapped rule. const RULE: R; } From 36ecbc21cfd52cb9e0d465bfe35003493d87d389 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 17:41:37 +0800 Subject: [PATCH 03/15] Implement Default for `pest::typed::template::Empty`. --- pest/src/typed/template/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pest/src/typed/template/mod.rs b/pest/src/typed/template/mod.rs index e460d5f..06e987d 100644 --- a/pest/src/typed/template/mod.rs +++ b/pest/src/typed/template/mod.rs @@ -400,7 +400,7 @@ impl<'i, R: RuleType> TypedNode<'i, R> for NONE { impl EmptyPairContainer for NONE {} /// Always accept and consume no input. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)] pub struct Empty; impl<'i, R: RuleType> TypedNode<'i, R> for Empty { #[inline] From 2617d0ebb2655215a797755bf8a88dff6444d8ce Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 17:43:21 +0800 Subject: [PATCH 04/15] Support doc comments. DoccDoc comments will also be added to generated codes. --- generator/src/common.rs | 18 ++--- generator/tests/expected.rs | 4 ++ meta/src/doc.rs | 7 +- meta/src/grammar.pest | 8 ++- meta/src/parser.rs | 127 +++++++++++++++++++++++++++++++++++- 5 files changed, 142 insertions(+), 22 deletions(-) diff --git a/generator/src/common.rs b/generator/src/common.rs index 6c59862..f267318 100644 --- a/generator/src/common.rs +++ b/generator/src/common.rs @@ -42,23 +42,17 @@ pub(crate) fn generate_rule_enum(rules: &[ParseRule], doc_comment: &DocComment) .map(|rule| { let rule_name = format_ident!("r#{}", rule.name); - match doc_comment.line_docs.get(&rule.name) { - Some(doc) => quote! { + let doc = &rule.doc; + quote! { + #( #[doc = #doc] - #rule_name, - }, - None => quote! { - #rule_name, - }, + )* + #rule_name, } }); let grammar_doc = &doc_comment.grammar_doc; - let grammar_doc = if let Some(grammar_doc) = grammar_doc { - quote! {#[doc = #grammar_doc]} - } else { - quote! {} - }; + let grammar_doc = quote! {#(#[doc = #grammar_doc])*}; quote! { #grammar_doc #[allow(dead_code, missing_docs, non_camel_case_types, clippy::upper_case_acronyms)] diff --git a/generator/tests/expected.rs b/generator/tests/expected.rs index 9724ac6..ca6d029 100644 --- a/generator/tests/expected.rs +++ b/generator/tests/expected.rs @@ -1,9 +1,13 @@ +#[doc = "For compatibility."] #[allow(dead_code, missing_docs, non_camel_case_types, clippy::upper_case_acronyms)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum Rule { EOI, + #[doc = "Regular rule."] r#Regular, + #[doc = "Atomic rule."] r#Atomic, + #[doc = "Silent rule."] r#NonAtomic, r#ExactString, r#CharRange, diff --git a/meta/src/doc.rs b/meta/src/doc.rs index fbc4b66..8eea3d2 100644 --- a/meta/src/doc.rs +++ b/meta/src/doc.rs @@ -2,9 +2,6 @@ use std::collections::HashMap; #[derive(Debug, Default)] pub struct DocComment { - pub grammar_doc: Option, - - /// HashMap for store all doc_comments for rules. - /// key is rule name, value is doc_comment. - pub line_docs: HashMap, + /// Document comments for the whole grammar file. + pub grammar_doc: Vec, } diff --git a/meta/src/grammar.pest b/meta/src/grammar.pest index f040516..fc0aa65 100644 --- a/meta/src/grammar.pest +++ b/meta/src/grammar.pest @@ -8,12 +8,13 @@ // modified, or distributed except according to those terms. grammar_rules = _{ - SOI ~ import* ~ grammar_rule ~ (import | grammar_rule)* ~ EOI + SOI ~ grammar_doc* ~ import* ~ grammar_rule ~ (import | grammar_rule)* ~ EOI } import = { "use" ~ path ~ ("as" ~ identifier)? } grammar_rule = { + rule_doc* ~ (identifier | overridable_operator) ~ arguments? ~ assignment_operator ~ silent_modifier? ~ ( @@ -106,4 +107,7 @@ newline = _{ "\n" | "\r\n" } WHITESPACE = _{ " " | "\t" | newline } block_comment = _{ "/*" ~ (block_comment | !"*/" ~ ANY)* ~ "*/" } -COMMENT = _{ block_comment | ("//" ~ (!newline ~ ANY)*) } +COMMENT = _{ block_comment | ("//" ~ !("/" | "!") ~ (!newline ~ ANY)*) ~ &(newline | EOI) } +doc_content = ${ (!newline ~ ANY)* } +rule_doc = ${ "///" ~ " "? ~ doc_content } +grammar_doc = ${ "//!" ~ " "? ~ doc_content } diff --git a/meta/src/parser.rs b/meta/src/parser.rs index 490a6a1..9ef71c1 100644 --- a/meta/src/parser.rs +++ b/meta/src/parser.rs @@ -115,6 +115,7 @@ impl Display for Range { #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct ParseRule { + pub doc: Vec, pub name: String, pub args: Vec, pub span: Span, @@ -330,6 +331,7 @@ fn _parse>( Rule::grammar_rule => { rules.push(parse_rule(pair, root.as_ref().to_path_buf())?); } + Rule::grammar_doc => doc.grammar_doc.push(parse_grammar_doc(pair)?), _ => (), } } @@ -368,6 +370,19 @@ fn parse_rule(rule: Pair, path: PathBuf) -> Result> let mut pairs = rule.into_inner(); + let mut doc = vec![]; + while let Some(pair) = pairs.peek() { + if pair.as_rule() == Rule::rule_doc { + doc.push(parse_rule_doc( + pairs + .next() + .expect("Peek says there is still at least one more pair."), + )?); + } else { + break; + } + } + let name = pairs .next() .expect("expected Rule::identifier") @@ -398,6 +413,7 @@ fn parse_rule(rule: Pair, path: PathBuf) -> Result> let node = parse_node(pairs.next().unwrap(), &span, &pratt_parser)?; Ok(ParseRule { + doc, name, args, span, @@ -459,6 +475,32 @@ fn parse_path( Ok(ParseNode { expr, span }) } +fn parse_grammar_doc(pair: Pair) -> Result> { + let string = &pair.as_str()[3..]; + let string = string.trim(); + let content = Some(string).ok_or(Error::new_from_span( + ErrorVariant::CustomError { + message: "incorrect grammar doc comment".to_string(), + }, + pair.as_span(), + ))?; + + Ok(content.to_string()) +} + +fn parse_rule_doc(pair: Pair) -> Result> { + let string = &pair.as_str()[3..]; + let string = string.trim(); + let content = Some(string).ok_or(Error::new_from_span( + ErrorVariant::CustomError { + message: "incorrect rule doc comment".to_string(), + }, + pair.as_span(), + ))?; + + Ok(content.to_string()) +} + fn parse_string(pair: Pair, span: &Span) -> Result> { let string = pair.as_str(); let content = unescape(&string[1..string.len() - 1]).ok_or(Error::new_from_span( @@ -805,8 +847,13 @@ mod tests { #[test] fn grammar_test() { let input = include_str!("../tests/pest3sample.pest"); - let parsed = parse(input, &Path::new("../tests/pest3sample.pest")); - assert!(parsed.is_ok()) + let parsed = parse_with_doc_comment(input, &Path::new("../tests/pest3sample.pest")); + let (rules, doc_comment) = match parsed { + Ok(parsed) => parsed, + Err(err) => panic!("{err}"), + }; + assert_ne!(rules.len(), 0); + assert_ne!(doc_comment.grammar_doc.len(), 0); } #[test] @@ -1150,7 +1197,8 @@ mod tests { rule: Rule::grammar_rules, positives: vec![ Rule::import, - Rule::grammar_rule + Rule::grammar_rule, + Rule::grammar_doc ], negatives: vec![], pos: 0 @@ -1402,6 +1450,79 @@ mod tests { }; } + #[test] + fn parse_comment() { + let pair = PestParser::parse(Rule::COMMENT, r#"// A test for grammar with doc comments."#) + .unwrap(); + assert_eq!(pair.into_iter().len(), 0); + + PestParser::parse( + Rule::COMMENT, + r#"//! A test for grammar with doc comments."#, + ) + .unwrap_err(); + + PestParser::parse( + Rule::COMMENT, + r#"/// A test for grammar with doc comments."#, + ) + .unwrap_err(); + } + + #[test] + fn parse_grammar_doc_comment() { + let input = r#"//! A test for grammar with doc comments."#; + + let pair = PestParser::parse(Rule::grammar_doc, input) + .unwrap_or_else(|e| panic!("{e}")) + .next() + .unwrap(); + + assert_eq!( + parse_grammar_doc(pair).unwrap(), + "A test for grammar with doc comments.", + ); + + let input = + "//! A test for grammar with doc comments.\n//! Second line should not be included."; + + let pair = PestParser::parse(Rule::grammar_doc, input) + .unwrap_or_else(|e| panic!("{e}")) + .next() + .unwrap(); + + assert_eq!( + parse_grammar_doc(pair).unwrap(), + "A test for grammar with doc comments.", + ); + + let input = r#" +//! A test for grammar with doc comments. +x = " "+ +"#; + PestParser::parse(Rule::grammar_rules, input).unwrap_or_else(|e| panic!("{e}")); + } + + #[test] + fn parse_rule_doc_comment() { + let input = r#"/// A test for rule with doc comments."#; + + let pair = PestParser::parse(Rule::rule_doc, input) + .unwrap_or_else(|e| panic!("{e}")) + .next() + .unwrap(); + + assert_eq!( + parse_rule_doc(pair).unwrap(), + "A test for rule with doc comments.", + ); + + let input = "\ +/// A test for grammar with doc comments. +x = pest::any+"; + PestParser::parse(Rule::grammar_rule, input).unwrap_or_else(|e| panic!("{e}")); + } + #[test] fn parse_string_escaped() { let input = r#""a\nb""#; From ed114451d3879f4cc3040b7f4d71bf15c89f4bf3 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 17:45:09 +0800 Subject: [PATCH 05/15] Add an example from @tomtau See . --- derive/tests/json.pest | 40 ++++++++++++++++++++++++++++++++++++++++ derive/tests/json.rs | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 derive/tests/json.pest create mode 100644 derive/tests/json.rs diff --git a/derive/tests/json.pest b/derive/tests/json.pest new file mode 100644 index 0000000..6d3319b --- /dev/null +++ b/derive/tests/json.pest @@ -0,0 +1,40 @@ +//! A parser for JSON file. +//! +//! And this is a example for JSON parser. +//! +//! Created by [Tomas Tauber](https://github.com/tomtau). +//! Modified by [Boyi Huang](https://github.com/TheVeryDarkness). + +json = pest::SOI ~ value ~ pest::EOI + +/// Matches object, e.g.: `{ "foo": "bar" }` +/// Foobar +object = "{" ~ pair ~ ("," ~ pair)* ~ "}" | "{" ~ "}" +pair = string ~ ":" ~ value + +array = "[" ~ value ~ ("," ~ value)* ~ "]" | "[" ~ "]" + + +////////////////////// +/// Matches value, e.g.: `"foo"`, `42`, `true`, `null`, `[]`, `{}`. +////////////////////// +value = string | number | object | array | bool | null + +string = "\"" - inner - "\"" +inner = (!("\"" | "\\") - pest::any)* - (escape ~ inner)? +escape = "\\" - ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | unicode) +// FIXME: should be under pest::* +ascii_hex_digit = ascii_digit | "A" | "B" | "C" | "D" | "E" | "F" +ascii_digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" +ascii_nonzero_digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" +unicode = "u" - ascii_hex_digit{4} + +number = "-"? - int - ("." ~ ascii_digit+ ~ exp? | exp)? +int = "0" | ascii_nonzero_digit - ascii_digit* +exp = ("E" | "e") - ("+" | "-")? - ascii_digit+ + +bool = "true" | "false" + +null = "null" + +~ = (" " | "\t" | "\r" | "\n")* diff --git a/derive/tests/json.rs b/derive/tests/json.rs new file mode 100644 index 0000000..b37097d --- /dev/null +++ b/derive/tests/json.rs @@ -0,0 +1,39 @@ +//! Created by [Tomas Tauber](https://github.com/tomtau). +//! Modified by [Boyi Huang](https://github.com/TheVeryDarkness). + +/// Grammar rules of a sample JSON parser +#[allow(missing_docs)] +pub mod json { + use pest_derive::Parser; + + /// JSON parser. + #[derive(Parser)] + #[grammar = "tests/json.pest"] + pub struct JsonParser; + +} + +#[cfg(test)] +mod tests { + use pest::typed::{PairContainer, TypedParser}; + + use crate::json; + #[test] + fn json_basic_test() { + let sample1 = "{\"key\": \"value\"}"; + let s1: json::rules::json = json::JsonParser::try_parse(sample1).unwrap(); + let values = s1.vec_children_pairs(); + assert_eq!(&values[0].rule, &json::Rule::value); + let obj = &values[0].children; + assert_eq!(obj[0].rule, json::Rule::object); + let pair = &obj[0].children; + assert_eq!(pair[0].rule, json::Rule::pair); + let key = &pair[0].children; + assert_eq!(key[0].rule, json::Rule::string); + assert_eq!(&sample1[key[0].start..key[0].end], "\"key\""); + let value = &key[1].children; + assert_eq!(value[0].rule, json::Rule::string); + assert_eq!(&sample1[value[0].start..value[0].end], "\"value\""); + } + +} \ No newline at end of file From 1d3a52e099a50929eff0794ce4b29008713c8b31 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 19:50:22 +0800 Subject: [PATCH 06/15] Support wrap fewer types in `std::boxed::Box`. --- generator/src/typed/attr.rs | 4 + generator/src/typed/config.rs | 2 + generator/src/typed/generator.rs | 40 ++++++-- generator/tests/expected.rs | 162 ++++++++++++++++++++----------- 4 files changed, 147 insertions(+), 61 deletions(-) diff --git a/generator/src/typed/attr.rs b/generator/src/typed/attr.rs index a737b32..c4f4048 100644 --- a/generator/src/typed/attr.rs +++ b/generator/src/typed/attr.rs @@ -21,6 +21,10 @@ pub(crate) fn parse_derive(ast: DeriveInput) -> (Ident, Generics, Vec Self { @@ -10,6 +11,7 @@ impl Default for Config { emit_rule_reference: false, do_not_emit_span: false, no_warnings: false, + box_all_rules: false, } } } diff --git a/generator/src/typed/generator.rs b/generator/src/typed/generator.rs index c79a68e..3d5532f 100644 --- a/generator/src/typed/generator.rs +++ b/generator/src/typed/generator.rs @@ -44,9 +44,16 @@ struct RuleInfo<'g> { pub boxed: bool, } impl<'g> RuleInfo<'g> { - fn from(rule: &'g ParseRule) -> Self { + fn new( + rule: &'g ParseRule, + config: Config, + reachability: &BTreeMap<&str, BTreeSet<&str>>, + ) -> Self { let rule_name = rule.name.as_str(); - let boxed = true; + let boxed = match config.box_all_rules { + true => true, + false => !reachability.contains_key(rule_name), + }; let rule_id = format_ident!("r#{}", rule_name); let silent = rule.silent; Self { @@ -173,12 +180,19 @@ fn create_rule<'g>( } }, }; + let content_type = if rule_info.boxed { + quote! {#this::std::Box<#inner_type>} + } else { + inner_type.clone() + }; quote! { #[doc = #doc] #[derive(Clone, Debug, Eq, PartialEq)] pub struct #name<'i> { - content: #this::std::Box<#inner_type>, - span: #this::Span<'i>, + /// Matched structure. + pub content: #content_type, + /// Matched span. + pub span: #this::Span<'i>, } impl<'i> #this::typed::wrapper::Rule<#root::Rule> for #name<'i> { type Rule = #root::Rule; @@ -389,6 +403,7 @@ fn process_expr<'g>( fn process_rule<'g: 'f, 'f>( rule: &'g ParseRule, mod_sys: &ModuleSystem<'g>, + reachability: &BTreeMap<&str, BTreeSet<&str>>, config: Config, res: &mut Output<'g>, ) { @@ -405,7 +420,7 @@ fn process_rule<'g: 'f, 'f>( "~" => res.add_option_trivia(inter.typename), "^" => res.add_mandatory_trivia(inter.typename), _ => { - let rule_info = RuleInfo::from(rule); + let rule_info = RuleInfo::new(rule, config, reachability); res.insert_rule_struct(create_rule( &rule_config, &rule_info, @@ -421,6 +436,7 @@ fn process_rules<'g: 'f, 'f>( mod_sys: &mut ModuleSystem<'g>, config: Config, ) -> Output<'g> { + let reachability = collect_reachability(rules); for rule in rules.iter() { match rule.name.as_str() { "~" | "^" => {} @@ -429,7 +445,7 @@ fn process_rules<'g: 'f, 'f>( } let mut res = Output::new(); for rule in rules.iter() { - process_rule(rule, mod_sys, config, &mut res); + process_rule(rule, mod_sys, &reachability, config, &mut res); } res } @@ -501,6 +517,13 @@ fn collect_used_rules<'s>(rules: &'s [ParseRule]) -> BTreeSet<&'s str> { res } +/// Wrap some nodes in [std::boxed::Box] to avoid infinite size struct, +/// which can break the edges in the reference graph, +/// and then collect reachability. +/// +/// Rules that are not in map keys are wrapped. +/// +/// We won't promise anything on which nodes are boxed. fn collect_reachability(rules: &[ParseRule]) -> BTreeMap<&str, BTreeSet<&str>> { let mut res = BTreeMap::new(); let rule_trivia = rules.iter().find(|rule| rule.name == "~"); @@ -508,7 +531,11 @@ fn collect_reachability(rules: &[ParseRule]) -> BTreeMap<&str, BTreeSet<&str>> { let entry = res.entry(rule.name.as_str()).or_default(); collect_used_rule(rule, rule_trivia, entry); } + // Length of any path is no more than `rules.len()`. for _ in 0..rules.len() { + // Before the `i`-th iteration, + // `res[a]` contains all nodes that can be reached from `a` + // in no more than `i+1` steps. for rule in rules { let rule_ref = rule.name.as_str(); if let Some(cur) = res.remove(&rule_ref) { @@ -528,7 +555,6 @@ fn collect_reachability(rules: &[ParseRule]) -> BTreeMap<&str, BTreeSet<&str>> { } fn generate_typed_pair_from_rule(rules: &[ParseRule], config: Config) -> TokenStream { - let defined_rules: BTreeSet<&str> = rules.iter().map(|rule| rule.name.as_str()).collect(); let mut mod_sys = ModuleSystem::new(); let graph = process_rules(rules, &mut mod_sys, config); graph.collect() diff --git a/generator/tests/expected.rs b/generator/tests/expected.rs index ca6d029..ab62a59 100644 --- a/generator/tests/expected.rs +++ b/generator/tests/expected.rs @@ -116,8 +116,10 @@ pub mod rules { #[doc = "Generated for rule `Regular`. Grammar: `'0'..'9'+`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Regular<'i> { - content: ::pest::std::Box, 0u8>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::RepOnce, 0u8>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Regular<'i> { type Rule = super::Rule; @@ -150,8 +152,10 @@ pub mod rules { #[doc = "Generated for rule `Atomic`. Grammar: `(CharRange+ ~ (\"+\" ~ CharRange+))`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Atomic<'i> { - content: ::pest::std::Box, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Sequence3, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Atomic<'i> { type Rule = super::Rule; @@ -184,8 +188,10 @@ pub mod rules { #[doc = "Generated for rule `NonAtomic`. Grammar: `(\"(\" ^ \")\")`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#NonAtomic<'i> { - content: ::pest::std::Box, 0u8, super::generics::Str, 2u8>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Sequence2, 0u8, super::generics::Str, 2u8>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#NonAtomic<'i> { type Rule = super::Rule; @@ -218,8 +224,10 @@ pub mod rules { #[doc = "Generated for rule `ExactString`. Grammar: `\"r#\"`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#ExactString<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Str, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#ExactString<'i> { type Rule = super::Rule; @@ -252,8 +260,10 @@ pub mod rules { #[doc = "Generated for rule `CharRange`. Grammar: `'0'..'9'`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#CharRange<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::CharRange<'0', '9'>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#CharRange<'i> { type Rule = super::Rule; @@ -286,8 +296,10 @@ pub mod rules { #[doc = "Generated for rule `Any`. Grammar: `pest::any`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Any<'i> { - content: ::pest::std::Box, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::r#any, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Any<'i> { type Rule = super::Rule; @@ -320,8 +332,10 @@ pub mod rules { #[doc = "Generated for rule `Seq`. Grammar: `(\"1\" ~ ('2'..'9' ~ \".\"))`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Seq<'i> { - content: ::pest::std::Box, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Sequence3, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Seq<'i> { type Rule = super::Rule; @@ -354,8 +368,10 @@ pub mod rules { #[doc = "Generated for rule `Choice`. Grammar: `(\"a\" | ((\"b\"+ ~ RepAtLeastOnce) | ((&\"c\" ~ (Choice ~ (Rep ~ Opt))) | (Peek | (PeekLeft | (PeekRight | (PeekLeftRight | (Drop | PeekAll))))))))`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Choice<'i> { - content: ::pest::std::Box, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: ::pest::std::Box, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Choice<'i> { type Rule = super::Rule; @@ -388,8 +404,10 @@ pub mod rules { #[doc = "Generated for rule `Rep`. Grammar: `\"b\"*`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Rep<'i> { - content: ::pest::std::Box, 0u8>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Rep, 0u8>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Rep<'i> { type Rule = super::Rule; @@ -422,8 +440,10 @@ pub mod rules { #[doc = "Generated for rule `RepAtLeastOnce`. Grammar: `'0'..'9'+`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepAtLeastOnce<'i> { - content: ::pest::std::Box, 0u8>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::RepOnce, 0u8>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#RepAtLeastOnce<'i> { type Rule = super::Rule; @@ -456,8 +476,10 @@ pub mod rules { #[doc = "Generated for rule `Opt`. Grammar: `\"?\"?`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Opt<'i> { - content: ::pest::std::Box<::pest::std::Option>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: ::pest::std::Option>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Opt<'i> { type Rule = super::Rule; @@ -490,8 +512,10 @@ pub mod rules { #[doc = "Generated for rule `RepExact`. Grammar: `RepAtLeastOnce[3..3]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepExact<'i> { - content: ::pest::std::Box, 0u8, 3usize, 3usize>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::RepMinMax, 0u8, 3usize, 3usize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#RepExact<'i> { type Rule = super::Rule; @@ -524,8 +548,10 @@ pub mod rules { #[doc = "Generated for rule `RepLeft`. Grammar: `RepExact[1..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepLeft<'i> { - content: ::pest::std::Box, 0u8, 1usize>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::RepMin, 0u8, 1usize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#RepLeft<'i> { type Rule = super::Rule; @@ -558,8 +584,10 @@ pub mod rules { #[doc = "Generated for rule `RepRight`. Grammar: `RepLeft[..2]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepRight<'i> { - content: ::pest::std::Box, 0u8, 2usize>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::RepMax, 0u8, 2usize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#RepRight<'i> { type Rule = super::Rule; @@ -592,8 +620,10 @@ pub mod rules { #[doc = "Generated for rule `RepLeftRight`. Grammar: `RepRight[1..2]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepLeftRight<'i> { - content: ::pest::std::Box, 0u8, 1usize, 2usize>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::RepMinMax, 0u8, 1usize, 2usize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#RepLeftRight<'i> { type Rule = super::Rule; @@ -626,8 +656,10 @@ pub mod rules { #[doc = "Generated for rule `Pos`. Grammar: `&(pest::SOI ~ RepLeftRight[2..4])`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Pos<'i> { - content: ::pest::std::Box, 0u8, 2usize, 4usize>, 1u8>>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Positive, 0u8, 2usize, 4usize>, 1u8>>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Pos<'i> { type Rule = super::Rule; @@ -660,8 +692,10 @@ pub mod rules { #[doc = "Generated for rule `Neg`. Grammar: `!(pest::EOI ~ Pos)`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Neg<'i> { - content: ::pest::std::Box, 1u8>>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::Negative, 1u8>>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Neg<'i> { type Rule = super::Rule; @@ -694,8 +728,10 @@ pub mod rules { #[doc = "Generated for rule `Push`. Grammar: `pest::push((RepLeft* ~ (Neg ~ (ExactString+ ~ (Push ~ (Pop ~ (Push ~ PopAll)))))))`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Push<'i> { - content: ::pest::std::Box, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: ::pest::std::Box, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Push<'i> { type Rule = super::Rule; @@ -728,8 +764,10 @@ pub mod rules { #[doc = "Generated for rule `Pop`. Grammar: `pest::pop`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Pop<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::r#pop<'i>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Pop<'i> { type Rule = super::Rule; @@ -762,8 +800,10 @@ pub mod rules { #[doc = "Generated for rule `PopAll`. Grammar: `pest::pop_all`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PopAll<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::r#pop_all<'i>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#PopAll<'i> { type Rule = super::Rule; @@ -796,8 +836,10 @@ pub mod rules { #[doc = "Generated for rule `Peek`. Grammar: `pest::peek`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Peek<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::r#peek<'i>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Peek<'i> { type Rule = super::Rule; @@ -830,8 +872,10 @@ pub mod rules { #[doc = "Generated for rule `PeekUnlimited`. Grammar: `pest::peek[..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekUnlimited<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::PeekSlice1<0isize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#PeekUnlimited<'i> { type Rule = super::Rule; @@ -864,8 +908,10 @@ pub mod rules { #[doc = "Generated for rule `PeekLeft`. Grammar: `pest::peek[1..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekLeft<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::PeekSlice1<1isize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#PeekLeft<'i> { type Rule = super::Rule; @@ -898,8 +944,10 @@ pub mod rules { #[doc = "Generated for rule `PeekRight`. Grammar: `pest::peek[..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekRight<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::PeekSlice1<0isize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#PeekRight<'i> { type Rule = super::Rule; @@ -932,8 +980,10 @@ pub mod rules { #[doc = "Generated for rule `PeekLeftRight`. Grammar: `pest::peek[1..2]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekLeftRight<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::PeekSlice2<1isize, 2isize>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#PeekLeftRight<'i> { type Rule = super::Rule; @@ -966,8 +1016,10 @@ pub mod rules { #[doc = "Generated for rule `Drop`. Grammar: `pest::drop`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Drop<'i> { - content: ::pest::std::Box, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::r#drop, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#Drop<'i> { type Rule = super::Rule; @@ -1000,8 +1052,10 @@ pub mod rules { #[doc = "Generated for rule `PeekAll`. Grammar: `pest::peek_all`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekAll<'i> { - content: ::pest::std::Box>, - span: ::pest::Span<'i>, + #[doc = r" Matched structure."] + pub content: super::generics::r#peek_all<'i>, + #[doc = r" Matched span."] + pub span: ::pest::Span<'i>, } impl<'i> ::pest::typed::wrapper::Rule for r#PeekAll<'i> { type Rule = super::Rule; From 6e9f022531d6e0b013e9577423c6721a120c0ca3 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 19:53:33 +0800 Subject: [PATCH 07/15] Add functions to sequence types and update doc comments for sequence_type! and choice_type!. --- pest/src/choice.rs | 5 +++-- pest/src/sequence.rs | 31 +++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/pest/src/choice.rs b/pest/src/choice.rs index fd83c54..cfac5c1 100644 --- a/pest/src/choice.rs +++ b/pest/src/choice.rs @@ -1,5 +1,6 @@ //! A [macro](crate::choice_type) to generate choice type -//! and generated choice types that has 2 to 15 variants. +//! and generated choice types that has 2 to 15 variants, +//! which are named `Choice{i}`. // TODO: peek to decide matched choice when possible. /// Generate choice type. @@ -7,7 +8,7 @@ /// ## Example /// /// ```rust -/// pest::choice_type!(Choice2, (Variant0, T0), (Variant1, T1)); +/// pest::choice_type!(Choice2, (Choice0, T0), (Choice1, T1)); /// ``` #[macro_export] macro_rules! choice_type { diff --git a/pest/src/sequence.rs b/pest/src/sequence.rs index 5c45f32..db46a98 100644 --- a/pest/src/sequence.rs +++ b/pest/src/sequence.rs @@ -1,16 +1,17 @@ //! A [macro](crate::sequence_type) to generate sequence type -//! and generated sequence types that has 2 to 15 fields. +//! and generated sequence types that has 2 to 15 fields, +//! which are named `field_{i}`. -/// Generate choice type. +/// Generate sequence type. /// /// ## Example /// /// ```rust -/// pest::sequence_type!(Sequence2, (element_0, T0, TRIVIA_0), (element_1, T1, TRIVIA_1)); +/// pest::sequence_type!(Sequence2, (field_0, T0, TRIVIA_0), (field_1, T1, TRIVIA_1)); /// ``` #[macro_export] macro_rules! sequence_type { - ( $name:ident, $( ( $variant:ident, $type:ident, $trivia:ident ) ),* $(,)? ) => { + ( $name:ident, $( ( $field:ident, $type:ident, $trivia:ident ) ),* $(,)? ) => { /// Sequence type generated by `pest::sequence_type!`. /// /// - `0`: No trivia. @@ -18,7 +19,21 @@ macro_rules! sequence_type { /// - `2`: Mandatory trivia. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct $name<$( $type, const $trivia: ::core::primitive::u8, )*> { - $( $variant: $type ),* + $( + #[doc = ::core::stringify!(Field for $type.)] + pub $field: $type, + )* + } + impl<'i, $($type, const $trivia: ::core::primitive::u8, )*> + $name<$($type, $trivia, )*> { + /// As a tuple of references. + pub fn as_tuple(&self) -> ($(&$type, )*) { + ( $( &self.$field, )* ) + } + /// Into a tuple of values. + pub fn into_tuple(self) -> ($($type, )*) { + ( $( self.$field, )* ) + } } impl<'i, R, $($type, const $trivia: ::core::primitive::u8, )*> $crate::typed::TypedNode<'i, R> for $name<$($type, $trivia, )*> @@ -40,11 +55,11 @@ macro_rules! sequence_type { if i > 1 { input = $crate::typed::template::try_handle_trivia::(input, stack, tracker)?; } - let (next, $variant) = $type::try_parse_with_partial(input, stack, tracker)?; + let (next, $field) = $type::try_parse_with_partial(input, stack, tracker)?; input = next; )* let res = Self { - $($variant, )* + $($field, )* }; ::core::option::Option::Some((input, res)) } @@ -58,7 +73,7 @@ macro_rules! sequence_type { { fn for_each_child_pair(&self, f: &mut impl $crate::std::FnMut($crate::token::Pair)) { $( - self.$variant.for_self_or_for_each_child_pair(f); + self.$field.for_self_or_for_each_child_pair(f); )* } } From 9cfbba919b43b698a0899b3dd5c1e6b69516af9c Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 20 Feb 2024 19:53:54 +0800 Subject: [PATCH 08/15] Update json example. --- derive/tests/json.pest | 6 ++++-- derive/tests/json.rs | 28 +++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/derive/tests/json.pest b/derive/tests/json.pest index 6d3319b..e5c7555 100644 --- a/derive/tests/json.pest +++ b/derive/tests/json.pest @@ -9,7 +9,7 @@ json = pest::SOI ~ value ~ pest::EOI /// Matches object, e.g.: `{ "foo": "bar" }` /// Foobar -object = "{" ~ pair ~ ("," ~ pair)* ~ "}" | "{" ~ "}" +object = "{" ~ pair^* ~ "}" pair = string ~ ":" ~ value array = "[" ~ value ~ ("," ~ value)* ~ "]" | "[" ~ "]" @@ -37,4 +37,6 @@ bool = "true" | "false" null = "null" -~ = (" " | "\t" | "\r" | "\n")* +space = " " | "\t" | "\r" | "\n" +~ = space* +^ = space* - "," - space* diff --git a/derive/tests/json.rs b/derive/tests/json.rs index b37097d..e2c4200 100644 --- a/derive/tests/json.rs +++ b/derive/tests/json.rs @@ -5,19 +5,18 @@ #[allow(missing_docs)] pub mod json { use pest_derive::Parser; - + /// JSON parser. #[derive(Parser)] #[grammar = "tests/json.pest"] pub struct JsonParser; - -} +} #[cfg(test)] mod tests { use pest::typed::{PairContainer, TypedParser}; - use crate::json; + use crate::{json, json::generics::*}; #[test] fn json_basic_test() { let sample1 = "{\"key\": \"value\"}"; @@ -36,4 +35,23 @@ mod tests { assert_eq!(&sample1[value[0].start..value[0].end], "\"value\""); } -} \ No newline at end of file + /// Test in structural style. + #[test] + fn json_structural_test() { + let sample1 = "{\"key\": \"value\"}"; + let s1: json::rules::json = json::JsonParser::try_parse(sample1).unwrap(); + let value: json::rules::value<'_> = s1.content.field_1; + match *value.content { + Choice6::Choice2(object) => { + let (_, mut pairs, _) = object.content.into_tuple(); + assert_eq!(pairs.content.len(), 1); + let pair = pairs.content.pop().unwrap(); + let (key, _, value) = pair.content.into_tuple(); + let (_, key, _) = key.content.into_tuple(); + assert_eq!(key.span.as_str(), "key"); + assert_eq!(value.span.as_str(), "\"value\""); + } + _ => {} + } + } +} From 31bf0f358c31b00113bb3cc8fd29ebf6c9b94147 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Mon, 26 Feb 2024 16:53:06 +0800 Subject: [PATCH 09/15] Support checking inputs without building AST. Also updated tests. --- generator/src/typed/generator.rs | 24 +- generator/src/typed/module.rs | 19 +- generator/tests/expected.rs | 432 +++++++++++--------------- pest/src/choice.rs | 20 ++ pest/src/lib.rs | 45 ++- pest/src/sequence.rs | 17 + pest/src/typed/mod.rs | 5 +- pest/src/typed/template/mod.rs | 273 ++++++++++++++++ pest/src/typed/template/repetition.rs | 33 +- pest/src/typed/tracker.rs | 45 +-- pest/src/typed/traits.rs | 139 +++++++-- pest/src/typed/wrapper.rs | 6 +- pest/tests/predefined_node.rs | 16 +- 13 files changed, 762 insertions(+), 312 deletions(-) diff --git a/generator/src/typed/generator.rs b/generator/src/typed/generator.rs index 3d5532f..7b0a483 100644 --- a/generator/src/typed/generator.rs +++ b/generator/src/typed/generator.rs @@ -194,22 +194,16 @@ fn create_rule<'g>( /// Matched span. pub span: #this::Span<'i>, } - impl<'i> #this::typed::wrapper::Rule<#root::Rule> for #name<'i> { + impl<'i> #this::typed::wrapper::Rule for #name<'i> { type Rule = #root::Rule; const RULE: #root::Rule = #root::Rule::#name; } - impl<'i> #this::typed::TypedNode<'i, #root::Rule> for #name<'i> { - fn try_parse_with_partial( - input: #this::Position<'i>, - stack: &mut #this::Stack<#this::Span<'i>>, - tracker: &mut #this::typed::Tracker<'i, #root::Rule>, - ) -> #this::std::Option<(#this::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = #inner_type::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - #this::std::Some((pos, Self{ content, span })) - }) + impl<'i> #this::typed::FullRuleStruct<'i> for #name<'i> { + type Inner = #inner_type; + type Content = #content_type; + #[inline] + fn new(content: Self::Content, span: #this::Span<'i>) -> Self { + Self { content, span } } } #pair_api @@ -440,7 +434,7 @@ fn process_rules<'g: 'f, 'f>( for rule in rules.iter() { match rule.name.as_str() { "~" | "^" => {} - _ => mod_sys.insert_rule(&rule.name), + _ => mod_sys.insert_rule(rule), } } let mut res = Output::new(); @@ -508,6 +502,7 @@ fn collect_used_rule<'g>( } } +#[cfg(test)] fn collect_used_rules<'s>(rules: &'s [ParseRule]) -> BTreeSet<&'s str> { let mut res = BTreeSet::new(); let rule_trivia = rules.iter().find(|rule| rule.name == "~"); @@ -598,6 +593,7 @@ fn generate_typed( res } +/// Derive typed parser from given grammar, attributes and type. pub fn derive_typed_parser( input: TokenStream, include_grammar: bool, diff --git a/generator/src/typed/module.rs b/generator/src/typed/module.rs index c85c85c..35e5668 100644 --- a/generator/src/typed/module.rs +++ b/generator/src/typed/module.rs @@ -2,6 +2,8 @@ use super::{ generator::{ProcessedPathArgs, RuleRef}, output::generics, }; +use pest::unicode::unicode_property_names; +use pest_meta::parser::ParseRule; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use std::collections::{btree_map::Keys, BTreeMap}; @@ -10,6 +12,7 @@ use std::collections::{btree_map::Keys, BTreeMap}; pub enum RuleGenerics { /// Defined rule in current module. Rule, + Unicode(Ident), BuiltIn { /// Built-in rule that accepts nothing as argument. /// @@ -50,6 +53,9 @@ impl RuleGenerics { let (path, name) = getter(); quote! { #root::rules::#( #path:: )* #name :: <'i> } } + Self::Unicode(ident) => { + quote! { #root::rules::unicode::#ident } + } Self::BuiltIn { direct, slice, @@ -132,7 +138,7 @@ impl<'g> ModuleSystem<'g> { ) }; } - let tree = BTreeMap::from([ + let mut tree = BTreeMap::from([ pest_builtin!(SOI {}), pest_builtin!(EOI {}), pest_builtin!(any {}), @@ -143,9 +149,18 @@ impl<'g> ModuleSystem<'g> { pest_builtin!(pop {'i}), pest_builtin!(pop_all {'i}), ]); + for unicode in unicode_property_names() { + assert!(unicode.is_ascii()); + let ident = format_ident!("{}", unicode.to_ascii_lowercase()); + tree.insert( + vec!["pest", "unicode", unicode], + RuleGenerics::Unicode(ident), + ); + } Self { tree } } - pub fn insert_rule(&mut self, key: &'g str) { + pub fn insert_rule(&mut self, rule: &'g ParseRule) { + let key = &rule.name; let value = RuleGenerics::Rule; self.tree.insert(vec![key], value); } diff --git a/generator/tests/expected.rs b/generator/tests/expected.rs index ab62a59..0f4cadb 100644 --- a/generator/tests/expected.rs +++ b/generator/tests/expected.rs @@ -121,18 +121,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Regular<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Regular<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Regular; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Regular<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::RepOnce::, 0u8>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Regular<'i> { + type Inner = super::generics::RepOnce, 0u8>; + type Content = super::generics::RepOnce, 0u8>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Regular<'i> { @@ -157,18 +155,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Atomic<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Atomic<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Atomic; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Atomic<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Sequence3::, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Atomic<'i> { + type Inner = super::generics::Sequence3, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>; + type Content = super::generics::Sequence3, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Atomic<'i> { @@ -193,18 +189,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#NonAtomic<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#NonAtomic<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#NonAtomic; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#NonAtomic<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Sequence2::, 0u8, super::generics::Str, 2u8>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#NonAtomic<'i> { + type Inner = super::generics::Sequence2, 0u8, super::generics::Str, 2u8>; + type Content = super::generics::Sequence2, 0u8, super::generics::Str, 2u8>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#NonAtomic<'i> { @@ -229,18 +223,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#ExactString<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#ExactString<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#ExactString; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#ExactString<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Str::::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#ExactString<'i> { + type Inner = super::generics::Str; + type Content = super::generics::Str; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#ExactString<'i> { @@ -265,18 +257,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#CharRange<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#CharRange<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#CharRange; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#CharRange<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::CharRange::<'0', '9'>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#CharRange<'i> { + type Inner = super::generics::CharRange<'0', '9'>; + type Content = super::generics::CharRange<'0', '9'>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#CharRange<'i> { @@ -301,18 +291,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Any<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Any<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Any; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Any<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#any::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Any<'i> { + type Inner = super::generics::r#any; + type Content = super::generics::r#any; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Any<'i> { @@ -337,18 +325,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Seq<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Seq<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Seq; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Seq<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Sequence3::, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Seq<'i> { + type Inner = super::generics::Sequence3, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>; + type Content = super::generics::Sequence3, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Seq<'i> { @@ -373,18 +359,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Choice<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Choice<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Choice; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Choice<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Choice9::, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Choice<'i> { + type Inner = super::generics::Choice9, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>; + type Content = ::pest::std::Box, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Choice<'i> { @@ -409,18 +393,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Rep<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Rep<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Rep; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Rep<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Rep::, 0u8>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Rep<'i> { + type Inner = super::generics::Rep, 0u8>; + type Content = super::generics::Rep, 0u8>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Rep<'i> { @@ -445,18 +427,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#RepAtLeastOnce<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#RepAtLeastOnce<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#RepAtLeastOnce; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#RepAtLeastOnce<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::RepOnce::, 0u8>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepAtLeastOnce<'i> { + type Inner = super::generics::RepOnce, 0u8>; + type Content = super::generics::RepOnce, 0u8>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#RepAtLeastOnce<'i> { @@ -481,18 +461,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Opt<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Opt<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Opt; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Opt<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = ::pest::std::Option::>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Opt<'i> { + type Inner = ::pest::std::Option>; + type Content = ::pest::std::Option>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Opt<'i> { @@ -517,18 +495,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#RepExact<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#RepExact<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#RepExact; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#RepExact<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::RepMinMax::, 0u8, 3usize, 3usize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepExact<'i> { + type Inner = super::generics::RepMinMax, 0u8, 3usize, 3usize>; + type Content = super::generics::RepMinMax, 0u8, 3usize, 3usize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#RepExact<'i> { @@ -553,18 +529,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#RepLeft<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#RepLeft<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#RepLeft; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#RepLeft<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::RepMin::, 0u8, 1usize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepLeft<'i> { + type Inner = super::generics::RepMin, 0u8, 1usize>; + type Content = super::generics::RepMin, 0u8, 1usize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#RepLeft<'i> { @@ -589,18 +563,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#RepRight<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#RepRight<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#RepRight; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#RepRight<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::RepMax::, 0u8, 2usize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepRight<'i> { + type Inner = super::generics::RepMax, 0u8, 2usize>; + type Content = super::generics::RepMax, 0u8, 2usize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#RepRight<'i> { @@ -625,18 +597,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#RepLeftRight<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#RepLeftRight<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#RepLeftRight; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#RepLeftRight<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::RepMinMax::, 0u8, 1usize, 2usize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepLeftRight<'i> { + type Inner = super::generics::RepMinMax, 0u8, 1usize, 2usize>; + type Content = super::generics::RepMinMax, 0u8, 1usize, 2usize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#RepLeftRight<'i> { @@ -661,18 +631,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Pos<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Pos<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Pos; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Pos<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Positive::, 0u8, 2usize, 4usize>, 1u8>>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Pos<'i> { + type Inner = super::generics::Positive, 0u8, 2usize, 4usize>, 1u8>>; + type Content = super::generics::Positive, 0u8, 2usize, 4usize>, 1u8>>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Pos<'i> { @@ -697,18 +665,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Neg<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Neg<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Neg; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Neg<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::Negative::, 1u8>>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Neg<'i> { + type Inner = super::generics::Negative, 1u8>>; + type Content = super::generics::Negative, 1u8>>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Neg<'i> { @@ -733,18 +699,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Push<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Push<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Push; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Push<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#push::, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Push<'i> { + type Inner = super::generics::r#push, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>; + type Content = ::pest::std::Box, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Push<'i> { @@ -769,18 +733,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Pop<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Pop<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Pop; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Pop<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#pop::<'i>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Pop<'i> { + type Inner = super::generics::r#pop<'i>; + type Content = super::generics::r#pop<'i>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Pop<'i> { @@ -805,18 +767,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#PopAll<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#PopAll<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#PopAll; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#PopAll<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#pop_all::<'i>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#PopAll<'i> { + type Inner = super::generics::r#pop_all<'i>; + type Content = super::generics::r#pop_all<'i>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#PopAll<'i> { @@ -841,18 +801,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Peek<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Peek<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Peek; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Peek<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#peek::<'i>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Peek<'i> { + type Inner = super::generics::r#peek<'i>; + type Content = super::generics::r#peek<'i>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Peek<'i> { @@ -877,18 +835,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#PeekUnlimited<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#PeekUnlimited<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#PeekUnlimited; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#PeekUnlimited<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::PeekSlice1::<0isize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#PeekUnlimited<'i> { + type Inner = super::generics::PeekSlice1<0isize>; + type Content = super::generics::PeekSlice1<0isize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#PeekUnlimited<'i> { @@ -913,18 +869,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#PeekLeft<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#PeekLeft<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#PeekLeft; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#PeekLeft<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::PeekSlice1::<1isize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#PeekLeft<'i> { + type Inner = super::generics::PeekSlice1<1isize>; + type Content = super::generics::PeekSlice1<1isize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#PeekLeft<'i> { @@ -949,18 +903,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#PeekRight<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#PeekRight<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#PeekRight; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#PeekRight<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::PeekSlice1::<0isize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#PeekRight<'i> { + type Inner = super::generics::PeekSlice1<0isize>; + type Content = super::generics::PeekSlice1<0isize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#PeekRight<'i> { @@ -985,18 +937,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#PeekLeftRight<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#PeekLeftRight<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#PeekLeftRight; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#PeekLeftRight<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::PeekSlice2::<1isize, 2isize>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#PeekLeftRight<'i> { + type Inner = super::generics::PeekSlice2<1isize, 2isize>; + type Content = super::generics::PeekSlice2<1isize, 2isize>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#PeekLeftRight<'i> { @@ -1021,18 +971,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#Drop<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#Drop<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#Drop; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#Drop<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#drop::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Drop<'i> { + type Inner = super::generics::r#drop; + type Content = super::generics::r#drop; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Drop<'i> { @@ -1057,18 +1005,16 @@ pub mod rules { #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } - impl<'i> ::pest::typed::wrapper::Rule for r#PeekAll<'i> { + impl<'i> ::pest::typed::wrapper::Rule for r#PeekAll<'i> { type Rule = super::Rule; const RULE: super::Rule = super::Rule::r#PeekAll; } - impl<'i> ::pest::typed::TypedNode<'i, super::Rule> for r#PeekAll<'i> { - fn try_parse_with_partial(input: ::pest::Position<'i>, stack: &mut ::pest::Stack<::pest::Span<'i>>, tracker: &mut ::pest::typed::Tracker<'i, super::Rule>) -> ::pest::std::Option<(::pest::Position<'i>, Self)> { - tracker.record_option_during(input, |tracker| { - let (pos, content) = super::generics::r#peek_all::<'i>::try_parse_with_partial(input, stack, tracker)?; - let content = content.into(); - let span = input.span(&pos); - ::pest::std::Some((pos, Self { content, span })) - }) + impl<'i> ::pest::typed::FullRuleStruct<'i> for r#PeekAll<'i> { + type Inner = super::generics::r#peek_all<'i>; + type Content = super::generics::r#peek_all<'i>; + #[inline] + fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#PeekAll<'i> { diff --git a/pest/src/choice.rs b/pest/src/choice.rs index cfac5c1..f66727c 100644 --- a/pest/src/choice.rs +++ b/pest/src/choice.rs @@ -50,6 +50,26 @@ macro_rules! choice_type { )* ::core::option::Option::None } + #[inline] + fn check_with_partial( + input: $crate::Position<'i>, + stack: &mut $crate::Stack<$crate::Span<'i>>, + tracker: &mut $crate::typed::Tracker<'i, R>, + ) -> ::core::option::Option<$crate::Position<'i>> { + $( + stack.snapshot(); + match $type::check_with_partial(input, stack, tracker) { + ::core::option::Option::Some(input) => { + stack.clear_snapshot(); + return ::core::option::Option::Some(input) + } + ::core::option::Option::None => { + stack.restore(); + } + } + )* + ::core::option::Option::None + } } impl $crate::typed::PairContainer for $name<$($type, )*> diff --git a/pest/src/lib.rs b/pest/src/lib.rs index 7879711..4670b08 100644 --- a/pest/src/lib.rs +++ b/pest/src/lib.rs @@ -13,7 +13,7 @@ pub mod typed; extern crate alloc; -pub use pest2::{error, RuleType, Stack}; +pub use pest2::{error, unicode, RuleType, Stack}; pub use position::Position; pub use span::Span; @@ -22,6 +22,47 @@ pub mod std { pub use std::boxed::Box; pub use std::ops::FnMut; pub use std::option::{Option, Option::None, Option::Some}; - pub use std::primitive::usize; + pub use std::primitive::{bool, char, usize}; + pub use std::result::{Result, Result::Err, Result::Ok}; pub use std::vec::Vec; } + +/// Generate unicode property type. +#[macro_export] +macro_rules! unicode { + ($property:ident) => { + #[doc = ::core::stringify!(Auto generated. Unicode property $property.)] + #[derive(Clone, Debug, Hash, PartialEq, Eq)] + #[allow(non_camel_case_types)] + pub struct $property { + pub content: $crate::std::char, + } + impl<'i, R: $crate::typed::RuleType> $crate::typed::TypedNode<'i, R> for $property { + #[inline] + fn try_parse_with_partial( + mut input: $crate::Position<'i>, + _stack: &mut $crate::Stack<$crate::Span<'i>>, + tracker: &mut $crate::typed::Tracker<'i, R>, + ) -> $crate::std::Option<($crate::Position<'i>, Self)> { + match $crate::typed::template::match_char_by(&mut input, $crate::unicode::$property) + { + $crate::std::Some(content) => $crate::std::Some((input, Self { content })), + $crate::std::None => $crate::std::None, + } + } + #[inline] + fn check_with_partial( + mut input: $crate::Position<'i>, + _stack: &mut $crate::Stack<$crate::Span<'i>>, + tracker: &mut $crate::typed::Tracker<'i, R>, + ) -> $crate::std::Option<$crate::Position<'i>> { + match $crate::typed::template::match_char_by(&mut input, $crate::unicode::$property) + { + $crate::std::Some(_) => $crate::std::Some(input), + $crate::std::None => $crate::std::None, + } + } + } + impl $crate::typed::EmptyPairContainer for $property {} + }; +} diff --git a/pest/src/sequence.rs b/pest/src/sequence.rs index db46a98..b829f22 100644 --- a/pest/src/sequence.rs +++ b/pest/src/sequence.rs @@ -63,6 +63,23 @@ macro_rules! sequence_type { }; ::core::option::Option::Some((input, res)) } + #[inline] + fn check_with_partial( + mut input: $crate::Position<'i>, + stack: &mut $crate::Stack<$crate::Span<'i>>, + tracker: &mut $crate::typed::Tracker<'i, R>, + ) -> ::core::option::Option<$crate::Position<'i>> { + let mut i = 0usize; + $( + i += 1; + if i > 1 { + input = $crate::typed::template::try_handle_trivia::(input, stack, tracker)?; + } + let next = $type::check_with_partial(input, stack, tracker)?; + input = next; + )* + ::core::option::Option::Some(input) + } } impl $crate::typed::PairContainer for $name<$($type, $trivia, )*> diff --git a/pest/src/typed/mod.rs b/pest/src/typed/mod.rs index 5e6175e..ed7966a 100644 --- a/pest/src/typed/mod.rs +++ b/pest/src/typed/mod.rs @@ -6,4 +6,7 @@ mod traits; pub mod wrapper; pub use tracker::Tracker; -pub use traits::{NeverFailedTypedNode, PairContainer, PairTree, RuleType, TypedNode, TypedParser}; +pub use traits::{ + EmptyPairContainer, FullRuleStruct, NeverFailedTypedNode, PairContainer, PairTree, RuleType, + TypedNode, TypedParser, +}; diff --git a/pest/src/typed/template/mod.rs b/pest/src/typed/template/mod.rs index 06e987d..0ebe008 100644 --- a/pest/src/typed/template/mod.rs +++ b/pest/src/typed/template/mod.rs @@ -38,6 +38,7 @@ impl From<()> for Str { } } impl<'i, R: RuleType, T: StringWrapper> TypedNode<'i, R> for Str { + #[inline] fn try_parse_with_partial( mut input: Position<'i>, _stack: &mut Stack>, @@ -49,6 +50,18 @@ impl<'i, R: RuleType, T: StringWrapper> TypedNode<'i, R> for Str { None } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + if input.match_string(Self::CONTENT) { + Some(input) + } else { + None + } + } } impl Debug for Str { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -83,6 +96,7 @@ impl<'i, T: StringWrapper> From<&'i str> for Insens<'i, T> { } } impl<'i, R: RuleType, T: StringWrapper> TypedNode<'i, R> for Insens<'i, T> { + #[inline] fn try_parse_with_partial( mut input: Position<'i>, _stack: &mut Stack>, @@ -96,6 +110,18 @@ impl<'i, R: RuleType, T: StringWrapper> TypedNode<'i, R> for Insens<'i, T> { None } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + if input.match_insensitive(Self::CONTENT) { + Some(input) + } else { + None + } + } } impl<'i, T: StringWrapper> Debug for Insens<'i, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -114,6 +140,7 @@ pub struct SkipChar<'i, const N: usize> { pub span: Span<'i>, } impl<'i, R: RuleType, const N: usize> TypedNode<'i, R> for SkipChar<'i, N> { + #[inline] fn try_parse_with_partial( mut input: Position<'i>, _stack: &mut Stack>, @@ -128,6 +155,17 @@ impl<'i, R: RuleType, const N: usize> TypedNode<'i, R> for SkipChar<'i, N> { false => None, } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + match input.skip(N) { + true => Some(input), + false => None, + } + } } impl<'i, const N: usize> Debug for SkipChar<'i, N> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -163,6 +201,17 @@ impl<'i, R: RuleType, const MIN: char, const MAX: char> TypedNode<'i, R> for Cha false => None, } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + match input.match_range(MIN..MAX) { + true => Some(input), + false => None, + } + } } impl Debug for CharRange { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -190,6 +239,17 @@ impl<'i, R: RuleType, const CHAR: char> TypedNode<'i, R> for Char { false => None, } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + match input.match_char_by(|c| c == CHAR) { + true => Some(input), + false => None, + } + } } impl Debug for Char { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -290,6 +350,7 @@ impl DerefMut for Positive { } } impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Positive { + #[inline] fn try_parse_with_partial( input: Position<'i>, stack: &mut Stack>, @@ -309,6 +370,26 @@ impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Positive { } }) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + tracker.positive_during(|tracker| { + stack.snapshot(); + match T::check_with_partial(input, stack, tracker) { + Some(_pos) => { + stack.restore(); + Some(input) + } + None => { + stack.restore(); + None + } + } + }) + } } impl EmptyPairContainer for Positive {} @@ -327,6 +408,7 @@ impl From<()> for Negative { } } impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Negative { + #[inline] fn try_parse_with_partial( input: Position<'i>, stack: &mut Stack>, @@ -346,6 +428,26 @@ impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Negative { } }) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + tracker.negative_during(|tracker| { + stack.snapshot(); + match T::check_with_partial(input, stack, tracker) { + Some(_) => { + stack.restore(); + None + } + None => { + stack.restore(); + Some(input) + } + } + }) + } } impl Debug for Negative { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -376,6 +478,21 @@ impl<'i, R: RuleType> TypedNode<'i, R> for ANY { false => None, } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + let mut c: char = ' '; + match input.match_char_by(|ch| { + c = ch; + true + }) { + true => Some(input), + false => None, + } + } } impl Debug for ANY { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -396,6 +513,14 @@ impl<'i, R: RuleType> TypedNode<'i, R> for NONE { ) -> Option<(Position<'i>, Self)> { None } + #[inline] + fn check_with_partial( + _input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + None + } } impl EmptyPairContainer for NONE {} @@ -411,6 +536,14 @@ impl<'i, R: RuleType> TypedNode<'i, R> for Empty { ) -> Option<(Position<'i>, Self)> { Some((input, Self)) } + #[inline] + fn check_with_partial( + input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + Some(input) + } } impl<'i, R: RuleType> NeverFailedTypedNode<'i, R> for Empty { fn parse_with_partial( @@ -438,6 +571,18 @@ impl<'i, R: RuleType> TypedNode<'i, R> for SOI { None } } + #[inline] + fn check_with_partial( + input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + if input.at_start() { + Some(input) + } else { + None + } + } } impl EmptyPairContainer for SOI {} @@ -459,6 +604,18 @@ impl<'i, R: RuleType> TypedNode<'i, R> for EOI { None } } + #[inline] + fn check_with_partial( + input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + if input.at_end() { + Some(input) + } else { + None + } + } } impl EmptyPairContainer for EOI {} @@ -498,6 +655,23 @@ impl<'i, R: RuleType> TypedNode<'i, R> for NEWLINE { }; Some((input, Self { content: t })) } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + _stack: &mut Stack>, + _tracker: &mut Tracker<'i, R>, + ) -> Option> { + let input = if input.match_string("\r\n") { + input + } else if input.match_string("\n") { + input + } else if input.match_string("\r") { + input + } else { + return None; + }; + Some(input) + } } impl Debug for NEWLINE { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -525,6 +699,16 @@ impl<'i, R: RuleType> TypedNode<'i, R> for PEEK_ALL<'i> { let (input, span) = peek_spans::(input, spans, tracker)?; Some((input, Self { span })) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + let spans = stack[0..stack.len()].iter().rev(); + let (input, _span) = peek_spans::(input, spans, tracker)?; + Some(input) + } } impl<'i> Debug for PEEK_ALL<'i> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -564,6 +748,23 @@ impl<'i, R: RuleType> TypedNode<'i, R> for PEEK<'i> { } } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + match stack.peek() { + Some(string) => match input.match_string(string.as_str()) { + true => Some(input), + false => None, + }, + None => { + tracker.empty_stack(input); + None + } + } + } } impl<'i> Debug for PEEK<'i> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -592,6 +793,20 @@ impl<'i, R: RuleType> TypedNode<'i, R> for DROP { } } } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + match stack.pop() { + Some(_) => Some(input), + None => { + tracker.empty_stack(input); + None + } + } + } } impl EmptyPairContainer for DROP {} @@ -625,6 +840,23 @@ impl<'i, R: RuleType> TypedNode<'i, R> for POP<'i> { } } } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + match stack.pop() { + Some(span) => match input.match_string(span.as_str()) { + true => Some(input), + false => None, + }, + None => { + tracker.empty_stack(input); + None + } + } + } } impl<'i> Debug for POP<'i> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -656,6 +888,16 @@ impl<'i, R: RuleType> TypedNode<'i, R> for POP_ALL<'i> { while stack.pop().is_some() {} Some((input, Self::from(res.span))) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + let input = PEEK_ALL::check_with_partial(input, stack, tracker)?; + while stack.pop().is_some() {} + Some(input) + } } impl<'i> Debug for POP_ALL<'i> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -687,6 +929,17 @@ impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for PUSH { stack.push(start.span(&input)); Some((input, Self::from(content))) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + let start = input; + let input = T::check_with_partial(input, stack, tracker)?; + stack.push(start.span(&input)); + Some(input) + } } impl Deref for PUSH { type Target = T; @@ -729,6 +982,16 @@ impl<'i, R: RuleType, const START: isize, const END: isize> TypedNode<'i, R> let (input, _) = peek_spans::(input, spans, tracker)?; Some((input, Self)) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + let spans = stack_slice(input, START, Some(END), stack, tracker)?; + let (input, _) = peek_spans::(input, spans, tracker)?; + Some(input) + } } impl EmptyPairContainer for PeekSlice2 {} @@ -746,6 +1009,16 @@ impl<'i, R: RuleType, const START: isize> TypedNode<'i, R> for PeekSlice1 let (input, _) = peek_spans::(input, spans, tracker)?; Some((input, Self)) } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + let spans = stack_slice(input, START, None, stack, tracker)?; + let (input, _) = peek_spans::(input, spans, tracker)?; + Some(input) + } } impl EmptyPairContainer for PeekSlice1 {} diff --git a/pest/src/typed/template/repetition.rs b/pest/src/typed/template/repetition.rs index 23f6828..7a32bba 100644 --- a/pest/src/typed/template/repetition.rs +++ b/pest/src/typed/template/repetition.rs @@ -37,7 +37,10 @@ impl< > NeverFailedTypedNode<'i, R> for RepMinMax { #[inline] - fn parse_with_partial(mut input: Position<'i>, stack: &mut Stack>) -> (Position<'i>, Self) { + fn parse_with_partial( + mut input: Position<'i>, + stack: &mut Stack>, + ) -> (Position<'i>, Self) { let mut vec = Vec::new(); let mut tracker = Tracker::new(input); @@ -96,6 +99,34 @@ impl< Some((input, Self { content: vec })) } + #[inline] + fn check_with_partial( + mut input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + let mut vec = Vec::new(); + + for i in 0..MAX { + match restore_on_none(stack, |stack| { + try_parse_unit::(input, stack, tracker, i) + }) { + Some((next, matched)) => { + input = next; + vec.push(matched); + } + None => { + if i < MIN { + return None; + } else { + break; + } + } + } + } + + Some(input) + } } impl IntoIterator for RepMinMax diff --git a/pest/src/typed/tracker.rs b/pest/src/typed/tracker.rs index 215df30..93cd5e6 100644 --- a/pest/src/typed/tracker.rs +++ b/pest/src/typed/tracker.rs @@ -169,9 +169,9 @@ impl<'i, R: RuleType> Tracker<'i, R> { pub(crate) fn record_option_during_with( &mut self, pos: Position<'i>, - f: impl FnOnce(&mut Self) -> Option<(Position<'i>, T)>, + f: impl FnOnce(&mut Self) -> Option, rule: R, - ) -> Option<(Position<'i>, T)> { + ) -> Option { if let Some((_, _, has_children)) = self.stack.last_mut() { *has_children = true; } @@ -186,7 +186,7 @@ impl<'i, R: RuleType> Tracker<'i, R> { } /// Record if the result doesn't match the state during calling `f`. #[inline] - pub fn record_during, E>( + pub fn record_result_during, E>( &mut self, pos: Position<'i>, f: impl FnOnce(&mut Self) -> Result<(Position<'i>, T), E>, @@ -195,13 +195,22 @@ impl<'i, R: RuleType> Tracker<'i, R> { } /// Record if the result doesn't match the state during calling `f`. #[inline] - pub fn record_option_during>( + pub fn record_option_during>( &mut self, pos: Position<'i>, f: impl FnOnce(&mut Self) -> Option<(Position<'i>, T)>, ) -> Option<(Position<'i>, T)> { self.record_option_during_with(pos, f, T::RULE) } + /// Record if the result doesn't match the state during calling `f`. + #[inline] + pub fn record_empty_during>( + &mut self, + pos: Position<'i>, + f: impl FnOnce(&mut Self) -> Option>, + ) -> Option> { + self.record_option_during_with(pos, f, T::RULE) + } fn collect_to_message(self) -> String { let (pos, attempts) = self.finish(); // "{} | " @@ -299,7 +308,7 @@ mod tests { use super::*; #[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] - enum Rule { + pub enum Rule { Program, SOI, Main, @@ -319,7 +328,7 @@ mod tests { ($name:ident) => { #[derive(Clone, PartialEq)] pub struct $name; - impl RuleWrapper for $name { + impl RuleWrapper for $name { const RULE: Rule = Rule::$name; type Rule = Rule; } @@ -335,12 +344,12 @@ mod tests { fn negative() -> Result<(), ()> { let pos = Position::from_start("abc\ndef\nghi"); let mut tracker = Tracker::<'_, Rule>::new(pos); - let _ = tracker.record_during(pos, |tracker| { + let _ = tracker.record_result_during(pos, |tracker| { tracker.positive_during(|tracker| { - tracker.record_during(pos, |_| Ok((pos, rule_wrappers::Main))) + tracker.record_result_during(pos, |_| Ok((pos, rule_wrappers::Main))) })?; tracker.negative_during(|tracker| { - tracker.record_during(pos, |_| Ok((pos, rule_wrappers::Main))) + tracker.record_result_during(pos, |_| Ok((pos, rule_wrappers::Main))) })?; Ok((pos, rule_wrappers::Program)) })?; @@ -361,19 +370,19 @@ mod tests { fn positive() -> Result<(), ()> { let pos = Position::from_start("abc\ndef\nghi"); let mut tracker = Tracker::<'_, Rule>::new(pos); - let _ = tracker.record_during(pos, |tracker| { + let _ = tracker.record_result_during(pos, |tracker| { let _ = tracker.positive_during(|tracker| { if false { Ok((pos, rule_wrappers::SOI)) } else { - tracker.record_during(pos, |_| Err(())) + tracker.record_result_during(pos, |_| Err(())) } }); let _ = tracker.negative_during(|tracker| { if false { Ok((pos, rule_wrappers::SOI)) } else { - tracker.record_during(pos, |_| Err(())) + tracker.record_result_during(pos, |_| Err(())) } }); Ok((pos, rule_wrappers::Program)) @@ -395,14 +404,14 @@ mod tests { fn unicode() -> Result<(), ()> { let mut pos = Position::from_start("αβψ\nδεφ\nγηι"); let mut tracker = Tracker::<'_, Rule>::new(pos); - let _ = tracker.record_during(pos, |tracker| { + let _ = tracker.record_result_during(pos, |tracker| { let suc = pos.match_string("α"); assert!(suc); tracker.positive_during(|tracker| { - tracker.record_during(pos, |_| Ok((pos, rule_wrappers::Main))) + tracker.record_result_during(pos, |_| Ok((pos, rule_wrappers::Main))) })?; tracker.negative_during(|tracker| { - tracker.record_during(pos, |_| Ok((pos, rule_wrappers::Main))) + tracker.record_result_during(pos, |_| Ok((pos, rule_wrappers::Main))) })?; Ok((pos, rule_wrappers::Program)) })?; @@ -423,13 +432,13 @@ mod tests { fn nested() -> Result<(), ()> { let mut pos = Position::from_start("αβψ\nδεφ\nγηι"); let mut tracker = Tracker::<'_, Rule>::new(pos); - let _ = tracker.record_during(pos, |tracker| { + let _ = tracker.record_result_during(pos, |tracker| { let suc = pos.match_string("α"); assert!(suc); tracker.negative_during(|tracker| { - tracker.record_during(pos, |tracker| { + tracker.record_result_during(pos, |tracker| { tracker.negative_during(|tracker| { - tracker.record_during(pos, |_| Ok((pos, rule_wrappers::Body))) + tracker.record_result_during(pos, |_| Ok((pos, rule_wrappers::Body))) })?; Ok((pos, rule_wrappers::Main)) }) diff --git a/pest/src/typed/traits.rs b/pest/src/typed/traits.rs index d9f18b9..8ad9c7c 100644 --- a/pest/src/typed/traits.rs +++ b/pest/src/typed/traits.rs @@ -17,6 +17,12 @@ pub trait RuleType: Copy + Debug + Eq + Hash + Ord { /// Node of a typed syntax tree. pub trait TypedNode<'i, R: RuleType>: Sized { + /// Try parse a part of or all of remained string into a node. + fn try_parse_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option<(Position<'i>, Self)>; /// Try parse remained string into a node. #[inline] fn try_parse_with( @@ -24,46 +30,75 @@ pub trait TypedNode<'i, R: RuleType>: Sized { stack: &mut Stack>, tracker: &mut Tracker<'i, R>, ) -> Option { - let (input, res) = match Self::try_parse_with_partial(input, stack, tracker) { - Some((input, res)) => (input, res), - None => return None, - }; - let (_input, _eoi) = match tracker.record_option_during_with( + let (input, res) = Self::try_parse_with_partial(input, stack, tracker)?; + let (_input, _eoi) = tracker.record_option_during_with( input, |tracker| EOI::try_parse_with_partial(input, stack, tracker), ::EOI, - ) { - Some((input, res)) => (input, res), - None => return None, - }; + )?; Some(res) } - /// Try parse a part of or all of remained string into a node. - fn try_parse_with_partial( + /// Try parsing leading part of string into a node. + #[inline] + fn try_parse_partial(input: &'i str) -> Result<(Position<'i>, Self), Error> { + let mut stack = Stack::new(); + let input = Position::from_start(input); + let mut tracker = Tracker::new(input); + Self::try_parse_with_partial(input, &mut stack, &mut tracker) + .ok_or_else(|| tracker.collect()) + } + /// Try parsing given string into a node. + #[inline] + fn try_parse(input: &'i str) -> Result> { + let mut stack = Stack::new(); + let input = Position::from_start(input); + let mut tracker = Tracker::new(input); + Self::try_parse_with(input, &mut stack, &mut tracker).ok_or_else(|| tracker.collect()) + } + /// Check whether the some leading part of the result can be accepted. + fn check_with_partial( input: Position<'i>, stack: &mut Stack>, tracker: &mut Tracker<'i, R>, - ) -> Option<(Position<'i>, Self)>; - /// Try parse given string into a node. + ) -> Option>; + /// Check whether the some leading part of the result can be accepted. #[inline] - fn try_parse(input: &'i str) -> Result> { + fn check_with( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> bool { + let input = match Self::check_with_partial(input, stack, tracker) { + Some(input) => input, + None => return false, + }; + let _input = match tracker.record_option_during_with( + input, + |tracker| EOI::check_with_partial(input, stack, tracker), + ::EOI, + ) { + Some(input) => input, + None => return false, + }; + true + } + /// Try parsing leading part of string into a node. + #[inline] + fn check_partial(input: &'i str) -> Result, Error> { let mut stack = Stack::new(); let input = Position::from_start(input); let mut tracker = Tracker::new(input); - match Self::try_parse_with(input, &mut stack, &mut tracker) { - Some(res) => Ok(res), - None => Err(tracker.collect()), - } + Self::check_with_partial(input, &mut stack, &mut tracker).ok_or_else(|| tracker.collect()) } - /// Try parse leading part of string into a node. + /// Try parsing given string into a node. #[inline] - fn try_parse_partial(input: &'i str) -> Result<(Position<'i>, Self), Error> { + fn check(input: &'i str) -> Result<(), Error> { let mut stack = Stack::new(); let input = Position::from_start(input); let mut tracker = Tracker::new(input); - match Self::try_parse_with_partial(input, &mut stack, &mut tracker) { - Some((input, res)) => Ok((input, res)), - None => Err(tracker.collect()), + match Self::check_with(input, &mut stack, &mut tracker) { + true => Ok(()), + false => Err(tracker.collect()), } } // /// Whether this node accepts null input. @@ -72,6 +107,40 @@ pub trait TypedNode<'i, R: RuleType>: Sized { // const FIRST: &'static [char]; } +/// Struct for rules with full capacity. +pub trait FullRuleStruct<'i>: wrapper::Rule { + /// Wrapped inner type. + type Inner: TypedNode<'i, Self::Rule>; + /// Wrapped content type. + type Content: From; + /// Create from span and content. + fn new(content: Self::Content, span: Span<'i>) -> Self; +} +impl<'i, R: RuleType, T: FullRuleStruct<'i, Rule = R>> TypedNode<'i, R> for T { + fn try_parse_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option<(Position<'i>, Self)> { + tracker.record_option_during(input, |tracker| { + let (pos, content) = ::try_parse_with_partial(input, stack, tracker)?; + let content = content.into(); + let span = input.span(&pos); + Some((pos, Self::new(content, span))) + }) + } + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + tracker.record_empty_during::(input, |tracker| { + let pos = ::check_with_partial(input, stack, tracker)?; + Some(pos) + }) + } +} + /// A container of pairs. pub trait PairContainer { /// for `Self` as a pair if it is, otherwise for each child pair. @@ -97,13 +166,14 @@ impl> PairContainer for Option { } } -pub(super) trait EmptyPairContainer {} +/// Contains no pair. +pub trait EmptyPairContainer {} impl PairContainer for T { fn for_each_child_pair(&self, _f: &mut impl FnMut(Pair)) {} } /// A pair that can be converted to a pair tree. -pub trait PairTree: PairContainer + wrapper::Rule { +pub trait PairTree: PairContainer + wrapper::Rule { /// Get pair span. fn get_span(&self) -> (usize, usize); /// Convert `Self` to a pair tree. @@ -121,6 +191,7 @@ pub trait PairTree: PairContainer + wrapper::Rule { } impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Option { + #[inline] fn try_parse_with_partial( input: Position<'i>, stack: &mut Stack>, @@ -138,6 +209,24 @@ impl<'i, R: RuleType, T: TypedNode<'i, R>> TypedNode<'i, R> for Option { } } } + #[inline] + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + ) -> Option> { + stack.snapshot(); + match T::check_with_partial(input, stack, tracker) { + Some(pos) => { + stack.clear_snapshot(); + Some(pos) + } + None => { + stack.restore(); + Some(input) + } + } + } } /// Parser that can produce typed syntax tree. diff --git a/pest/src/typed/wrapper.rs b/pest/src/typed/wrapper.rs index ff6d7b2..3a80dfc 100644 --- a/pest/src/typed/wrapper.rs +++ b/pest/src/typed/wrapper.rs @@ -1,5 +1,5 @@ //! Wrapper. -use pest2::RuleType; +use super::RuleType; /// A wrapper for string constant. pub trait String { @@ -12,11 +12,11 @@ pub trait String { } /// A wrapper for string constant. -pub trait Rule { +pub trait Rule { /// Should be the type of wrapped rule. type Rule: RuleType; /// Wrapped rule. - const RULE: R; + const RULE: Self::Rule; } /// Bound for the length of vector. diff --git a/pest/tests/predefined_node.rs b/pest/tests/predefined_node.rs index add50cc..83937d0 100644 --- a/pest/tests/predefined_node.rs +++ b/pest/tests/predefined_node.rs @@ -13,11 +13,11 @@ mod tests { wrapper::{Rule as RuleWrapper, String as StringWrapper}, RuleType, Tracker, TypedNode, TypedParser, }, - Position, Span, Stack, + unicode, Position, Span, Stack, }; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - enum Rule { + pub enum Rule { Foo, EOI, } @@ -28,6 +28,8 @@ mod tests { type MandatoryTrivia<'i> = Empty; } + unicode!(MATH); + struct Parser; impl TypedParser for Parser {} @@ -41,7 +43,7 @@ mod tests { pub struct StrFoo { content: Str, } - impl RuleWrapper for StrFoo { + impl RuleWrapper for StrFoo { type Rule = Rule; const RULE: Rule = Rule::Foo; } @@ -54,6 +56,14 @@ mod tests { let (pos, content) = Str::::try_parse_with_partial(input, stack, tracker)?; Some((pos, Self { content })) } + fn check_with_partial( + input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, Rule>, + ) -> Option> { + let pos = Str::::check_with_partial(input, stack, tracker)?; + Some(pos) + } } #[test] From e67575b5a87613d952ce94ac3a2617b4ec66d706 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Mon, 26 Feb 2024 16:53:15 +0800 Subject: [PATCH 10/15] Update attr.rs --- generator/src/typed/attr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generator/src/typed/attr.rs b/generator/src/typed/attr.rs index c4f4048..4f54373 100644 --- a/generator/src/typed/attr.rs +++ b/generator/src/typed/attr.rs @@ -1,6 +1,7 @@ use super::config::Config; use crate::config::{get_bool, get_string, GrammarSource}; use proc_macro2::Ident; +use quote::ToTokens; use syn::{DeriveInput, Generics}; pub(crate) fn parse_derive(ast: DeriveInput) -> (Ident, Generics, Vec, Config) { @@ -23,8 +24,6 @@ pub(crate) fn parse_derive(ast: DeriveInput) -> (Ident, Generics, Vec Date: Mon, 26 Feb 2024 16:53:29 +0800 Subject: [PATCH 11/15] Import pest2 for unicode. --- generator/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/Cargo.toml b/generator/Cargo.toml index 6dc70c1..f560bca 100644 --- a/generator/Cargo.toml +++ b/generator/Cargo.toml @@ -9,7 +9,7 @@ proc-macro2 = "1.0" quote = "1.0" syn = "2.0" pest_meta.workspace = true +pest.workspace = true [dev-dependencies] lazy_static = { version = "1.4.0" } -pest.workspace = true From 9a09d14b9b11a8702298f6f6d8a38e1358a0c819 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Mon, 26 Feb 2024 17:01:27 +0800 Subject: [PATCH 12/15] Format codes. --- generator/tests/expected.rs | 555 +++++++++++++++++++++++++++++------ generator/tests/generator.rs | 2 - pest/src/choice.rs | 2 +- pest/src/formatter.rs | 2 +- pest/src/sequence.rs | 2 +- 5 files changed, 476 insertions(+), 87 deletions(-) diff --git a/generator/tests/expected.rs b/generator/tests/expected.rs index 0f4cadb..419edf2 100644 --- a/generator/tests/expected.rs +++ b/generator/tests/expected.rs @@ -1,5 +1,10 @@ #[doc = "For compatibility."] -#[allow(dead_code, missing_docs, non_camel_case_types, clippy::upper_case_acronyms)] +#[allow( + dead_code, + missing_docs, + non_camel_case_types, + clippy::upper_case_acronyms +)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum Rule { EOI, @@ -40,8 +45,10 @@ impl ::pest::typed::RuleType for Rule { type MandatoryTrivia<'i> = trivia::MandatoryTrivia<'i>; } mod trivia { - pub type OptionalTrivia<'i> = super::generics::Rep, 0u8>; - pub type MandatoryTrivia<'i> = super::generics::RepOnce, 0u8>; + pub type OptionalTrivia<'i> = + super::generics::Rep, 0u8>; + pub type MandatoryTrivia<'i> = + super::generics::RepOnce, 0u8>; } mod wrapper { #[doc = "A wrapper for `\" \"`."] @@ -134,10 +141,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Regular<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -151,7 +164,14 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Atomic<'i> { #[doc = r" Matched structure."] - pub content: super::generics::Sequence3, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>, + pub content: super::generics::Sequence3< + super::generics::RepOnce, 0u8>, + 0u8, + super::generics::Str, + 1u8, + super::generics::RepOnce, 0u8>, + 1u8, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -160,18 +180,38 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#Atomic; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Atomic<'i> { - type Inner = super::generics::Sequence3, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>; - type Content = super::generics::Sequence3, 0u8>, 0u8, super::generics::Str, 1u8, super::generics::RepOnce, 0u8>, 1u8>; + type Inner = super::generics::Sequence3< + super::generics::RepOnce, 0u8>, + 0u8, + super::generics::Str, + 1u8, + super::generics::RepOnce, 0u8>, + 1u8, + >; + type Content = super::generics::Sequence3< + super::generics::RepOnce, 0u8>, + 0u8, + super::generics::Str, + 1u8, + super::generics::RepOnce, 0u8>, + 1u8, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Atomic<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -185,7 +225,12 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#NonAtomic<'i> { #[doc = r" Matched structure."] - pub content: super::generics::Sequence2, 0u8, super::generics::Str, 2u8>, + pub content: super::generics::Sequence2< + super::generics::Str, + 0u8, + super::generics::Str, + 2u8, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -194,18 +239,34 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#NonAtomic; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#NonAtomic<'i> { - type Inner = super::generics::Sequence2, 0u8, super::generics::Str, 2u8>; - type Content = super::generics::Sequence2, 0u8, super::generics::Str, 2u8>; + type Inner = super::generics::Sequence2< + super::generics::Str, + 0u8, + super::generics::Str, + 2u8, + >; + type Content = super::generics::Sequence2< + super::generics::Str, + 0u8, + super::generics::Str, + 2u8, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#NonAtomic<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -236,10 +297,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#ExactString<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -270,10 +337,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#CharRange<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -304,10 +377,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Any<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -321,7 +400,14 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Seq<'i> { #[doc = r" Matched structure."] - pub content: super::generics::Sequence3, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>, + pub content: super::generics::Sequence3< + super::generics::Str, + 0u8, + super::generics::CharRange<'2', '9'>, + 1u8, + super::generics::Str, + 1u8, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -330,18 +416,38 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#Seq; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Seq<'i> { - type Inner = super::generics::Sequence3, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>; - type Content = super::generics::Sequence3, 0u8, super::generics::CharRange<'2', '9'>, 1u8, super::generics::Str, 1u8>; + type Inner = super::generics::Sequence3< + super::generics::Str, + 0u8, + super::generics::CharRange<'2', '9'>, + 1u8, + super::generics::Str, + 1u8, + >; + type Content = super::generics::Sequence3< + super::generics::Str, + 0u8, + super::generics::CharRange<'2', '9'>, + 1u8, + super::generics::Str, + 1u8, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Seq<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -355,7 +461,33 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Choice<'i> { #[doc = r" Matched structure."] - pub content: ::pest::std::Box, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>>, + pub content: ::pest::std::Box< + super::generics::Choice9< + super::generics::Str, + super::generics::Sequence2< + super::generics::RepOnce, 0u8>, + 0u8, + super::rules::RepAtLeastOnce<'i>, + 1u8, + >, + super::generics::Sequence4< + super::generics::Positive>, + 0u8, + super::rules::Choice<'i>, + 1u8, + super::rules::Rep<'i>, + 1u8, + super::rules::Opt<'i>, + 1u8, + >, + super::rules::Peek<'i>, + super::rules::PeekLeft<'i>, + super::rules::PeekRight<'i>, + super::rules::PeekLeftRight<'i>, + super::rules::Drop<'i>, + super::rules::PeekAll<'i>, + >, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -364,18 +496,74 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#Choice; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Choice<'i> { - type Inner = super::generics::Choice9, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>; - type Content = ::pest::std::Box, super::generics::Sequence2, 0u8>, 0u8, super::rules::RepAtLeastOnce<'i>, 1u8>, super::generics::Sequence4>, 0u8, super::rules::Choice<'i>, 1u8, super::rules::Rep<'i>, 1u8, super::rules::Opt<'i>, 1u8>, super::rules::Peek<'i>, super::rules::PeekLeft<'i>, super::rules::PeekRight<'i>, super::rules::PeekLeftRight<'i>, super::rules::Drop<'i>, super::rules::PeekAll<'i>>>; + type Inner = super::generics::Choice9< + super::generics::Str, + super::generics::Sequence2< + super::generics::RepOnce, 0u8>, + 0u8, + super::rules::RepAtLeastOnce<'i>, + 1u8, + >, + super::generics::Sequence4< + super::generics::Positive>, + 0u8, + super::rules::Choice<'i>, + 1u8, + super::rules::Rep<'i>, + 1u8, + super::rules::Opt<'i>, + 1u8, + >, + super::rules::Peek<'i>, + super::rules::PeekLeft<'i>, + super::rules::PeekRight<'i>, + super::rules::PeekLeftRight<'i>, + super::rules::Drop<'i>, + super::rules::PeekAll<'i>, + >; + type Content = ::pest::std::Box< + super::generics::Choice9< + super::generics::Str, + super::generics::Sequence2< + super::generics::RepOnce, 0u8>, + 0u8, + super::rules::RepAtLeastOnce<'i>, + 1u8, + >, + super::generics::Sequence4< + super::generics::Positive>, + 0u8, + super::rules::Choice<'i>, + 1u8, + super::rules::Rep<'i>, + 1u8, + super::rules::Opt<'i>, + 1u8, + >, + super::rules::Peek<'i>, + super::rules::PeekLeft<'i>, + super::rules::PeekRight<'i>, + super::rules::PeekLeftRight<'i>, + super::rules::Drop<'i>, + super::rules::PeekAll<'i>, + >, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Choice<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -406,10 +594,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Rep<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -440,10 +634,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#RepAtLeastOnce<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -474,10 +674,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Opt<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -491,7 +697,8 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepExact<'i> { #[doc = r" Matched structure."] - pub content: super::generics::RepMinMax, 0u8, 3usize, 3usize>, + pub content: + super::generics::RepMinMax, 0u8, 3usize, 3usize>, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -500,18 +707,26 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#RepExact; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepExact<'i> { - type Inner = super::generics::RepMinMax, 0u8, 3usize, 3usize>; - type Content = super::generics::RepMinMax, 0u8, 3usize, 3usize>; + type Inner = + super::generics::RepMinMax, 0u8, 3usize, 3usize>; + type Content = + super::generics::RepMinMax, 0u8, 3usize, 3usize>; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#RepExact<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -542,10 +757,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#RepLeft<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -576,10 +797,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#RepRight<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -610,10 +837,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#RepLeftRight<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -627,7 +860,14 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Pos<'i> { #[doc = r" Matched structure."] - pub content: super::generics::Positive, 0u8, 2usize, 4usize>, 1u8>>, + pub content: super::generics::Positive< + super::generics::Sequence2< + super::generics::r#SOI, + 0u8, + super::generics::RepMinMax, 0u8, 2usize, 4usize>, + 1u8, + >, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -636,18 +876,38 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#Pos; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Pos<'i> { - type Inner = super::generics::Positive, 0u8, 2usize, 4usize>, 1u8>>; - type Content = super::generics::Positive, 0u8, 2usize, 4usize>, 1u8>>; + type Inner = super::generics::Positive< + super::generics::Sequence2< + super::generics::r#SOI, + 0u8, + super::generics::RepMinMax, 0u8, 2usize, 4usize>, + 1u8, + >, + >; + type Content = super::generics::Positive< + super::generics::Sequence2< + super::generics::r#SOI, + 0u8, + super::generics::RepMinMax, 0u8, 2usize, 4usize>, + 1u8, + >, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Pos<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -661,7 +921,9 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Neg<'i> { #[doc = r" Matched structure."] - pub content: super::generics::Negative, 1u8>>, + pub content: super::generics::Negative< + super::generics::Sequence2, 1u8>, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -670,18 +932,28 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#Neg; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Neg<'i> { - type Inner = super::generics::Negative, 1u8>>; - type Content = super::generics::Negative, 1u8>>; + type Inner = super::generics::Negative< + super::generics::Sequence2, 1u8>, + >; + type Content = super::generics::Negative< + super::generics::Sequence2, 1u8>, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Neg<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -695,7 +967,26 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Push<'i> { #[doc = r" Matched structure."] - pub content: ::pest::std::Box, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>>, + pub content: ::pest::std::Box< + super::generics::r#push< + super::generics::Sequence7< + super::generics::Rep, 0u8>, + 0u8, + super::rules::Neg<'i>, + 1u8, + super::generics::RepOnce, 0u8>, + 1u8, + super::rules::Push<'i>, + 1u8, + super::rules::Pop<'i>, + 1u8, + super::rules::Push<'i>, + 1u8, + super::rules::PopAll<'i>, + 1u8, + >, + >, + >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -704,18 +995,60 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#Push; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Push<'i> { - type Inner = super::generics::r#push, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>; - type Content = ::pest::std::Box, 0u8>, 0u8, super::rules::Neg<'i>, 1u8, super::generics::RepOnce, 0u8>, 1u8, super::rules::Push<'i>, 1u8, super::rules::Pop<'i>, 1u8, super::rules::Push<'i>, 1u8, super::rules::PopAll<'i>, 1u8>>>; + type Inner = super::generics::r#push< + super::generics::Sequence7< + super::generics::Rep, 0u8>, + 0u8, + super::rules::Neg<'i>, + 1u8, + super::generics::RepOnce, 0u8>, + 1u8, + super::rules::Push<'i>, + 1u8, + super::rules::Pop<'i>, + 1u8, + super::rules::Push<'i>, + 1u8, + super::rules::PopAll<'i>, + 1u8, + >, + >; + type Content = ::pest::std::Box< + super::generics::r#push< + super::generics::Sequence7< + super::generics::Rep, 0u8>, + 0u8, + super::rules::Neg<'i>, + 1u8, + super::generics::RepOnce, 0u8>, + 1u8, + super::rules::Push<'i>, + 1u8, + super::rules::Pop<'i>, + 1u8, + super::rules::Push<'i>, + 1u8, + super::rules::PopAll<'i>, + 1u8, + >, + >, + >; #[inline] fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { Self { content, span } } } impl<'i> ::pest::typed::PairContainer for r#Push<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -746,10 +1079,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Pop<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -780,10 +1119,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#PopAll<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -814,10 +1159,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Peek<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -848,10 +1199,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#PeekUnlimited<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -882,10 +1239,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#PeekLeft<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -916,10 +1279,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#PeekRight<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -950,10 +1319,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#PeekLeftRight<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -984,10 +1359,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#Drop<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -1018,10 +1399,16 @@ pub mod rules { } } impl<'i> ::pest::typed::PairContainer for r#PeekAll<'i> { - fn for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { self.content.for_self_or_for_each_child_pair(f) } - fn for_self_or_for_each_child_pair(&self, f: &mut impl ::pest::std::FnMut(::pest::token::Pair)) { + fn for_self_or_for_each_child_pair( + &self, + f: &mut impl ::pest::std::FnMut(::pest::token::Pair), + ) { use pest::typed::PairTree; f(self.as_pair_tree()) } @@ -1039,5 +1426,9 @@ pub mod generics { pub use pest::sequence::Sequence3; pub use pest::sequence::Sequence4; pub use pest::sequence::Sequence7; - pub use pest::typed::template::{CharRange, Insens, Negative, PeekSlice1, PeekSlice2, Positive, Rep, RepMax, RepMin, RepMinMax, RepOnce, Str, ANY as any, DROP as drop, EOI, PEEK as peek, PEEK_ALL as peek_all, POP as pop, POP_ALL as pop_all, PUSH as push, SOI}; + pub use pest::typed::template::{ + CharRange, Insens, Negative, PeekSlice1, PeekSlice2, Positive, Rep, RepMax, RepMin, + RepMinMax, RepOnce, Str, ANY as any, DROP as drop, EOI, PEEK as peek, PEEK_ALL as peek_all, + POP as pop, POP_ALL as pop_all, PUSH as push, SOI, + }; } diff --git a/generator/tests/generator.rs b/generator/tests/generator.rs index 013275d..8a2bafb 100644 --- a/generator/tests/generator.rs +++ b/generator/tests/generator.rs @@ -22,8 +22,6 @@ fn generated_rules() { std::fs::write(path_generated, &actual).unwrap(); let output = std::process::Command::new("rustfmt") .arg(path_generated) - .arg("--config") - .arg("use_small_heuristics=Max,max_width=1000") .output() .unwrap(); assert!( diff --git a/pest/src/choice.rs b/pest/src/choice.rs index f66727c..b52c989 100644 --- a/pest/src/choice.rs +++ b/pest/src/choice.rs @@ -1,4 +1,4 @@ -//! A [macro](crate::choice_type) to generate choice type +//! A [macro](crate::choice_type) to generate choice type //! and generated choice types that has 2 to 15 variants, //! which are named `Choice{i}`. diff --git a/pest/src/formatter.rs b/pest/src/formatter.rs index ac97959..5e892d4 100644 --- a/pest/src/formatter.rs +++ b/pest/src/formatter.rs @@ -1,5 +1,5 @@ //! Copied from [pest-typed/formatter.rs]. -//! +//! //! [pest-typed/formatter.rs]: https://github.com/TheVeryDarkness/pest-typed/blob/0.12.1/main/src/formatter.rs use crate::{Position, Span}; diff --git a/pest/src/sequence.rs b/pest/src/sequence.rs index b829f22..47ce4f0 100644 --- a/pest/src/sequence.rs +++ b/pest/src/sequence.rs @@ -1,4 +1,4 @@ -//! A [macro](crate::sequence_type) to generate sequence type +//! A [macro](crate::sequence_type) to generate sequence type //! and generated sequence types that has 2 to 15 fields, //! which are named `field_{i}`. From 951674687e79f3ea8973ecccf2a0b442ff92dcac Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Mon, 26 Feb 2024 23:31:36 +0800 Subject: [PATCH 13/15] Refactor module system and use meta/tests/pest3sample.pest as grammar test. --- derive/tests/grammar.pest | 18 +- derive/tests/sample.rs | 36 ++++ generator/src/typed/attr.rs | 1 - generator/src/typed/generator.rs | 39 ++-- generator/src/typed/module.rs | 212 +++++++++++++++------ generator/src/typed/output.rs | 5 +- generator/tests/.gitignore | 3 +- generator/tests/expected.rs | 310 +++++++++++++++++++------------ generator/tests/generator.rs | 32 +++- generator/tests/syntax.pest | 20 +- 10 files changed, 461 insertions(+), 215 deletions(-) create mode 100644 derive/tests/sample.rs diff --git a/derive/tests/grammar.pest b/derive/tests/grammar.pest index eec3ec5..e387feb 100644 --- a/derive/tests/grammar.pest +++ b/derive/tests/grammar.pest @@ -36,17 +36,17 @@ repeat_min_atomic = string{2..} repeat_max = string~{..2} repeat_max_atomic = string{..2} soi_at_start = pest::SOI - string -repeat_mutate_stack = (pest::push('a'..'c') - ",")* - pest::pop - pest::pop - pest::pop -repeat_mutate_stack_pop_all = (pest::push('a'..'c') - ",")* - pest::pop_all +repeat_mutate_stack = (pest::stack::push('a'..'c') - ",")* - pest::stack::pop - pest::stack::pop - pest::stack::pop +repeat_mutate_stack_pop_all = (pest::stack::push('a'..'c') - ",")* - pest::stack::pop_all will_fail = repeat_mutate_stack_pop_all - "FAIL" stack_resume_after_fail = will_fail | repeat_mutate_stack_pop_all -peek_ = pest::push(range) - pest::push(range) - pest::peek - pest::peek -peek_all = pest::push(range) - pest::push(range) - pest::peek_all -peek_slice_23 = pest::push(range) - pest::push(range) - pest::push(range) ~ pest::push(range) ~ pest::push(range) ~ pest::peek[1..-2] -pop_ = pest::push(range) - pest::push(range) - pest::pop - pest::pop -pop_all = pest::push(range) - pest::push(range) - pest::pop_all -pop_fail = pest::push(range) - !pest::pop - range - pest::pop -checkpoint_restore = pest::push("") - (pest::push("a") - "b" - pest::pop | pest::drop - "b" | pest::pop - "a") - pest::EOI +peek_ = pest::stack::push(range) - pest::stack::push(range) - pest::stack::peek - pest::stack::peek +peek_all = pest::stack::push(range) - pest::stack::push(range) - pest::stack::peek_all +peek_slice_23 = pest::stack::push(range) - pest::stack::push(range) - pest::stack::push(range) ~ pest::stack::push(range) ~ pest::stack::push(range) ~ pest::stack::peek[1..-2] +pop_ = pest::stack::push(range) - pest::stack::push(range) - pest::stack::pop - pest::stack::pop +pop_all = pest::stack::push(range) - pest::stack::push(range) - pest::stack::pop_all +pop_fail = pest::stack::push(range) - !pest::stack::pop - range - pest::stack::pop +checkpoint_restore = pest::stack::push("") - (pest::stack::push("a") - "b" - pest::stack::pop | pest::stack::drop - "b" | pest::stack::pop - "a") - pest::EOI /* ascii_digits = ASCII_DIGIT+ diff --git a/derive/tests/sample.rs b/derive/tests/sample.rs new file mode 100644 index 0000000..56ee19c --- /dev/null +++ b/derive/tests/sample.rs @@ -0,0 +1,36 @@ +#![allow(unused_variables)] +use anyhow::Result; +use pest::typed::TypedNode as _; +use pest_derive::Parser; + +#[derive(Parser)] +#[grammar = "../meta/tests/pest3sample.pest"] +struct Parser; + +#[test] +fn comment() -> Result<()> { + rules::main::try_parse_partial("x x x /*x*/")?; + rules::main::try_parse("x x x /*x*/").unwrap_err(); + Ok(()) +} + +#[test] +fn skip_on_two_end() -> Result<()> { + rules::main::try_parse_partial("x x ")?; + rules::main::try_parse(" x x").unwrap_err(); + rules::main::try_parse("x x ").unwrap_err(); + Ok(()) +} + +#[test] +fn post_skip() -> Result<()> { + let program = rules::program::try_parse("x x /*x*/")?; + Ok(()) +} + +#[test] +fn pre_skip() -> Result<()> { + rules::program::try_parse("/* x x */ ")?; + rules::program::try_parse("/* x x */ x x")?; + Ok(()) +} diff --git a/generator/src/typed/attr.rs b/generator/src/typed/attr.rs index 4f54373..c8db507 100644 --- a/generator/src/typed/attr.rs +++ b/generator/src/typed/attr.rs @@ -1,7 +1,6 @@ use super::config::Config; use crate::config::{get_bool, get_string, GrammarSource}; use proc_macro2::Ident; -use quote::ToTokens; use syn::{DeriveInput, Generics}; pub(crate) fn parse_derive(ast: DeriveInput) -> (Ident, Generics, Vec, Config) { diff --git a/generator/src/typed/generator.rs b/generator/src/typed/generator.rs index 7b0a483..3b0057b 100644 --- a/generator/src/typed/generator.rs +++ b/generator/src/typed/generator.rs @@ -120,17 +120,6 @@ impl<'g> RuleRef<'g> { let path = path.iter().map(String::as_str).collect::>(); Self { path, args } } - /// Create from a name of a rule defined in current module. - pub fn from_current(path: Vec<&'g str>) -> Self { - let args = None; - Self { path, args } - } - /// Create from a name of a rule defined in current module. - fn from_top_level(name: &'g str) -> Self { - let path = vec![name]; - let args = None; - Self { path, args } - } } impl<'g> Display for RuleRef<'g> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -144,6 +133,7 @@ impl<'g> Display for RuleRef<'g> { } fn create_rule<'g>( + config: Config, rule_config: &RuleConfig<'g>, rule_info: &RuleInfo<'g>, inner_type: TokenStream, @@ -155,16 +145,22 @@ fn create_rule<'g>( "Generated for rule `{}`. Grammar: `{}`.", rule_info.rule_name, rule_config.grammar.node, ); + let args: Vec<_> = rule_config + .grammar + .args + .iter() + .map(|s| format_ident!("r#{}", s)) + .collect(); // Pairs inside silent rule will be ignored. let pair_api = match rule_info.silent { true => quote! { - impl<'i> #this::typed::PairContainer<#root::Rule> for #name<'i> { + impl<'i, #(#args, )*> #this::typed::PairContainer<#root::Rule> for #name<'i, #(#args, )*> { fn for_each_child_pair(&self, f: &mut impl #this::std::FnMut(#this::token::Pair<#root::Rule>)) {} fn for_self_or_for_each_child_pair(&self, f: &mut impl #this::std::FnMut(#this::token::Pair<#root::Rule>)) {} } }, false => quote! { - impl<'i> #this::typed::PairContainer<#root::Rule> for #name<'i> { + impl<'i, #(#args, )*> #this::typed::PairContainer<#root::Rule> for #name<'i, #(#args, )*> { fn for_each_child_pair(&self, f: &mut impl #this::std::FnMut(#this::token::Pair<#root::Rule>)) { self.content.for_self_or_for_each_child_pair(f) } @@ -173,7 +169,7 @@ fn create_rule<'g>( f(self.as_pair_tree()) } } - impl<'i> #this::typed::PairTree<#root::Rule> for #name<'i> { + impl<'i, #(#args, )*> #this::typed::PairTree<#root::Rule> for #name<'i, #(#args, )*> { fn get_span(&self) -> (#this::std::usize, #this::std::usize) { (self.span.start(), self.span.end()) } @@ -188,21 +184,21 @@ fn create_rule<'g>( quote! { #[doc = #doc] #[derive(Clone, Debug, Eq, PartialEq)] - pub struct #name<'i> { + pub struct #name<'i, #(#args, )*> { /// Matched structure. pub content: #content_type, /// Matched span. pub span: #this::Span<'i>, } - impl<'i> #this::typed::wrapper::Rule for #name<'i> { + impl<'i, #(#args, )*> #this::typed::wrapper::Rule for #name<'i, #(#args, )*> { type Rule = #root::Rule; const RULE: #root::Rule = #root::Rule::#name; } - impl<'i> #this::typed::FullRuleStruct<'i> for #name<'i> { + impl<'i, #(#args, )*> #this::typed::FullRuleStruct<'i> for #name<'i, #(#args, )*> { type Inner = #inner_type; type Content = #content_type; #[inline] - fn new(content: Self::Content, span: #this::Span<'i>) -> Self { + fn new(content: >::Content, span: #this::Span<'i>) -> Self { Self { content, span } } } @@ -293,10 +289,8 @@ fn process_expr<'g>( ProcessedPathArgs::process(args, rule_config, output, config, mod_sys, root) }); let rule_ref = RuleRef::new(prefix, args); - let typename = mod_sys.resolve(&rule_ref, root).expect(&format!( - "`{rule_ref}` can't be resolved. Available rules are: {:?}", - mod_sys.keys() - )); + let typename = mod_sys + .resolve(rule_config.grammar, &rule_ref, root); Intermediate { typename } } ParseExpr::PosPred(node) => { @@ -416,6 +410,7 @@ fn process_rule<'g: 'f, 'f>( _ => { let rule_info = RuleInfo::new(rule, config, reachability); res.insert_rule_struct(create_rule( + config, &rule_config, &rule_info, inter.typename, diff --git a/generator/src/typed/module.rs b/generator/src/typed/module.rs index 35e5668..fd56497 100644 --- a/generator/src/typed/module.rs +++ b/generator/src/typed/module.rs @@ -6,12 +6,18 @@ use pest::unicode::unicode_property_names; use pest_meta::parser::ParseRule; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; -use std::collections::{btree_map::Keys, BTreeMap}; +use std::{ + cell::RefCell, + collections::{btree_map::Keys, BTreeMap, HashMap, HashSet}, + rc::Rc, +}; #[derive(Clone, Debug)] pub enum RuleGenerics { /// Defined rule in current module. - Rule, + Rule { + argc: usize, + }, Unicode(Ident), BuiltIn { /// Built-in rule that accepts nothing as argument. @@ -30,29 +36,39 @@ pub enum RuleGenerics { }, } impl RuleGenerics { - pub fn call(&self, rule_ref: &RuleRef<'_>, root: &TokenStream) -> TokenStream { - let getter = || { - let mut path = rule_ref.path.iter().map(|s| format_ident!("{}", s)); - let name = path.next_back().unwrap(); - (path, name) - }; - let builtin_getter = || { - assert_eq!(rule_ref.path.len(), 2); - let name = rule_ref.path.last().unwrap(); - let name = format_ident!("r#{}", name); - name - }; + pub fn call( + &self, + name: &str, + rule_ref: &RuleRef<'_>, + args: Option<&ProcessedPathArgs>, + root: &TokenStream, + ) -> TokenStream { let generics = generics(); + let name = format_ident!("r#{}", name); match self { - Self::Rule => { - assert!( - rule_ref.args.is_none(), - "Unexpected arguments in `{}`.", - rule_ref, - ); - let (path, name) = getter(); - quote! { #root::rules::#( #path:: )* #name :: <'i> } - } + Self::Rule { argc } => match (argc, args) { + (0, None) => { + quote! { #root::rules::#name::<'i> } + } + (0, Some(_args)) => { + panic!("Unexpected arguments in `{}`.", rule_ref,); + } + (argc, None) => { + panic!("Expect {argc} arguments in `{rule_ref}`."); + } + (_argc, Some(ProcessedPathArgs::Slice(slice))) => { + panic!("Unexpected slice {slice} in `{rule_ref}`."); + } + (argc, Some(ProcessedPathArgs::Call(args))) => { + assert_eq!( + *argc, + args.len(), + "Argument count not matched in `{}`.", + rule_ref + ); + quote! { #root::rules::#name::<'i, #(#args, )*> } + } + }, Self::Unicode(ident) => { quote! { #root::rules::unicode::#ident } } @@ -60,9 +76,8 @@ impl RuleGenerics { direct, slice, callable, - } => match &rule_ref.args { + } => match args { None => { - let name = builtin_getter(); let (lifetime,) = direct.expect(&format!( "Built-in rule {rule_ref} can't be called without arguments." )); @@ -89,7 +104,6 @@ impl RuleGenerics { if let Some(argc) = argc { assert_eq!(args.len(), argc, "Argument count not matched."); } - let name = builtin_getter(); quote! { #root::#generics::#name::< #( #args, )* > } } }, @@ -97,13 +111,62 @@ impl RuleGenerics { } } +#[derive(Clone, Debug)] +enum ModuleNode<'g> { + // MutableCollection(RefCell>>>), + Collection(HashMap<&'g str, Rc>>), + Map { + bound: HashSet, + mapper: fn(&'g str) -> TokenStream, + }, + Generics(RuleGenerics), + Imported(Rc), +} + +impl<'g> ModuleNode<'g> { + /// [Err] here is actually not an error. + fn child(&self, node: &'g str) -> &Self { + match self { + Self::Collection(map) => map.get(node).unwrap_or_else(|| { + panic!( + "Node {} can't be resolved. Available nodes are {:?}.", + node, + map.keys() + ) + }), + Self::Map { bound, mapper } => { + assert!(bound.contains(node), "{node} is out of bound."); + panic!("No child found.") + } + Self::Generics(_generics) => panic!("No child found."), + Self::Imported(rc) => rc.child(node), + } + } + fn get( + &self, + root: &TokenStream, + node: &'g str, + rule_ref: &RuleRef<'g>, + args: &Option, + ) -> TokenStream { + match self { + Self::Collection(map) => panic!("Collection can't be called."), + Self::Map { bound, mapper } => { + assert!(args.is_none(), "Unexpected arguments."); + mapper(node) + } + Self::Generics(generics) => generics.call(node, rule_ref, args.as_ref(), root), + Self::Imported(rc) => rc.get(root, node, rule_ref, args), + } + } +} + /// Module system for pest3. /// /// `'g` stands for the lifetime of grammar file content. #[derive(Clone, Debug)] pub struct ModuleSystem<'g> { - /// Path -> Rule. - tree: BTreeMap, RuleGenerics>, + root: ModuleNode<'g>, } impl<'g> ModuleSystem<'g> { @@ -129,19 +192,20 @@ impl<'g> ModuleSystem<'g> { macro_rules! pest_builtin { ( $name:ident $( {$($direct:tt)*} )? $( [$($slice:tt)*] )? $( ($($callable:tt)*) )? ) => { ( - vec!["pest", core::stringify!($name)], - RuleGenerics::BuiltIn { - direct: None $( .or(Some(pest_direct! { $($direct)* })) )?, - slice: None $( .or(Some(pest_slice! { $( $slice )* })) )?, - callable: None $( .or(Some(pest_callable! { $( $callable )* })) )?, - }, + core::stringify!($name), + Rc::new( + ModuleNode::Generics( + RuleGenerics::BuiltIn { + direct: None $( .or(Some(pest_direct! { $($direct)* })) )?, + slice: None $( .or(Some(pest_slice! { $( $slice )* })) )?, + callable: None $( .or(Some(pest_callable! { $( $callable )* })) )?, + }, + ) + ) ) }; } - let mut tree = BTreeMap::from([ - pest_builtin!(SOI {}), - pest_builtin!(EOI {}), - pest_builtin!(any {}), + let pest_stack = HashMap::from([ pest_builtin!(peek {'i} [PeekSlice1, PeekSlice2]), pest_builtin!(peek_all {'i}), pest_builtin!(drop {}), @@ -149,27 +213,65 @@ impl<'g> ModuleSystem<'g> { pest_builtin!(pop {'i}), pest_builtin!(pop_all {'i}), ]); - for unicode in unicode_property_names() { + let bound = HashSet::from_iter(unicode_property_names().map(|unicode| { assert!(unicode.is_ascii()); - let ident = format_ident!("{}", unicode.to_ascii_lowercase()); - tree.insert( - vec!["pest", "unicode", unicode], - RuleGenerics::Unicode(ident), - ); - } - Self { tree } + // let ident = format_ident!("{}", unicode.to_ascii_lowercase()); + unicode.to_ascii_lowercase() + })); + let mapper = |s: &'g str| { + let ident = format_ident!("{}", s.to_ascii_uppercase()); + quote! {#ident} + }; + let pest_unicode = ModuleNode::Map { bound, mapper }; + let pest = HashMap::from([ + pest_builtin!(SOI {}), + pest_builtin!(EOI {}), + pest_builtin!(soi {}), + pest_builtin!(eoi {}), + pest_builtin!(any {}), + ("stack", Rc::new(ModuleNode::Collection(pest_stack))), + ("unicode", Rc::new(pest_unicode)), + ]); + let root = ModuleNode::Collection(HashMap::from([( + "pest", + Rc::new(ModuleNode::Collection(pest)), + )])); + + Self { root } } pub fn insert_rule(&mut self, rule: &'g ParseRule) { let key = &rule.name; - let value = RuleGenerics::Rule; - self.tree.insert(vec![key], value); - } - pub fn resolve(&self, rule_ref: &RuleRef<'g>, root: &TokenStream) -> Option { - self.tree - .get(&rule_ref.path) - .map(|rg| rg.call(rule_ref, root)) + let argc = rule.args.len(); + let value = RuleGenerics::Rule { argc }; + if let ModuleNode::Collection(root) = &mut self.root { + root.insert(key, Rc::new(ModuleNode::Generics(value))); + } } - pub fn keys(&self) -> Keys<'_, Vec<&'g str>, RuleGenerics> { - self.tree.keys() + pub fn resolve( + &self, + rule: &'g ParseRule, + rule_ref: &RuleRef<'g>, + root: &TokenStream, + ) -> TokenStream { + // Rule generics arguments. + if let None = rule_ref.args { + if rule_ref.path.len() == 1 { + let arg = rule.args.iter().find(|arg| arg == &rule_ref.path[0]); + if let Some(arg) = arg { + let ident = format_ident!("r#{}", arg); + return quote! {#ident}; + } + } + } + let mut rc = &self.root; + for node in &rule_ref.path { + rc = rc.child(node); + } + rc.get( + root, + rule_ref.path.last().unwrap(), + rule_ref, + &rule_ref.args, + ) } } diff --git a/generator/src/typed/output.rs b/generator/src/typed/output.rs index e344d8b..1fbc930 100644 --- a/generator/src/typed/output.rs +++ b/generator/src/typed/output.rs @@ -165,8 +165,9 @@ impl<'g> Output<'g> { Positive, Negative, CharRange, Str, Insens, Rep, RepOnce, RepMin, RepMax, RepMinMax, - SOI as SOI, - EOI as EOI, + SOI,EOI, + SOI as soi, + EOI as eoi, ANY as any, PEEK as peek, PeekSlice1, PeekSlice2, diff --git a/generator/tests/.gitignore b/generator/tests/.gitignore index 3c52ba5..9e4a659 100644 --- a/generator/tests/.gitignore +++ b/generator/tests/.gitignore @@ -1 +1,2 @@ -generated.rs \ No newline at end of file +generated.rs +generated_sample.rs \ No newline at end of file diff --git a/generator/tests/expected.rs b/generator/tests/expected.rs index 419edf2..880aca4 100644 --- a/generator/tests/expected.rs +++ b/generator/tests/expected.rs @@ -136,7 +136,10 @@ pub mod rules { type Inner = super::generics::RepOnce, 0u8>; type Content = super::generics::RepOnce, 0u8>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -165,11 +168,11 @@ pub mod rules { pub struct r#Atomic<'i> { #[doc = r" Matched structure."] pub content: super::generics::Sequence3< - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 0u8, super::generics::Str, 1u8, - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 1u8, >, #[doc = r" Matched span."] @@ -181,23 +184,26 @@ pub mod rules { } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Atomic<'i> { type Inner = super::generics::Sequence3< - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 0u8, super::generics::Str, 1u8, - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 1u8, >; type Content = super::generics::Sequence3< - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 0u8, super::generics::Str, 1u8, - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 1u8, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -252,7 +258,10 @@ pub mod rules { 2u8, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -292,7 +301,10 @@ pub mod rules { type Inner = super::generics::Str; type Content = super::generics::Str; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -332,7 +344,10 @@ pub mod rules { type Inner = super::generics::CharRange<'0', '9'>; type Content = super::generics::CharRange<'0', '9'>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -372,7 +387,10 @@ pub mod rules { type Inner = super::generics::r#any; type Content = super::generics::r#any; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -433,7 +451,10 @@ pub mod rules { 1u8, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -467,25 +488,25 @@ pub mod rules { super::generics::Sequence2< super::generics::RepOnce, 0u8>, 0u8, - super::rules::RepAtLeastOnce<'i>, + super::rules::r#RepAtLeastOnce<'i>, 1u8, >, super::generics::Sequence4< super::generics::Positive>, 0u8, - super::rules::Choice<'i>, + super::rules::r#Choice<'i>, 1u8, - super::rules::Rep<'i>, + super::rules::r#Rep<'i>, 1u8, - super::rules::Opt<'i>, + super::rules::r#Opt<'i>, 1u8, >, - super::rules::Peek<'i>, - super::rules::PeekLeft<'i>, - super::rules::PeekRight<'i>, - super::rules::PeekLeftRight<'i>, - super::rules::Drop<'i>, - super::rules::PeekAll<'i>, + super::rules::r#Peek<'i>, + super::rules::r#PeekLeft<'i>, + super::rules::r#PeekRight<'i>, + super::rules::r#PeekLeftRight<'i>, + super::rules::r#Drop<'i>, + super::rules::r#PeekAll<'i>, >, >, #[doc = r" Matched span."] @@ -501,25 +522,25 @@ pub mod rules { super::generics::Sequence2< super::generics::RepOnce, 0u8>, 0u8, - super::rules::RepAtLeastOnce<'i>, + super::rules::r#RepAtLeastOnce<'i>, 1u8, >, super::generics::Sequence4< super::generics::Positive>, 0u8, - super::rules::Choice<'i>, + super::rules::r#Choice<'i>, 1u8, - super::rules::Rep<'i>, + super::rules::r#Rep<'i>, 1u8, - super::rules::Opt<'i>, + super::rules::r#Opt<'i>, 1u8, >, - super::rules::Peek<'i>, - super::rules::PeekLeft<'i>, - super::rules::PeekRight<'i>, - super::rules::PeekLeftRight<'i>, - super::rules::Drop<'i>, - super::rules::PeekAll<'i>, + super::rules::r#Peek<'i>, + super::rules::r#PeekLeft<'i>, + super::rules::r#PeekRight<'i>, + super::rules::r#PeekLeftRight<'i>, + super::rules::r#Drop<'i>, + super::rules::r#PeekAll<'i>, >; type Content = ::pest::std::Box< super::generics::Choice9< @@ -527,29 +548,32 @@ pub mod rules { super::generics::Sequence2< super::generics::RepOnce, 0u8>, 0u8, - super::rules::RepAtLeastOnce<'i>, + super::rules::r#RepAtLeastOnce<'i>, 1u8, >, super::generics::Sequence4< super::generics::Positive>, 0u8, - super::rules::Choice<'i>, + super::rules::r#Choice<'i>, 1u8, - super::rules::Rep<'i>, + super::rules::r#Rep<'i>, 1u8, - super::rules::Opt<'i>, + super::rules::r#Opt<'i>, 1u8, >, - super::rules::Peek<'i>, - super::rules::PeekLeft<'i>, - super::rules::PeekRight<'i>, - super::rules::PeekLeftRight<'i>, - super::rules::Drop<'i>, - super::rules::PeekAll<'i>, + super::rules::r#Peek<'i>, + super::rules::r#PeekLeft<'i>, + super::rules::r#PeekRight<'i>, + super::rules::r#PeekLeftRight<'i>, + super::rules::r#Drop<'i>, + super::rules::r#PeekAll<'i>, >, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -589,7 +613,10 @@ pub mod rules { type Inner = super::generics::Rep, 0u8>; type Content = super::generics::Rep, 0u8>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -629,7 +656,10 @@ pub mod rules { type Inner = super::generics::RepOnce, 0u8>; type Content = super::generics::RepOnce, 0u8>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -669,7 +699,10 @@ pub mod rules { type Inner = ::pest::std::Option>; type Content = ::pest::std::Option>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -698,7 +731,7 @@ pub mod rules { pub struct r#RepExact<'i> { #[doc = r" Matched structure."] pub content: - super::generics::RepMinMax, 0u8, 3usize, 3usize>, + super::generics::RepMinMax, 0u8, 3usize, 3usize>, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -708,11 +741,14 @@ pub mod rules { } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepExact<'i> { type Inner = - super::generics::RepMinMax, 0u8, 3usize, 3usize>; + super::generics::RepMinMax, 0u8, 3usize, 3usize>; type Content = - super::generics::RepMinMax, 0u8, 3usize, 3usize>; + super::generics::RepMinMax, 0u8, 3usize, 3usize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -740,7 +776,7 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepLeft<'i> { #[doc = r" Matched structure."] - pub content: super::generics::RepMin, 0u8, 1usize>, + pub content: super::generics::RepMin, 0u8, 1usize>, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -749,10 +785,13 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#RepLeft; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepLeft<'i> { - type Inner = super::generics::RepMin, 0u8, 1usize>; - type Content = super::generics::RepMin, 0u8, 1usize>; + type Inner = super::generics::RepMin, 0u8, 1usize>; + type Content = super::generics::RepMin, 0u8, 1usize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -780,7 +819,7 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepRight<'i> { #[doc = r" Matched structure."] - pub content: super::generics::RepMax, 0u8, 2usize>, + pub content: super::generics::RepMax, 0u8, 2usize>, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -789,10 +828,13 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#RepRight; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepRight<'i> { - type Inner = super::generics::RepMax, 0u8, 2usize>; - type Content = super::generics::RepMax, 0u8, 2usize>; + type Inner = super::generics::RepMax, 0u8, 2usize>; + type Content = super::generics::RepMax, 0u8, 2usize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -820,7 +862,7 @@ pub mod rules { #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#RepLeftRight<'i> { #[doc = r" Matched structure."] - pub content: super::generics::RepMinMax, 0u8, 1usize, 2usize>, + pub content: super::generics::RepMinMax, 0u8, 1usize, 2usize>, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, } @@ -829,10 +871,14 @@ pub mod rules { const RULE: super::Rule = super::Rule::r#RepLeftRight; } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#RepLeftRight<'i> { - type Inner = super::generics::RepMinMax, 0u8, 1usize, 2usize>; - type Content = super::generics::RepMinMax, 0u8, 1usize, 2usize>; + type Inner = super::generics::RepMinMax, 0u8, 1usize, 2usize>; + type Content = + super::generics::RepMinMax, 0u8, 1usize, 2usize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -864,7 +910,7 @@ pub mod rules { super::generics::Sequence2< super::generics::r#SOI, 0u8, - super::generics::RepMinMax, 0u8, 2usize, 4usize>, + super::generics::RepMinMax, 0u8, 2usize, 4usize>, 1u8, >, >, @@ -880,7 +926,7 @@ pub mod rules { super::generics::Sequence2< super::generics::r#SOI, 0u8, - super::generics::RepMinMax, 0u8, 2usize, 4usize>, + super::generics::RepMinMax, 0u8, 2usize, 4usize>, 1u8, >, >; @@ -888,12 +934,15 @@ pub mod rules { super::generics::Sequence2< super::generics::r#SOI, 0u8, - super::generics::RepMinMax, 0u8, 2usize, 4usize>, + super::generics::RepMinMax, 0u8, 2usize, 4usize>, 1u8, >, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -922,7 +971,7 @@ pub mod rules { pub struct r#Neg<'i> { #[doc = r" Matched structure."] pub content: super::generics::Negative< - super::generics::Sequence2, 1u8>, + super::generics::Sequence2, 1u8>, >, #[doc = r" Matched span."] pub span: ::pest::Span<'i>, @@ -933,13 +982,16 @@ pub mod rules { } impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Neg<'i> { type Inner = super::generics::Negative< - super::generics::Sequence2, 1u8>, + super::generics::Sequence2, 1u8>, >; type Content = super::generics::Negative< - super::generics::Sequence2, 1u8>, + super::generics::Sequence2, 1u8>, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -963,26 +1015,26 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `Push`. Grammar: `pest::push((RepLeft* ~ (Neg ~ (ExactString+ ~ (Push ~ (Pop ~ (Push ~ PopAll)))))))`."] + #[doc = "Generated for rule `Push`. Grammar: `pest::stack::push((RepLeft* ~ (Neg ~ (ExactString+ ~ (Push ~ (Pop ~ (Push ~ PopAll)))))))`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Push<'i> { #[doc = r" Matched structure."] pub content: ::pest::std::Box< super::generics::r#push< super::generics::Sequence7< - super::generics::Rep, 0u8>, + super::generics::Rep, 0u8>, 0u8, - super::rules::Neg<'i>, + super::rules::r#Neg<'i>, 1u8, - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 1u8, - super::rules::Push<'i>, + super::rules::r#Push<'i>, 1u8, - super::rules::Pop<'i>, + super::rules::r#Pop<'i>, 1u8, - super::rules::Push<'i>, + super::rules::r#Push<'i>, 1u8, - super::rules::PopAll<'i>, + super::rules::r#PopAll<'i>, 1u8, >, >, @@ -997,44 +1049,47 @@ pub mod rules { impl<'i> ::pest::typed::FullRuleStruct<'i> for r#Push<'i> { type Inner = super::generics::r#push< super::generics::Sequence7< - super::generics::Rep, 0u8>, + super::generics::Rep, 0u8>, 0u8, - super::rules::Neg<'i>, + super::rules::r#Neg<'i>, 1u8, - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 1u8, - super::rules::Push<'i>, + super::rules::r#Push<'i>, 1u8, - super::rules::Pop<'i>, + super::rules::r#Pop<'i>, 1u8, - super::rules::Push<'i>, + super::rules::r#Push<'i>, 1u8, - super::rules::PopAll<'i>, + super::rules::r#PopAll<'i>, 1u8, >, >; type Content = ::pest::std::Box< super::generics::r#push< super::generics::Sequence7< - super::generics::Rep, 0u8>, + super::generics::Rep, 0u8>, 0u8, - super::rules::Neg<'i>, + super::rules::r#Neg<'i>, 1u8, - super::generics::RepOnce, 0u8>, + super::generics::RepOnce, 0u8>, 1u8, - super::rules::Push<'i>, + super::rules::r#Push<'i>, 1u8, - super::rules::Pop<'i>, + super::rules::r#Pop<'i>, 1u8, - super::rules::Push<'i>, + super::rules::r#Push<'i>, 1u8, - super::rules::PopAll<'i>, + super::rules::r#PopAll<'i>, 1u8, >, >, >; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1058,7 +1113,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `Pop`. Grammar: `pest::pop`."] + #[doc = "Generated for rule `Pop`. Grammar: `pest::stack::pop`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Pop<'i> { #[doc = r" Matched structure."] @@ -1074,7 +1129,10 @@ pub mod rules { type Inner = super::generics::r#pop<'i>; type Content = super::generics::r#pop<'i>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1098,7 +1156,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `PopAll`. Grammar: `pest::pop_all`."] + #[doc = "Generated for rule `PopAll`. Grammar: `pest::stack::pop_all`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PopAll<'i> { #[doc = r" Matched structure."] @@ -1114,7 +1172,10 @@ pub mod rules { type Inner = super::generics::r#pop_all<'i>; type Content = super::generics::r#pop_all<'i>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1138,7 +1199,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `Peek`. Grammar: `pest::peek`."] + #[doc = "Generated for rule `Peek`. Grammar: `pest::stack::peek`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Peek<'i> { #[doc = r" Matched structure."] @@ -1154,7 +1215,10 @@ pub mod rules { type Inner = super::generics::r#peek<'i>; type Content = super::generics::r#peek<'i>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1178,7 +1242,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `PeekUnlimited`. Grammar: `pest::peek[..]`."] + #[doc = "Generated for rule `PeekUnlimited`. Grammar: `pest::stack::peek[..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekUnlimited<'i> { #[doc = r" Matched structure."] @@ -1194,7 +1258,10 @@ pub mod rules { type Inner = super::generics::PeekSlice1<0isize>; type Content = super::generics::PeekSlice1<0isize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1218,7 +1285,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `PeekLeft`. Grammar: `pest::peek[1..]`."] + #[doc = "Generated for rule `PeekLeft`. Grammar: `pest::stack::peek[1..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekLeft<'i> { #[doc = r" Matched structure."] @@ -1234,7 +1301,10 @@ pub mod rules { type Inner = super::generics::PeekSlice1<1isize>; type Content = super::generics::PeekSlice1<1isize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1258,7 +1328,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `PeekRight`. Grammar: `pest::peek[..]`."] + #[doc = "Generated for rule `PeekRight`. Grammar: `pest::stack::peek[..]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekRight<'i> { #[doc = r" Matched structure."] @@ -1274,7 +1344,10 @@ pub mod rules { type Inner = super::generics::PeekSlice1<0isize>; type Content = super::generics::PeekSlice1<0isize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1298,7 +1371,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `PeekLeftRight`. Grammar: `pest::peek[1..2]`."] + #[doc = "Generated for rule `PeekLeftRight`. Grammar: `pest::stack::peek[1..2]`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekLeftRight<'i> { #[doc = r" Matched structure."] @@ -1314,7 +1387,10 @@ pub mod rules { type Inner = super::generics::PeekSlice2<1isize, 2isize>; type Content = super::generics::PeekSlice2<1isize, 2isize>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1338,7 +1414,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `Drop`. Grammar: `pest::drop`."] + #[doc = "Generated for rule `Drop`. Grammar: `pest::stack::drop`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#Drop<'i> { #[doc = r" Matched structure."] @@ -1354,7 +1430,10 @@ pub mod rules { type Inner = super::generics::r#drop; type Content = super::generics::r#drop; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1378,7 +1457,7 @@ pub mod rules { (self.span.start(), self.span.end()) } } - #[doc = "Generated for rule `PeekAll`. Grammar: `pest::peek_all`."] + #[doc = "Generated for rule `PeekAll`. Grammar: `pest::stack::peek_all`."] #[derive(Clone, Debug, Eq, PartialEq)] pub struct r#PeekAll<'i> { #[doc = r" Matched structure."] @@ -1394,7 +1473,10 @@ pub mod rules { type Inner = super::generics::r#peek_all<'i>; type Content = super::generics::r#peek_all<'i>; #[inline] - fn new(content: Self::Content, span: ::pest::Span<'i>) -> Self { + fn new( + content: >::Content, + span: ::pest::Span<'i>, + ) -> Self { Self { content, span } } } @@ -1428,7 +1510,7 @@ pub mod generics { pub use pest::sequence::Sequence7; pub use pest::typed::template::{ CharRange, Insens, Negative, PeekSlice1, PeekSlice2, Positive, Rep, RepMax, RepMin, - RepMinMax, RepOnce, Str, ANY as any, DROP as drop, EOI, PEEK as peek, PEEK_ALL as peek_all, - POP as pop, POP_ALL as pop_all, PUSH as push, SOI, + RepMinMax, RepOnce, Str, ANY as any, DROP as drop, EOI, EOI as eoi, PEEK as peek, + PEEK_ALL as peek_all, POP as pop, POP_ALL as pop_all, PUSH as push, SOI, SOI as soi, }; } diff --git a/generator/tests/generator.rs b/generator/tests/generator.rs index 8a2bafb..54070d3 100644 --- a/generator/tests/generator.rs +++ b/generator/tests/generator.rs @@ -7,7 +7,7 @@ use quote::quote; /// rustfmt generator/tests/generated.txt /// ``` #[test] -fn generated_rules() { +fn generated() { let path_generated = "tests/generated.rs"; let path_expected = "tests/expected.rs"; let actual = derive_typed_parser( @@ -35,3 +35,33 @@ fn generated_rules() { panic!("Generated codes have changed.") } } + +#[test] +fn generated_sample() { + let path_generated = "tests/generated_sample.rs"; + let path_expected = "tests/expected_sample.rs"; + let actual = derive_typed_parser( + quote! { + #[grammar = "../meta/tests/pest3sample.pest"] + struct Parser; + }, + false, + false, + ); + let actual = actual.to_string(); + std::fs::write(path_generated, &actual).unwrap(); + let output = std::process::Command::new("rustfmt") + .arg(path_generated) + .output() + .unwrap(); + assert!( + output.status.success(), + "STDOUT:\n{}\nSTDERR:\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap(), + ); + + if std::fs::read(path_generated).unwrap() != std::fs::read(path_expected).unwrap() { + panic!("Generated codes have changed.") + } +} diff --git a/generator/tests/syntax.pest b/generator/tests/syntax.pest index 253d29f..39da322 100644 --- a/generator/tests/syntax.pest +++ b/generator/tests/syntax.pest @@ -28,17 +28,17 @@ RepLeftRight = RepRight{1..2} Pos = &(pest::SOI ~ RepLeftRight{2..4}) Neg = !(pest::EOI ~ Pos) -Push = pest::push(RepLeft* ~ Neg ~ ExactString+ ~ Push ~ Pop ~ Push ~ PopAll) +Push = pest::stack::push(RepLeft* ~ Neg ~ ExactString+ ~ Push ~ Pop ~ Push ~ PopAll) -Pop = pest::pop -PopAll = pest::pop_all +Pop = pest::stack::pop +PopAll = pest::stack::pop_all -Peek = pest::peek -PeekUnlimited = pest::peek[..] -PeekLeft = pest::peek[1..] -PeekRight = pest::peek[..] -PeekLeftRight = pest::peek[1..2] +Peek = pest::stack::peek +PeekUnlimited = pest::stack::peek[..] +PeekLeft = pest::stack::peek[1..] +PeekRight = pest::stack::peek[..] +PeekLeftRight = pest::stack::peek[1..2] -Drop = pest::drop +Drop = pest::stack::drop -PeekAll = pest::peek_all +PeekAll = pest::stack::peek_all From 0faa18790db5135551d9716bd6d11ce6515bb8d0 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 27 Feb 2024 10:02:03 +0800 Subject: [PATCH 14/15] Fix `check_with_partial` of `RepMinMax`. --- pest/src/typed/template/repetition.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/pest/src/typed/template/repetition.rs b/pest/src/typed/template/repetition.rs index 7a32bba..06ffb78 100644 --- a/pest/src/typed/template/repetition.rs +++ b/pest/src/typed/template/repetition.rs @@ -105,15 +105,12 @@ impl< stack: &mut Stack>, tracker: &mut Tracker<'i, R>, ) -> Option> { - let mut vec = Vec::new(); - for i in 0..MAX { match restore_on_none(stack, |stack| { - try_parse_unit::(input, stack, tracker, i) + check_unit::(input, stack, tracker, i) }) { - Some((next, matched)) => { + Some(next) => { input = next; - vec.push(matched); } None => { if i < MIN { @@ -191,3 +188,18 @@ fn try_parse_unit<'i, R: RuleType, T: TypedNode<'i, R>, const TRIVIA: u8>( input = next; Some((input, matched)) } + +#[inline] +fn check_unit<'i, R: RuleType, T: TypedNode<'i, R>, const TRIVIA: u8>( + mut input: Position<'i>, + stack: &mut Stack>, + tracker: &mut Tracker<'i, R>, + i: usize, +) -> Option> { + if i > 0 { + input = try_handle_trivia::(input, stack, tracker)?; + } + let next = T::check_with_partial(input, stack, tracker)?; + input = next; + Some(input) +} From 8dc3206d1e1a66ebd8386f5e9b195449d95f69a2 Mon Sep 17 00:00:00 2001 From: TheVeryDarkness <3266343194@qq.com> Date: Tue, 27 Feb 2024 10:12:58 +0800 Subject: [PATCH 15/15] Add a todo to `TypedNode`. --- pest/src/typed/traits.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pest/src/typed/traits.rs b/pest/src/typed/traits.rs index 8ad9c7c..3a92782 100644 --- a/pest/src/typed/traits.rs +++ b/pest/src/typed/traits.rs @@ -101,6 +101,11 @@ pub trait TypedNode<'i, R: RuleType>: Sized { false => Err(tracker.collect()), } } + // /// Whether this node will modify the stack. + // /// Must be evaluated correctly, + // /// otherwise the stack won't be restored correctly. + // const MODIFY_STACK: bool; + // /// Whether this node accepts null input. // const NULLABLE: bool; // /// Leading characters that this node accepts.