From e1862c395c87492645cbc01ed402a6728d099857 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Mon, 20 Nov 2017 20:40:32 +0000 Subject: [PATCH 1/6] Made preliminary changes to subgrammars. The code shows an example structure for subgrammars being implemented, without any checking. --- src/grammar.rustpeg | 18 +++++++++++++--- src/translate.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/grammar.rustpeg b/src/grammar.rustpeg index 2e8ed4c..990f7f5 100644 --- a/src/grammar.rustpeg +++ b/src/grammar.rustpeg @@ -11,17 +11,19 @@ spanned pub items -> Vec> = _ items:spanned**_ _ { items } rule -> Rule - = legacy_exported:exportflag _ cached:cacheflag _ public:pubflag _ name:identifier _ returns:returntype _ "=" _ expression:expression (_ ";")? { + = legacy_exported:exportflag _ cached:cacheflag _ public:pubflag _ is_shared:shareflag _ name:identifier _ returns:returntype _ "=" _ expression:expression (_ ";")? { Rule{ name: name, expr: Box::new(expression), ret_type: returns, exported: public || legacy_exported, + shared: is_shared, cached: cached } } pubflag -> bool = PUB { true } / { false } + shareflag -> bool = SHARED { true } / { false } exportflag -> bool = #quiet<("#[export]" / "#[pub]") {true} / {false}> cacheflag -> bool = "#[cache]" {true} / {false} @@ -30,10 +32,14 @@ template -> Template Template { name: name, params: params, expr: Box::new(expression) } } +subgrammar -> Subgrammar + = IMPORT _ grammar_name:identifier converter:( _ THROUGH _ "{" _ code:rust_expr _ "}" { code })? { Subgrammar { name: grammar_name, converter: converter } } + item -> Item = u:rust_use { Item::Use(u) } / r:rule { Item::Rule(r) } / t:template { Item::Template(t) } + / s:subgrammar { Item::Subgrammar(s) } / grammar_args grammar_args -> Item @@ -148,9 +154,12 @@ repeatnum -> String #[cache] primary -> Spanned = spanned< - name:identifier !(_ ("<" / "->" / "=")) { + name:identifier !(_ ("<" / "->" / "=" / "::")) { RuleExpr(name) } + / grammar_name:identifier "::" rule_name:identifier { + SubgrammarRuleExpr(grammar_name, rule_name) + } / name:identifier _ "<" _ args:COMMASEP _ ">" !( _ "=") { TemplateInvoke(name, args) } @@ -189,8 +198,11 @@ nonBraceCharacters = [^{}]+ KEYWORD = k !([a-zA-Z0-9_]) USE = KEYWORD<"use"> PUB = KEYWORD<"pub"> +SHARED = KEYWORD<"shared"> +IMPORT = KEYWORD<"import"> +THROUGH = KEYWORD<"through"> -keyword = USE / PUB +keyword = USE / PUB / SHARED / IMPORT / THROUGH integer -> usize = i:$([0-9]+) { i.parse().unwrap() } diff --git a/src/translate.rs b/src/translate.rs index 7f11a9a..6eceffc 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -13,6 +13,7 @@ fn raw(s: &str) -> Tokens { pub(crate) struct Grammar { pub imports: Vec, + pub subgrammars : Vec, pub rules: Vec, pub templates: HashMap, pub args: Vec<(String, String)>, @@ -21,6 +22,7 @@ pub(crate) struct Grammar { impl Grammar { pub fn from_ast(compiler: &mut PegCompiler, items: Vec>) -> Result { let mut imports = Vec::new(); + let mut subgrammars : Vec = Vec::new(); let mut rules: Vec = Vec::new(); let mut templates = HashMap::new(); @@ -49,6 +51,17 @@ impl Grammar { ) } } + Item::Subgrammar(subgrammar) => { + if subgrammars.iter().any(|imported_grammar| imported_grammar.name == subgrammar.name) { + compiler.span_error( + format!("Subgrammar `{}` imported multiple times", subgrammar.name), + item.span, + Some("duplicate import".to_owned()) + ) + } + + subgrammars.push(subgrammar); + } Item::GrammarArgs(args) => { if grammar_args.is_none() { grammar_args = Some(args); @@ -63,7 +76,7 @@ impl Grammar { } } - Ok(Grammar{ imports:imports, rules:rules, templates:templates, args: grammar_args.unwrap_or(vec![]) }) + Ok(Grammar{ imports:imports, subgrammars:subgrammars, rules:rules, templates:templates, args: grammar_args.unwrap_or(vec![]) }) } fn find_rule(&self, name: &str) -> Option<&Rule> { @@ -92,6 +105,7 @@ pub enum Item { Use(String), Rule(Rule), Template(Template), + Subgrammar(Subgrammar), GrammarArgs(Vec<(String, String)>) } @@ -100,6 +114,7 @@ pub struct Rule { pub expr: Box>, pub ret_type: String, pub exported: bool, + pub shared: bool, pub cached: bool, } @@ -109,6 +124,11 @@ pub struct Template { pub expr: Box>, } +pub struct Subgrammar { + pub name: String, + pub converter: Option, +} + #[derive(Clone)] pub struct CharSetCase { pub start: char, @@ -127,6 +147,7 @@ pub enum Expr { LiteralExpr(String,bool), CharSetExpr(bool, Vec), RuleExpr(String), + SubgrammarRuleExpr(String, String), SequenceExpr(Vec>), ChoiceExpr(Vec>), OptionalExpr(Box>), @@ -610,6 +631,33 @@ fn compile_expr(compiler: &mut PegCompiler, cx: Context, e: &Spanned) -> T } } + SubgrammarRuleExpr(ref subgrammar_name, ref rule_name) => { + if let Some(ref subgrammar) = cx.grammar.subgrammars.iter().find(|ref sg| &sg.name == subgrammar_name) { + let func = raw(&format!("{}::__parse_{}", subgrammar_name, rule_name)); + let converter = subgrammar.converter.as_ref() + .map(|code| format!(", {}", code)) + .unwrap_or("".to_owned()); + + if cx.result_used { + quote!{ #func(__input, __state, __pos #converter) } + } else { + quote!{ + match #func(__input, __state, __pos #converter) { + Matched(pos, _) => Matched(pos, ()), + Failed => Failed, + } + } + } + } else { + compiler.span_error( + format!("No subgrammar named `{}` found", subgrammar_name), + e.span, + Some("subgrammar not found".to_owned()) + ); + quote!() + } + } + TemplateInvoke(ref name, ref params) => { let template = match cx.grammar.templates.get(&name[..]) { Some(x) => x, From f1211da442871e3bcb5ee4bf39c97b0572e12701 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Mon, 20 Nov 2017 23:38:20 +0000 Subject: [PATCH 2/6] Update grammar.rs with subgrammar changes. --- src/grammar.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/grammar.rs b/src/grammar.rs index 5d08640..4eda5d1 100644 --- a/src/grammar.rs +++ b/src/grammar.rs @@ -64,18 +64,21 @@ max_err_pos { self . max_err_pos = pos ; } } Failed } } struct ParseState < 'inp fn __parse_items < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Vec> > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = __parse__ ( __input , __state , __pos , file_span ) ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , start ) => { { let __seq_res = __parse_item ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , node ) => { { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , end ) => { Matched ( __pos , { codemap::Spanned { node, span: file_span.subspan(start as u64, end as u64) } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } Matched ( __repeat_pos , __repeat_value ) } ; match __seq_res { Matched ( __pos , items ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { items } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } - fn __parse_rule < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Rule > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = __parse_exportflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , legacy_exported ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_cacheflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , cached ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_pubflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , public ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , name ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_returntype ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , returns ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "=" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , expression ) => { { let __seq_res = match { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , ";" ) } Failed => Failed , } } { Matched ( __newpos , _ ) => { Matched ( __newpos , ( ) ) } , Failed => { Matched ( __pos , ( ) ) } , } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { + fn __parse_rule < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Rule > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = __parse_exportflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , legacy_exported ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_cacheflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , cached ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_pubflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , public ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_shareflag ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , is_shared ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , name ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_returntype ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , returns ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "=" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , expression ) => { { let __seq_res = match { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , ";" ) } Failed => Failed , } } { Matched ( __newpos , _ ) => { Matched ( __newpos , ( ) ) } , Failed => { Matched ( __pos , ( ) ) } , } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { Rule{ name: name, expr: Box::new(expression), ret_type: returns, exported: public || legacy_exported, + shared: is_shared, cached: cached } - } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } + } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } fn __parse_pubflag < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < bool > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = { let __seq_res = __parse_PUB ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { true } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => Matched ( __pos , { false } ) } } } + fn __parse_shareflag < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < bool > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = { let __seq_res = __parse_SHARED ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { true } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => Matched ( __pos , { false } ) } } } + fn __parse_exportflag < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < bool > { # ! [ allow ( non_snake_case , unused ) ] { __state . suppress_fail += 1 ; let res = { let __choice_res = { let __seq_res = { let __choice_res = slice_eq ( __input , __state , __pos , "#[export]" ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => slice_eq ( __input , __state , __pos , "#[pub]" ) } } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { true } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => Matched ( __pos , { false } ) } } ; __state . suppress_fail -= 1 ; res } } fn __parse_cacheflag < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < bool > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#[cache]" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { true } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => Matched ( __pos , { false } ) } } } @@ -84,7 +87,9 @@ max_err_pos { self . max_err_pos = pos ; } } Failed } } struct ParseState < 'inp Template { name: name, params: params, expr: Box::new(expression) } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } - fn __parse_item < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Item > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = { let __seq_res = __parse_rust_use ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , u ) => { Matched ( __pos , { Item::Use(u) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_rule ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , r ) => { Matched ( __pos , { Item::Rule(r) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_template ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , t ) => { Matched ( __pos , { Item::Template(t) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => __parse_grammar_args ( __input , __state , __pos , file_span ) } } } } } } } + fn __parse_subgrammar < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Subgrammar > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = __parse_IMPORT ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , grammar_name ) => { { let __seq_res = match { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_THROUGH ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "{" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_rust_expr ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , code ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "}" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { code } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } { Matched ( __newpos , __value ) => { Matched ( __newpos , Some ( __value ) ) } , Failed => { Matched ( __pos , None ) } , } ; match __seq_res { Matched ( __pos , converter ) => { Matched ( __pos , { Subgrammar { name: grammar_name, converter: converter } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } + + fn __parse_item < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Item > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = { let __seq_res = __parse_rust_use ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , u ) => { Matched ( __pos , { Item::Use(u) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_rule ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , r ) => { Matched ( __pos , { Item::Rule(r) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_template ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , t ) => { Matched ( __pos , { Item::Template(t) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_subgrammar ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , s ) => { Matched ( __pos , { Item::Subgrammar(s) } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => __parse_grammar_args ( __input , __state , __pos , file_span ) } } } } } } } } } fn __parse_grammar_args < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Item > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = slice_eq ( __input , __state , __pos , "#![" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "arguments" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "(" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "," ) ; match __seq_res { Matched ( __pos , _ ) => { __parse__ ( __input , __state , __pos , file_span ) } Failed => Failed , } } } Failed => Failed , } } ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = __parse_grammar_argument ( __input , __state , __pos , file_span ) ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } Matched ( __repeat_pos , __repeat_value ) } ; match __seq_res { Matched ( __pos , list ) => { { let __seq_res = match { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , "," ) } Failed => Failed , } } { Matched ( __newpos , _ ) => { Matched ( __newpos , ( ) ) } , Failed => { Matched ( __pos , ( ) ) } , } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { list } ) } Failed => Failed , } } } Failed => Failed , } } ; match __seq_res { Matched ( __pos , args ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ")" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "]" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { Item::GrammarArgs(args) } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } @@ -154,11 +159,13 @@ max_err_pos { self . max_err_pos = pos ; } } Failed } } struct ParseState < 'inp fn __parse_repeatnum < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < String > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = { let __seq_res = __parse_integer ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , i ) => { Matched ( __pos , { i.to_string() } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __seq_res = slice_eq ( __input , __state , __pos , "{" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_rust_expr ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , e ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "}" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { e } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } } } - fn __parse_primary < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Spanned > { # ! [ allow ( non_snake_case , unused ) ] if let Some ( entry ) = __state . primary_cache . get ( & __pos ) { return entry . clone ( ) ; } let __rule_result = { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , start ) => { { let __seq_res = { let __choice_res = { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , name ) => { { let __seq_res = { __state . suppress_fail += 1 ; let __assert_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __choice_res = slice_eq ( __input , __state , __pos , "<" ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = slice_eq ( __input , __state , __pos , "->" ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => slice_eq ( __input , __state , __pos , "=" ) } } } } } Failed => Failed , } } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { + fn __parse_primary < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Spanned > { # ! [ allow ( non_snake_case , unused ) ] if let Some ( entry ) = __state . primary_cache . get ( & __pos ) { return entry . clone ( ) ; } let __rule_result = { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , start ) => { { let __seq_res = { let __choice_res = { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , name ) => { { let __seq_res = { __state . suppress_fail += 1 ; let __assert_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __choice_res = slice_eq ( __input , __state , __pos , "<" ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = slice_eq ( __input , __state , __pos , "->" ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = slice_eq ( __input , __state , __pos , "=" ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => slice_eq ( __input , __state , __pos , "::" ) } } } } } } } Failed => Failed , } } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { RuleExpr(name) - } ) } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , name ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "<" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "," ) ; match __seq_res { Matched ( __pos , _ ) => { __parse__ ( __input , __state , __pos , file_span ) } Failed => Failed , } } } Failed => Failed , } } ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } Matched ( __repeat_pos , __repeat_value ) } ; match __seq_res { Matched ( __pos , list ) => { { let __seq_res = match { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , "," ) } Failed => Failed , } } { Matched ( __newpos , _ ) => { Matched ( __newpos , ( ) ) } , Failed => { Matched ( __pos , ( ) ) } , } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { list } ) } Failed => Failed , } } } Failed => Failed , } } ; match __seq_res { Matched ( __pos , args ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ">" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { __state . suppress_fail += 1 ; let __assert_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , "=" ) } Failed => Failed , } } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { + } ) } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , grammar_name ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "::" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , rule_name ) => { Matched ( __pos , { + SubgrammarRuleExpr(grammar_name, rule_name) + } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = __parse_identifier ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , name ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "<" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "," ) ; match __seq_res { Matched ( __pos , _ ) => { __parse__ ( __input , __state , __pos , file_span ) } Failed => Failed , } } } Failed => Failed , } } ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } Matched ( __repeat_pos , __repeat_value ) } ; match __seq_res { Matched ( __pos , list ) => { { let __seq_res = match { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , "," ) } Failed => Failed , } } { Matched ( __newpos , _ ) => { Matched ( __newpos , ( ) ) } , Failed => { Matched ( __pos , ( ) ) } , } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { list } ) } Failed => Failed , } } } Failed => Failed , } } ; match __seq_res { Matched ( __pos , args ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ">" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { __state . suppress_fail += 1 ; let __assert_res = { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { slice_eq ( __input , __state , __pos , "=" ) } Failed => Failed , } } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { TemplateInvoke(name, args) - } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_literal ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_class ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "." ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { AnyCharExpr } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#position" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { PositionExpr } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#quiet" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "<" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , e ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ">" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { QuietExpr(Box::new(e)) } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#expected" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "(" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_doubleQuotedString ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , s ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ")" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { FailExpr(s) } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#infix" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "<" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , atom ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ">" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "{" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = __parse__ ( __input , __state , __pos , file_span ) ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = __parse_infix_level ( __input , __state , __pos , file_span ) ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } if __repeat_value . len ( ) >= 1 { Matched ( __repeat_pos , __repeat_value ) } else { Failed } } ; match __seq_res { Matched ( __pos , levels ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "}" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { InfixExpr{ atom: Box::new(atom), levels:levels } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __seq_res = slice_eq ( __input , __state , __pos , "(" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , expression ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ")" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { expression.node } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } } } } } } } } } } } } } } } } } } ; match __seq_res { Matched ( __pos , node ) => { { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , end ) => { Matched ( __pos , { codemap::Spanned { node, span: file_span.subspan(start as u64, end as u64) } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; __state . primary_cache . insert ( __pos , __rule_result . clone ( ) ) ; __rule_result } + } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_literal ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_class ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "." ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { AnyCharExpr } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#position" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { PositionExpr } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#quiet" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "<" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , e ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ">" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { QuietExpr(Box::new(e)) } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#expected" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "(" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_doubleQuotedString ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , s ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ")" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { FailExpr(s) } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#infix" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "<" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , atom ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ">" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "{" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = __parse__ ( __input , __state , __pos , file_span ) ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = __parse_infix_level ( __input , __state , __pos , file_span ) ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } if __repeat_value . len ( ) >= 1 { Matched ( __repeat_pos , __repeat_value ) } else { Failed } } ; match __seq_res { Matched ( __pos , levels ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , "}" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { InfixExpr{ atom: Box::new(atom), levels:levels } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __seq_res = slice_eq ( __input , __state , __pos , "(" ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = __parse_expression ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , expression ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = slice_eq ( __input , __state , __pos , ")" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { expression.node } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } } } } } } } } } } } } } } } } } } } } ; match __seq_res { Matched ( __pos , node ) => { { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , end ) => { Matched ( __pos , { codemap::Spanned { node, span: file_span.subspan(start as u64, end as u64) } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; __state . primary_cache . insert ( __pos , __rule_result . clone ( ) ) ; __rule_result } fn __parse_infix_level < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < InfixLevel > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = { let __choice_res = { let __seq_res = slice_eq ( __input , __state , __pos , "#L" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { InfixAssoc::Left } ) } Failed => Failed , } } ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __seq_res = slice_eq ( __input , __state , __pos , "#R" ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { InfixAssoc::Right } ) } Failed => Failed , } } } } ; match __seq_res { Matched ( __pos , assoc ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = __parse__ ( __input , __state , __pos , file_span ) ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = __parse_infix_op ( __input , __state , __pos , file_span ) ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } if __repeat_value . len ( ) >= 1 { Matched ( __repeat_pos , __repeat_value ) } else { Failed } } ; match __seq_res { Matched ( __pos , operators ) => { Matched ( __pos , { InfixLevel{ assoc: assoc, operators: operators} } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } @@ -178,7 +185,13 @@ max_err_pos { self . max_err_pos = pos ; } } Failed } } struct ParseState < 'inp fn __parse_PUB < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < () > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = slice_eq ( __input , __state , __pos , "pub" ) ; match __seq_res { Matched ( __pos , _ ) => { { __state . suppress_fail += 1 ; let __assert_res = if __input . len ( ) > __pos { let ( __ch , __next ) = char_range_at ( __input , __pos ) ; match __ch { 'a' ... 'z' | 'A' ... 'Z' | '0' ... '9' | '_' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) , } } else { __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } } Failed => Failed , } } } - fn __parse_keyword < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < () > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = __parse_USE ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => __parse_PUB ( __input , __state , __pos , file_span ) } } } + fn __parse_SHARED < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < () > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = slice_eq ( __input , __state , __pos , "shared" ) ; match __seq_res { Matched ( __pos , _ ) => { { __state . suppress_fail += 1 ; let __assert_res = if __input . len ( ) > __pos { let ( __ch , __next ) = char_range_at ( __input , __pos ) ; match __ch { 'a' ... 'z' | 'A' ... 'Z' | '0' ... '9' | '_' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) , } } else { __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } } Failed => Failed , } } } + + fn __parse_IMPORT < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < () > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = slice_eq ( __input , __state , __pos , "import" ) ; match __seq_res { Matched ( __pos , _ ) => { { __state . suppress_fail += 1 ; let __assert_res = if __input . len ( ) > __pos { let ( __ch , __next ) = char_range_at ( __input , __pos ) ; match __ch { 'a' ... 'z' | 'A' ... 'Z' | '0' ... '9' | '_' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) , } } else { __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } } Failed => Failed , } } } + + fn __parse_THROUGH < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < () > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = slice_eq ( __input , __state , __pos , "through" ) ; match __seq_res { Matched ( __pos , _ ) => { { __state . suppress_fail += 1 ; let __assert_res = if __input . len ( ) > __pos { let ( __ch , __next ) = char_range_at ( __input , __pos ) ; match __ch { 'a' ... 'z' | 'A' ... 'Z' | '0' ... '9' | '_' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) , } } else { __state . mark_failure ( __pos , "[a-zA-Z0-9_]" ) } ; __state . suppress_fail -= 1 ; match __assert_res { Failed => Matched ( __pos , ( ) ) , Matched ( .. ) => Failed , } } } Failed => Failed , } } } + + fn __parse_keyword < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < () > { # ! [ allow ( non_snake_case , unused ) ] { let __choice_res = __parse_USE ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_PUB ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_SHARED ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => { let __choice_res = __parse_IMPORT ( __input , __state , __pos , file_span ) ; match __choice_res { Matched ( __pos , __value ) => Matched ( __pos , __value ) , Failed => __parse_THROUGH ( __input , __state , __pos , file_span ) } } } } } } } } } fn __parse_integer < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < usize > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = { let str_start = __pos ; match { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __step_res = if __input . len ( ) > __pos { let ( __ch , __next ) = char_range_at ( __input , __pos ) ; match __ch { '0' ... '9' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[0-9]" ) , } } else { __state . mark_failure ( __pos , "[0-9]" ) } ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } if __repeat_value . len ( ) >= 1 { Matched ( __repeat_pos , ( ) ) } else { Failed } } { Matched ( __newpos , _ ) => { Matched ( __newpos , & __input [ str_start .. __newpos ] ) } , Failed => Failed , } } ; match __seq_res { Matched ( __pos , i ) => { Matched ( __pos , { i.parse().unwrap() } ) } Failed => Failed , } } } From b1c7eb4599b93a1e81d306df1a74778ef8235c2e Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Mon, 20 Nov 2017 23:56:05 +0000 Subject: [PATCH 3/6] Added shared pub mod and fixed fn calls. --- src/translate.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/translate.rs b/src/translate.rs index 6eceffc..a207c37 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -405,6 +405,11 @@ fn compile_rule(compiler: &mut PegCompiler, grammar: &Grammar, rule: &Rule) -> T let nl = raw("\n\n"); // make output slightly more readable let extra_args_def = grammar.extra_args_def(); + let shared = if rule.shared { + raw("pub(crate)") + } else { + raw("") + }; if rule.cached { let cache_field = raw(&format!("{}_cache", rule.name)); @@ -422,7 +427,7 @@ fn compile_rule(compiler: &mut PegCompiler, grammar: &Grammar, rule: &Rule) -> T }; quote! { #nl - fn #name<'input>(__input: &'input str, __state: &mut ParseState<'input>, __pos: usize #extra_args_def) -> RuleResult<#ret_ty> { + #shared fn #name<'input>(__input: &'input str, __state: &mut ParseState<'input>, __pos: usize #extra_args_def) -> RuleResult<#ret_ty> { #![allow(non_snake_case, unused)] if let Some(entry) = __state.#cache_field.get(&__pos) { #cache_trace @@ -435,7 +440,7 @@ fn compile_rule(compiler: &mut PegCompiler, grammar: &Grammar, rule: &Rule) -> T } } else { quote! { #nl - fn #name<'input>(__input: &'input str, __state: &mut ParseState<'input>, __pos: usize #extra_args_def) -> RuleResult<#ret_ty> { + #shared fn #name<'input>(__input: &'input str, __state: &mut ParseState<'input>, __pos: usize #extra_args_def) -> RuleResult<#ret_ty> { #![allow(non_snake_case, unused)] #wrapped_body } @@ -633,10 +638,10 @@ fn compile_expr(compiler: &mut PegCompiler, cx: Context, e: &Spanned) -> T SubgrammarRuleExpr(ref subgrammar_name, ref rule_name) => { if let Some(ref subgrammar) = cx.grammar.subgrammars.iter().find(|ref sg| &sg.name == subgrammar_name) { - let func = raw(&format!("{}::__parse_{}", subgrammar_name, rule_name)); + let func = raw(&format!("super::{}::__parse_{}", subgrammar_name, rule_name)); let converter = subgrammar.converter.as_ref() - .map(|code| format!(", {}", code)) - .unwrap_or("".to_owned()); + .map(|code| raw(&format!(", {}", code))) + .unwrap_or(raw("")); if cx.result_used { quote!{ #func(__input, __state, __pos #converter) } From cac92b141fc11198930e851e6360f45195984a33 Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Wed, 22 Nov 2017 00:07:09 +0000 Subject: [PATCH 4/6] Added ParseState conversion helper for subgrammar use. --- src/translate.rs | 50 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/translate.rs b/src/translate.rs index a207c37..0d62b82 100644 --- a/src/translate.rs +++ b/src/translate.rs @@ -201,7 +201,7 @@ static HELPERS: &'static str = stringify! { } #[derive(Clone)] - enum RuleResult { + pub enum RuleResult { Matched(usize, T), Failed, } @@ -349,25 +349,40 @@ fn make_parse_state(rules: &[Rule]) -> Tokens { } } + let cache_field_new = cache_fields.iter(); + let cache_field_from = cache_fields.iter(); + quote! { - struct ParseState<'input> { - max_err_pos: usize, - suppress_fail: usize, - reparsing_on_error: bool, - expected: ::std::collections::HashSet<&'static str>, + pub(crate) struct ParseState<'input> { + pub max_err_pos: usize, + pub suppress_fail: usize, + pub reparsing_on_error: bool, + pub expected: ::std::collections::HashSet<&'static str>, _phantom: ::std::marker::PhantomData<&'input ()>, #(#cache_fields_def),* } impl<'input> ParseState<'input> { + pub fn from(max_err_pos: usize, suppress_fail: usize, reparsing_on_error: bool, expected: &::std::collections::HashSet<&'static str>) -> ParseState<'input> { + #![allow(unused)] + ParseState { + max_err_pos: max_err_pos, + suppress_fail: suppress_fail, + reparsing_on_error: reparsing_on_error, + expected: expected.clone(), + _phantom: ::std::marker::PhantomData, + #(#cache_field_from: ::std::collections::HashMap::new()),* + } + } fn new() -> ParseState<'input> { + #![allow(unused)] ParseState { max_err_pos: 0, suppress_fail: 0, reparsing_on_error: false, expected: ::std::collections::HashSet::new(), _phantom: ::std::marker::PhantomData, - #(#cache_fields: ::std::collections::HashMap::new()),* + #(#cache_field_new: ::std::collections::HashMap::new()),* } } } @@ -639,17 +654,30 @@ fn compile_expr(compiler: &mut PegCompiler, cx: Context, e: &Spanned) -> T SubgrammarRuleExpr(ref subgrammar_name, ref rule_name) => { if let Some(ref subgrammar) = cx.grammar.subgrammars.iter().find(|ref sg| &sg.name == subgrammar_name) { let func = raw(&format!("super::{}::__parse_{}", subgrammar_name, rule_name)); + let subgrammar_module = raw(subgrammar_name); let converter = subgrammar.converter.as_ref() .map(|code| raw(&format!(", {}", code))) .unwrap_or(raw("")); + let subgrammar_path = quote!{ super::#subgrammar_module }; + + let state_conversion = + quote! { + &mut #subgrammar_path::ParseState::from( + __state.max_err_pos, + __state.suppress_fail, + __state.reparsing_on_error, + &__state.expected + ) + }; + if cx.result_used { - quote!{ #func(__input, __state, __pos #converter) } + quote!{ #func(__input, #state_conversion, __pos #converter) } } else { quote!{ - match #func(__input, __state, __pos #converter) { - Matched(pos, _) => Matched(pos, ()), - Failed => Failed, + match #func(__input, #state_conversion, __pos #converter) { + #subgrammar_path::RuleResult::Matched(pos, _) => Matched(pos, ()), + #subgrammar_path::RuleResult::Failed => Failed, } } } From 46056c94f234f219fe4b01458fdfeb803a49034c Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Wed, 22 Nov 2017 00:07:22 +0000 Subject: [PATCH 5/6] Updated grammar.rs --- src/grammar.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/grammar.rs b/src/grammar.rs index 4eda5d1..9f506e3 100644 --- a/src/grammar.rs +++ b/src/grammar.rs @@ -3,7 +3,7 @@ use self :: RuleResult :: { Matched , Failed } ; use translate::*; use std::char s . chars ( ) . flat_map ( | c | c . escape_default ( ) ) . collect ( ) } fn char_range_at ( s : & str , pos : usize ) -> ( char , usize ) { let c = & s [ pos .. ] . chars ( ) . next ( ) . unwrap ( ) ; let next_pos = -pos + c . len_utf8 ( ) ; ( * c , next_pos ) } # [ derive ( Clone ) ] enum +pos + c . len_utf8 ( ) ; ( * c , next_pos ) } # [ derive ( Clone ) ] pub enum RuleResult < T > { Matched ( usize , T ) , Failed , } # [ derive ( PartialEq , Eq , Debug , Clone ) ] pub struct ParseError { pub line : usize , pub column : usize , pub offset : usize , pub expected : :: @@ -60,7 +60,7 @@ inline ( always ) ] fn mark_failure ( if self . suppress_fail == 0 { if self . reparsing_on_error { self . mark_failure_slow_path ( pos , expected ) ; } else if pos > self . -max_err_pos { self . max_err_pos = pos ; } } Failed } } struct ParseState < 'input > { max_err_pos : usize , suppress_fail : usize , reparsing_on_error : bool , expected : :: std :: collections :: HashSet < & 'static str > , _phantom : :: std :: marker :: PhantomData < & 'input ( ) > , primary_cache : :: std :: collections :: HashMap < usize , RuleResult < Spanned >> } impl < 'input > ParseState < 'input > { fn new ( ) -> ParseState < 'input > { ParseState { max_err_pos : 0 , suppress_fail : 0 , reparsing_on_error : false , expected : :: std :: collections :: HashSet :: new ( ) , _phantom : :: std :: marker :: PhantomData , primary_cache : :: std :: collections :: HashMap :: new ( ) } } } +max_err_pos { self . max_err_pos = pos ; } } Failed } } pub ( crate ) struct ParseState < 'input > { pub max_err_pos : usize , pub suppress_fail : usize , pub reparsing_on_error : bool , pub expected : :: std :: collections :: HashSet < & 'static str > , _phantom : :: std :: marker :: PhantomData < & 'input ( ) > , primary_cache : :: std :: collections :: HashMap < usize , RuleResult < Spanned >> } impl < 'input > ParseState < 'input > { pub fn from ( max_err_pos : usize , suppress_fail : usize , reparsing_on_error : bool , expected : & :: std :: collections :: HashSet < & 'static str > ) -> ParseState < 'input > { # ! [ allow ( unused ) ] ParseState { max_err_pos : max_err_pos , suppress_fail : suppress_fail , reparsing_on_error : reparsing_on_error , expected : expected . clone ( ) , _phantom : :: std :: marker :: PhantomData , primary_cache : :: std :: collections :: HashMap :: new ( ) } } fn new ( ) -> ParseState < 'input > { # ! [ allow ( unused ) ] ParseState { max_err_pos : 0 , suppress_fail : 0 , reparsing_on_error : false , expected : :: std :: collections :: HashSet :: new ( ) , _phantom : :: std :: marker :: PhantomData , primary_cache : :: std :: collections :: HashMap :: new ( ) } } } fn __parse_items < 'input > ( __input : & 'input str , __state : & mut ParseState < 'input > , __pos : usize , file_span : codemap::Span ) -> RuleResult < Vec> > { # ! [ allow ( non_snake_case , unused ) ] { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! ( ) ; loop { let __pos = __repeat_pos ; let __pos = if __repeat_value . len ( ) > 0 { let __sep_res = __parse__ ( __input , __state , __pos , file_span ) ; match __sep_res { Matched ( __newpos , _ ) => { __newpos } , Failed => break , } } else { __pos } ; let __step_res = { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , start ) => { { let __seq_res = __parse_item ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , node ) => { { let __seq_res = Matched ( __pos , __pos ) ; match __seq_res { Matched ( __pos , end ) => { Matched ( __pos , { codemap::Spanned { node, span: file_span.subspan(start as u64, end as u64) } } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } ; match __step_res { Matched ( __newpos , __value ) => { __repeat_pos = __newpos ; __repeat_value . push ( __value ) ; } , Failed => { break ; } } } Matched ( __repeat_pos , __repeat_value ) } ; match __seq_res { Matched ( __pos , items ) => { { let __seq_res = __parse__ ( __input , __state , __pos , file_span ) ; match __seq_res { Matched ( __pos , _ ) => { Matched ( __pos , { items } ) } Failed => Failed , } } } Failed => Failed , } } } Failed => Failed , } } } From 3f66b26a9b190a83f661bc8ef812461f15b9102d Mon Sep 17 00:00:00 2001 From: Isaac van Bakel Date: Wed, 22 Nov 2017 00:20:40 +0000 Subject: [PATCH 6/6] Added tests to check subgrammar compilation Subgrammars without arguments are tested. Subgrammars with arguments using some converter are also tested. --- peg-tests/build.rs | 2 ++ peg-tests/src/test_grammar.rustpeg | 9 +++++++++ peg-tests/src/test_subgrammar.rustpeg | 3 +++ .../src/test_subgrammar_with_args.rustpeg | 4 ++++ peg-tests/src/tests.rs | 20 +++++++++++++++++++ 5 files changed, 38 insertions(+) create mode 100644 peg-tests/src/test_subgrammar.rustpeg create mode 100644 peg-tests/src/test_subgrammar_with_args.rustpeg diff --git a/peg-tests/build.rs b/peg-tests/build.rs index f625288..98ac6fd 100644 --- a/peg-tests/build.rs +++ b/peg-tests/build.rs @@ -1,5 +1,7 @@ extern crate peg; fn main() { + peg::cargo_build("src/test_subgrammar.rustpeg"); + peg::cargo_build("src/test_subgrammar_with_args.rustpeg"); peg::cargo_build("src/test_grammar.rustpeg"); } diff --git a/peg-tests/src/test_grammar.rustpeg b/peg-tests/src/test_grammar.rustpeg index fa0d183..bdc7e08 100644 --- a/peg-tests/src/test_grammar.rustpeg +++ b/peg-tests/src/test_grammar.rustpeg @@ -119,3 +119,12 @@ issue152 -> i32 // a } pub error_pos = ("a" / "\n" / "\r")* + +import test_subgrammar + +pub subgrammar_rule = test_subgrammar::only_rule + +import test_subgrammar_with_args through { 5 } + +pub subgrammar_with_args_rule = test_subgrammar_with_args::repeater + diff --git a/peg-tests/src/test_subgrammar.rustpeg b/peg-tests/src/test_subgrammar.rustpeg new file mode 100644 index 0000000..a2d0f51 --- /dev/null +++ b/peg-tests/src/test_subgrammar.rustpeg @@ -0,0 +1,3 @@ +shared only_rule -> () + = "this is the only subgrammar rule" + diff --git a/peg-tests/src/test_subgrammar_with_args.rustpeg b/peg-tests/src/test_subgrammar_with_args.rustpeg new file mode 100644 index 0000000..4fdf288 --- /dev/null +++ b/peg-tests/src/test_subgrammar_with_args.rustpeg @@ -0,0 +1,4 @@ +#![arguments(my_arg: usize)] + +shared repeater -> () + = "a"*<{my_arg}> diff --git a/peg-tests/src/tests.rs b/peg-tests/src/tests.rs index 7bf794d..f3de4bd 100755 --- a/peg-tests/src/tests.rs +++ b/peg-tests/src/tests.rs @@ -6,6 +6,14 @@ mod test_grammar { include!(concat!(env!("OUT_DIR"), "/test_grammar.rs")); } +mod test_subgrammar { + include!(concat!(env!("OUT_DIR"), "/test_subgrammar.rs")); +} + +mod test_subgrammar_with_args { + include!(concat!(env!("OUT_DIR"), "/test_subgrammar_with_args.rs")); +} + use self::test_grammar::*; #[test] @@ -131,6 +139,16 @@ fn test_renamed_imports() { assert_eq!(renamed_imports("").unwrap(), (42, 42)); } +#[test] +fn test_subgrammar() { + assert!(subgrammar_rule("this is the only subgrammar rule").is_ok()) +} + +#[test] +fn test_subgrammar_with_args() { + assert!(subgrammar_with_args_rule("aaaaa").is_ok()) +} + #[test] fn test_neg_lookahead_err() { let err = neg_lookahead_err("ac").err().unwrap(); @@ -186,3 +204,5 @@ fn test_error_pos() { assert_eq!(err.line, 3); assert_eq!(err.column, 4); } + +