From da2317851e585a7c043ef979f78d36af03c2853d Mon Sep 17 00:00:00 2001 From: Taehwan Kim Date: Sat, 24 Aug 2024 19:54:00 +0900 Subject: [PATCH] add GLR Parser - bump version to 2.5.0 - add lookahead predefined variable to reduce action - add README about GLR parser - add(parser) %glr syntax - invalid non-terminal now returns InvalidTerminalError, no unreachable - add(core) Parser and Context trait - fix(core) add `allow_conflict` option to grammar builder --- Cargo.toml | 2 +- README.md | 72 +- example/glr/Cargo.toml | 7 + example/glr/src/main.rs | 44 + example/glr/src/parser.rs | 31 + rusty_lr/Cargo.toml | 12 +- rusty_lr/src/lib.rs | 65 +- rusty_lr_buildscript/Cargo.toml | 6 +- rusty_lr_core/Cargo.toml | 2 +- rusty_lr_core/src/builder/grammar.rs | 212 ++-- rusty_lr_core/src/builder/state.rs | 38 +- rusty_lr_core/src/glr/context.rs | 15 + rusty_lr_core/src/glr/error.rs | 155 +++ rusty_lr_core/src/glr/mod.rs | 152 +++ rusty_lr_core/src/glr/node.rs | 73 ++ rusty_lr_core/src/glr/parser.rs | 13 + rusty_lr_core/src/glr/state.rs | 101 ++ rusty_lr_core/src/lib.rs | 34 +- rusty_lr_core/src/lr/context.rs | 22 + rusty_lr_core/src/{ => lr}/error.rs | 43 +- rusty_lr_core/src/lr/mod.rs | 79 ++ rusty_lr_core/src/lr/parser.rs | 13 + rusty_lr_core/src/{ => lr}/state.rs | 5 +- rusty_lr_derive/Cargo.toml | 6 +- rusty_lr_executable/Cargo.toml | 6 +- rusty_lr_parser/Cargo.toml | 4 +- rusty_lr_parser/src/emit.rs | 711 ++++++++++--- rusty_lr_parser/src/grammar.rs | 7 + rusty_lr_parser/src/parser/args.rs | 1 + rusty_lr_parser/src/parser/lexer.rs | 8 + rusty_lr_parser/src/parser/parser.rs | 7 +- rusty_lr_parser/src/parser/parser_expanded.rs | 952 ++++++++---------- 32 files changed, 2012 insertions(+), 886 deletions(-) create mode 100644 example/glr/Cargo.toml create mode 100644 example/glr/src/main.rs create mode 100644 example/glr/src/parser.rs create mode 100644 rusty_lr_core/src/glr/context.rs create mode 100644 rusty_lr_core/src/glr/error.rs create mode 100644 rusty_lr_core/src/glr/mod.rs create mode 100644 rusty_lr_core/src/glr/node.rs create mode 100644 rusty_lr_core/src/glr/parser.rs create mode 100644 rusty_lr_core/src/glr/state.rs create mode 100644 rusty_lr_core/src/lr/context.rs rename rusty_lr_core/src/{ => lr}/error.rs (85%) create mode 100644 rusty_lr_core/src/lr/mod.rs create mode 100644 rusty_lr_core/src/lr/parser.rs rename rusty_lr_core/src/{ => lr}/state.rs (97%) diff --git a/Cargo.toml b/Cargo.toml index ee3f1f0..f70ea4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,5 @@ members = [ "rusty_lr_executable", "example/calculator", "example/calculator_u8", - "example/lrtest", + "example/lrtest", "example/glr", ] diff --git a/README.md b/README.md index 8e66036..8eb9f81 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ [![crates.io](https://img.shields.io/crates/v/rusty_lr.svg)](https://crates.io/crates/rusty_lr) [![docs.rs](https://docs.rs/rusty_lr/badge.svg)](https://docs.rs/rusty_lr) -yacc-like LR(1) and LALR(1) Deterministic Finite Automata (DFA) generator from Context Free Grammar (CFGs). +GLR, LR(1) and LALR(1) parser generator for Rust. -RustyLR provides [procedural macros](#proc-macro) and [buildscript tools](#integrating-with-buildrs) to generate LR(1) and LALR(1) parser. +RustyLR provides [procedural macros](#proc-macro) and [buildscript tools](#integrating-with-buildrs) to generate GLR, LR(1) and LALR(1) parser. The generated parser will be a pure Rust code, and the calculation of building DFA will be done at compile time. -Reduce action can be written in Rust code, +Reduce action can be written in Rust, and the error messages are [readable and detailed](#readable-error-messages-with-codespan). For huge and complex grammars, it is recommended to use the [buildscipt](#integrating-with-buildrs). @@ -125,7 +125,7 @@ println!("userdata: {}", userdata); - [Proc-macro](#proc-macro) - [Integrating with `build.rs`](#integrating-with-buildrs) - [Start Parsing](#start-parsing) - - [Error Handling](#error-handling) + - [GLR Parser](#glr-parser) - [Syntax](#syntax) @@ -234,32 +234,30 @@ for token in input_sequence { let start_symbol_value = context.accept(); ``` -## Error Handling -There are two error variants returned from `feed()` function: - - `InvalidTerminal(InvalidTerminalError)` : when invalid terminal symbol is fed - - `ReduceAction(ReduceActionError)` : when the reduce action returns `Err(Error)` - -For `ReduceActionError`, the error type can be defined by [`%err`](#error-type-optional) directive. If not defined, `DefaultReduceActionError` will be used. - -When printing the error message, there are two ways to get the error message: - - `e.long_message( &parser, &context )` : get the error message as `String`, in a detailed format - - `e as Display` : briefly print the short message through `Display` trait. - -The `long_message` function requires the reference to the parser and the context. -It will make a detailed error message of what current state was trying to parse, and what the expected terminal symbols were. -### Example of long_message +## GLR Parser +The GLR (Generalized LR parser) can be generated by `%glr;` directive in the grammar. ``` -Invalid Terminal: *. Expected one of: , (, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ->>> In: - M -> M * • M ->>> Backtrace: - M -> M • * M ->>> Backtrace: - A -> A + • A ->>> Backtrace: - A -> A • + A +// generate GLR parser; +// from now on, shift/reduce, reduce/reduce conflicts will not be treated as errors +%glr; +... ``` +GLR parser can handle ambiguous grammars that LR(1) or LALR(1) parser cannot. +When it encounters any kind of conflict during parsing, +the parser will diverge into multiple states, and will try every paths until it fails. +Of course, there must be single unique path left at the end of parsing (the point where you feed `eof` token). +### Resolving Ambiguities +You can resolve the ambiguties through the [reduce action](#reduceaction-optional). +Simply, returning `Result::Err(Error)` from the reduce action will revoke current path. +The `Error` variant type can be defined by [`%err`](#error-type-optional) directive. + +### Note on GLR Parser + - Still in development, not have been tested enough (patches are welcome!). + - Since there are multiple paths, the reduce action can be called multiple times, even if the result will be thrown away in the future. + - Every `RuleType` and `Term` must implement `Clone` trait. + - User must be aware of the point where shift/reduce or reduce/reduce conflicts occur. + Every time the parser diverges, the calculation cost will increase. ## Syntax To start writing down a context-free grammar, you need to define necessary directives first. @@ -301,6 +299,7 @@ Every line in the macro must follow the syntax below. - [`%err`, `%error`](#error-type-optional) - [`%derive`](#derive-optional) - [`%derive`](#derive-optional) + - [`%glr`](#glr-parser-generation) --- @@ -409,7 +408,8 @@ A(i32): ... ; ### Accessing token data in ReduceAction **predefined variables** can be used in `ReduceAction`: - - `data` : userdata passed to `feed()` function. + - `data` ( `&mut UserData` ) : userdata passed to the `feed()` function. + - `lookahead` ( `&Term` ) : lookahead token that caused the reduce action. To access the data of each token, you can directly use the name of the token as a variable. - For non-terminal symbols, the type of variable is `RuleType`. @@ -682,4 +682,18 @@ let mut context = parser.begin(); println!( "{:?}", context ); // debug-print context let cloned_context = context.clone(); // clone context, you can re-feed the input sequence using cloned context -``` \ No newline at end of file +``` + + +--- + +### GLR parser generation +``` +%glr; +``` +Swith to GLR parser generation. + +If you want to generate GLR parser, add `%glr;` directive in the grammar. +With this directive, any Shift/Reduce, Reduce/Reduce conflicts will not be treated as errors. + +See [GLR Parser](#glr-parser) section for more details. diff --git a/example/glr/Cargo.toml b/example/glr/Cargo.toml new file mode 100644 index 0000000..4974972 --- /dev/null +++ b/example/glr/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "glr" +version = "0.1.0" +edition = "2021" + +[dependencies] +rusty_lr = { path = "../../rusty_lr", features = ["fxhash"] } diff --git a/example/glr/src/main.rs b/example/glr/src/main.rs new file mode 100644 index 0000000..4ef4395 --- /dev/null +++ b/example/glr/src/main.rs @@ -0,0 +1,44 @@ +pub mod parser; +// pub mod parser_expanded; + +fn main() { + let p = parser::EParser::new(); + let mut c = p.begin(); + + let input = "1+2*3+4"; + for ch in input.chars() { + println!("feed: {}", ch); + match p.feed(&mut c, ch) { + Ok(_) => { + println!("nodes: {}", c.current_nodes.nodes.len()); + } + Err(e) => { + println!("Error: {:?}", e); + break; + } + } + } + println!("feed eof"); + match p.feed(&mut c, '\0') { + Ok(_) => { + println!("nodes: {}", c.current_nodes.nodes.len()); + } + Err(e) => { + println!("Error: {:?}", e); + } + } + + println!("{}", c.accept()); + + // for mut n in c.current_nodes.nodes.into_iter() { + // loop { + // println!("{}", n.state()); + // if let Some(par) = n.parent() { + // n = std::rc::Rc::clone(par); + // } else { + // break; + // } + // } + // println!("---"); + // } +} diff --git a/example/glr/src/parser.rs b/example/glr/src/parser.rs new file mode 100644 index 0000000..856419b --- /dev/null +++ b/example/glr/src/parser.rs @@ -0,0 +1,31 @@ +use rusty_lr::lr1; + +lr1! { + %glr; + %tokentype char; + %start E; + %eof '\0'; + + %left [plus star]; + + %token plus '+'; + %token star '*'; + %token zero '0'; + %token one '1'; + %token two '2'; + %token three '3'; + %token four '4'; + %token five '5'; + %token six '6'; + %token seven '7'; + %token eight '8'; + %token nine '9'; + + Digit(char): ch=[zero-nine] { println!("Digit: {}", ch); ch }; + + E(i32) : E plus e2=E { println!("Plus"); E + e2 } + | E star e2=E { println!("Star"); E * e2 } + | Digit { println!("D2E"); Digit as i32 - '0' as i32 } + ; + +} diff --git a/rusty_lr/Cargo.toml b/rusty_lr/Cargo.toml index 2813135..36c9652 100644 --- a/rusty_lr/Cargo.toml +++ b/rusty_lr/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "rusty_lr" -version = "2.4.0" +version = "2.5.0" edition = "2021" license = "MIT" -description = "yacc-like, LR(1) and LALR(1) parser generator with custom reduce action" +description = "GLR, LR(1) and LALR(1) parser generator with custom reduce action" repository = "https://github.com/ehwan/RustyLR" readme = "../README.md" -keywords = ["parser", "yacc", "context-free-grammar", "lr", "compiler"] +keywords = ["parser", "bison", "context-free-grammar", "lr", "compiler"] categories = ["parsing", "compilers", "parser-implementations"] [dependencies] -rusty_lr_core = "2.4" -rusty_lr_derive = "1.11" -rusty_lr_buildscript = { version = "0.6", optional = true } +rusty_lr_core = "2.5" +rusty_lr_derive = "1.12" +rusty_lr_buildscript = { version = "0.7", optional = true } # rusty_lr_core = { path = "../rusty_lr_core" } # rusty_lr_derive = { path = "../rusty_lr_derive" } # rusty_lr_buildscript = { path = "../rusty_lr_buildscript", optional = true } diff --git a/rusty_lr/src/lib.rs b/rusty_lr/src/lib.rs index 5a822ef..e5f1f98 100644 --- a/rusty_lr/src/lib.rs +++ b/rusty_lr/src/lib.rs @@ -1,9 +1,9 @@ //! # RustyLR -//! yacc-like LR(1) and LALR(1) Deterministic Finite Automata (DFA) generator from Context Free Grammar (CFGs). +//! GLR, LR(1) and LALR(1) parser generator for Rust. //! -//! RustyLR provides [procedural macros](#proc-macro) and [buildscript tools](#integrating-with-buildrs) to generate LR(1) and LALR(1) parser. +//! RustyLR provides [procedural macros](#proc-macro) and [buildscript tools](#integrating-with-buildrs) to generate GLR, LR(1) and LALR(1) parser. //! The generated parser will be a pure Rust code, and the calculation of building DFA will be done at compile time. -//! Reduce action can be written in Rust code, +//! Reduce action can be written in Rust, //! and the error messages are **readable and detailed**. //! For huge and complex grammars, it is recommended to use the [buildscipt](#integrating-with-buildrs). //! @@ -27,11 +27,11 @@ //! //! These macros will generate structs: //! - `Parser` : contains DFA tables and production rules -//! - [`ParseError`] : type alias for `Error` returned from `feed()` +//! - `ParseError` : type alias for `Error` returned from `feed()` //! - `Context` : contains current state and data stack //! - `enum NonTerminals` : a list of non-terminal symbols //! - [`Rule`](`ProductionRule`) : type alias for production rules -//! - [`State`] : type alias for DFA states +//! - `State` : type alias for DFA states //! //! All structs above are prefixed by ``. //! In most cases, what you want is the `Parser` and `ParseError` structs, and the others are used internally. @@ -125,31 +125,34 @@ //! let start_symbol_value = context.accept(); //! ``` //! -//! ## Error Handling -//! There are two error variants returned from `feed()` function: -//! - `InvalidTerminal(InvalidTerminalError)` : when invalid terminal symbol is fed -//! - `ReduceAction(ReduceActionError)` : when the reduce action returns `Err(Error)` -//! -//! For `ReduceActionError`, the error type can be defined by [`%err`](#error-type-optional) directive. If not defined, `String` will be used. -//! -//! When printing the error message, there are two ways to get the error message: -//! - `e.long_message( &parser, &context )` : get the error message as `String`, in a detailed format -//! - `e as Display` : briefly print the short message through `Display` trait. -//! -//! The `long_message` function requires the reference to the parser and the context. -//! It will make a detailed error message of what current state was trying to parse, and what the expected terminal symbols were. -//! ### Example of long_message -//! ```text -//! Invalid Terminal: *. Expected one of: , (, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 -//! >>> In: -//! M -> M * • M -//! >>> Backtrace: -//! M -> M • * M -//! >>> Backtrace: -//! A -> A + • A -//! >>> Backtrace: -//! A -> A • + A +//! +//! +//! ## GLR Parser +//! The GLR (Generalized LR parser) can be generated by `%glr;` directive in the grammar. //! ``` +//! // generate GLR parser; +//! // from now on, shift/reduce, reduce/reduce conflicts will not be treated as errors +//! %glr; +//! ... +//! ``` +//! GLR parser can handle ambiguous grammars that LR(1) or LALR(1) parser cannot. +//! When it encounters any kind of conflict during parsing, +//! the parser will diverge into multiple states, and will try every paths until it fails. +//! Of course, there must be single unique path left at the end of parsing (the point where you feed `eof` token). +//! +//! ### Resolving Ambiguities +//! You can resolve the ambiguties through the reduce action. +//! Simply, returning `Result::Err(Error)` from the reduce action will revoke current path. +//! The `Error` variant type can be defined by `%err` directive. +//! +//! ### Note on GLR Parser +//! - Still in development, not have been tested enough (patches are welcome!). +//! - Since there are multiple paths, the reduce action can be called multiple times, even if the result will be thrown away in the future. +//! - Every `RuleType` and `Term` must implement `Clone` trait. +//! - User must be aware of the point where shift/reduce or reduce/reduce conflicts occur. +//! Every time the parser diverges, the calculation cost will increase. +//! +//! //! //! ## Syntax //! To start writing down a context-free grammar, you need to define necessary directives first. @@ -168,8 +171,8 @@ //! } //! ``` //! -//! `lr1!` macro will generate a parser struct with LR(1) DFA tables. -//! If you want to generate LALR(1) parser, use `lalr1!` macro. +//! [`lr1!`] macro will generate a parser struct with LR(1) DFA tables. +//! If you want to generate LALR(1) parser, use [`lalr1!`] macro. //! Every line in the macro must follow the syntax below. //! //! Syntax can be found in [repository](https://github.com/ehwan/RustyLR/tree/main?tab=readme-ov-file#syntax). diff --git a/rusty_lr_buildscript/Cargo.toml b/rusty_lr_buildscript/Cargo.toml index 1162a46..c7db9f3 100644 --- a/rusty_lr_buildscript/Cargo.toml +++ b/rusty_lr_buildscript/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty_lr_buildscript" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "MIT" description = "buildscipt tools for rusty_lr" @@ -14,7 +14,7 @@ categories = ["parsing"] proc-macro2 = { version = "1.0.86", features = ["span-locations"] } quote = "1.0" # rusty_lr_parser = { path = "../rusty_lr_parser" } -rusty_lr_parser = "3.9" +rusty_lr_parser = "3.10" # rusty_lr_core = { path = "../rusty_lr_core", features = ["fxhash", "builder"] } -rusty_lr_core = { version = "2.4", features = ["fxhash", "builder"] } +rusty_lr_core = { version = "2.5", features = ["fxhash", "builder"] } codespan-reporting = "0.11" diff --git a/rusty_lr_core/Cargo.toml b/rusty_lr_core/Cargo.toml index a7d8f9e..8b6ed71 100644 --- a/rusty_lr_core/Cargo.toml +++ b/rusty_lr_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty_lr_core" -version = "2.4.0" +version = "2.5.0" edition = "2021" license = "MIT" description = "core library for rusty_lr" diff --git a/rusty_lr_core/src/builder/grammar.rs b/rusty_lr_core/src/builder/grammar.rs index cbb59bc..b7d84ee 100644 --- a/rusty_lr_core/src/builder/grammar.rs +++ b/rusty_lr_core/src/builder/grammar.rs @@ -26,6 +26,11 @@ pub struct Grammar { /// rules for each nonterminals rules_map: HashMap>, + + /// if true, allow any kind of conflict. + /// this option is for GLR parser. + /// conflict resolving through `reduce_types` is still applied. + allow_conflict: bool, } impl Grammar { @@ -35,9 +40,14 @@ impl Grammar { firsts: Default::default(), reduce_types: Default::default(), rules_map: Default::default(), + allow_conflict: false, } } + pub fn allow_conflict(&mut self) { + self.allow_conflict = true; + } + /// add new production rule for given nonterminal 'name' pub fn add_rule(&mut self, name: NonTerm, rule: Vec>) -> usize where @@ -376,6 +386,8 @@ impl Grammar { if next_rules_term.contains_key(&lookahead) { // shift/reduce conflict may occur here, check reduce type + // note that conflict resolving through `reduce_types` is still applied + // even if `allow_conflict` is set to true match self.reduce_types.get(&lookahead) { Some(ReduceType::Left) => { // reduce first @@ -384,20 +396,18 @@ impl Grammar { next_rules_term.remove(&lookahead); // check for reduce/reduce conflict - if let Some(old) = state.reduce_map.get_mut(&lookahead) { - // same rule, continue - if old == &empty_rule { - continue; - } - - // conflict + let reduce_ruleset = + state.reduce_map.entry(lookahead.clone()).or_default(); + reduce_ruleset.insert(empty_rule); + if !self.allow_conflict && reduce_ruleset.len() > 1 { + let mut iter = reduce_ruleset.iter(); + let rule1 = *iter.next().unwrap(); + let rule2 = *iter.next().unwrap(); return Err(BuildError::ReduceReduceConflict { lookahead, - rule1: *old, - rule2: empty_rule, + rule1, + rule2, }); - } else { - state.reduce_map.insert(lookahead, empty_rule); } } Some(ReduceType::Right) => { @@ -408,44 +418,49 @@ impl Grammar { None => { // shift/reduce error - // next_rules_term has set of rules that is already shifted. - // so shift -= 1 again to get the rule that is not shifted yet - let shifted_rules: BTreeMap<_, _> = next_rules_term[&lookahead] - .rules - .iter() - .map(|(rule_ref, lookaheads)| { - let mut rule_ref = *rule_ref; - rule_ref.shifted -= 1; - (rule_ref, lookaheads.clone()) - }) - .collect(); - - return Err(BuildError::ShiftReduceConflict { - reduce: empty_rule, - shift: LookaheadRuleRefSet { - rules: shifted_rules, - }, - term: lookahead.clone(), - }); + if self.allow_conflict { + state + .reduce_map + .entry(lookahead.clone()) + .or_default() + .insert(empty_rule); + } else { + // next_rules_term has set of rules that is already shifted. + // so shift -= 1 again to get the rule that is not shifted yet + let shifted_rules: BTreeMap<_, _> = next_rules_term[&lookahead] + .rules + .iter() + .map(|(rule_ref, lookaheads)| { + let mut rule_ref = *rule_ref; + rule_ref.shifted -= 1; + (rule_ref, lookaheads.clone()) + }) + .collect(); + + return Err(BuildError::ShiftReduceConflict { + reduce: empty_rule, + shift: LookaheadRuleRefSet { + rules: shifted_rules, + }, + term: lookahead.clone(), + }); + } } } } else { // no shift/reduce conflict // check for reduce/reduce conflict - if let Some(old) = state.reduce_map.get_mut(&lookahead) { - // same rule, continue - if old == &empty_rule { - continue; - } - - // conflict + let reduce_ruleset = state.reduce_map.entry(lookahead.clone()).or_default(); + reduce_ruleset.insert(empty_rule); + if !self.allow_conflict && reduce_ruleset.len() > 1 { + let mut iter = reduce_ruleset.iter(); + let rule1 = *iter.next().unwrap(); + let rule2 = *iter.next().unwrap(); return Err(BuildError::ReduceReduceConflict { lookahead, - rule1: *old, - rule2: empty_rule, + rule1, + rule2, }); - } else { - state.reduce_map.insert(lookahead, empty_rule); } } } @@ -454,27 +469,6 @@ impl Grammar { // process next rules with token // add shift and goto action for (next_term, next_rule_set) in next_rules_term.into_iter() { - // check for shift/reduce conflict again - if states[state_id].reduce_map.contains_key(next_term) { - match self.reduce_types.get(next_term) { - Some(ReduceType::Left) => { - // reduce first - continue; - } - Some(ReduceType::Right) => { - states[state_id].reduce_map.remove(next_term); - } - None => { - // shift/reduce error - return Err(BuildError::ShiftReduceConflict { - reduce: states[state_id].reduce_map[next_term], - shift: next_rule_set.clone(), - term: next_term.clone(), - }); - } - } - } - let next_state_id = self.build_recursive(next_rule_set, states, state_map)?; states[state_id] @@ -575,6 +569,8 @@ impl Grammar { if next_rules_term.contains_key(&lookahead) { // shift/reduce conflict may occur here, check reduce type + // note that conflict resolving through `reduce_types` is still applied + // even if `allow_conflict` is set to true match self.reduce_types.get(&lookahead) { Some(ReduceType::Left) => { // reduce first @@ -583,20 +579,18 @@ impl Grammar { next_rules_term.remove(&lookahead); // check for reduce/reduce conflict - if let Some(old) = state.reduce_map.get_mut(&lookahead) { - // same rule, continue - if old == &empty_rule { - continue; - } - - // conflict + let reduce_ruleset = + state.reduce_map.entry(lookahead.clone()).or_default(); + reduce_ruleset.insert(empty_rule); + if !self.allow_conflict && reduce_ruleset.len() > 1 { + let mut iter = reduce_ruleset.iter(); + let rule1 = *iter.next().unwrap(); + let rule2 = *iter.next().unwrap(); return Err(BuildError::ReduceReduceConflict { lookahead, - rule1: *old, - rule2: empty_rule, + rule1, + rule2, }); - } else { - state.reduce_map.insert(lookahead, empty_rule); } } Some(ReduceType::Right) => { @@ -606,30 +600,49 @@ impl Grammar { } None => { // shift/reduce error - return Err(BuildError::ShiftReduceConflict { - reduce: empty_rule, - shift: next_rules_term[&lookahead].clone(), - term: lookahead.clone(), - }); + if self.allow_conflict { + state + .reduce_map + .entry(lookahead.clone()) + .or_default() + .insert(empty_rule); + } else { + // next_rules_term has set of rules that is already shifted. + // so shift -= 1 again to get the rule that is not shifted yet + let shifted_rules: BTreeMap<_, _> = next_rules_term[&lookahead] + .rules + .iter() + .map(|(rule_ref, lookaheads)| { + let mut rule_ref = *rule_ref; + rule_ref.shifted -= 1; + (rule_ref, lookaheads.clone()) + }) + .collect(); + + return Err(BuildError::ShiftReduceConflict { + reduce: empty_rule, + shift: LookaheadRuleRefSet { + rules: shifted_rules, + }, + term: lookahead.clone(), + }); + } } } } else { // no shift/reduce conflict // check for reduce/reduce conflict - if let Some(old) = state.reduce_map.get_mut(&lookahead) { - // same rule, continue - if old == &empty_rule { - continue; - } - - // conflict + let reduce_ruleset = state.reduce_map.entry(lookahead.clone()).or_default(); + reduce_ruleset.insert(empty_rule); + if !self.allow_conflict && reduce_ruleset.len() > 1 { + let mut iter = reduce_ruleset.iter(); + let rule1 = *iter.next().unwrap(); + let rule2 = *iter.next().unwrap(); return Err(BuildError::ReduceReduceConflict { lookahead, - rule1: *old, - rule2: empty_rule, + rule1, + rule2, }); - } else { - state.reduce_map.insert(lookahead, empty_rule); } } } @@ -639,27 +652,6 @@ impl Grammar { // add shift and goto action // if next_token is in reduce_map, then it is a reduce/shift conflict for (next_term, next_rule_set) in next_rules_term.into_iter() { - // check for shift/reduce conflict again - if states[state_id].reduce_map.contains_key(next_term) { - match self.reduce_types.get(next_term) { - Some(ReduceType::Left) => { - // reduce first - continue; - } - Some(ReduceType::Right) => { - states[state_id].reduce_map.remove(next_term); - } - None => { - // shift/reduce error - return Err(BuildError::ShiftReduceConflict { - reduce: states[state_id].reduce_map[next_term], - shift: next_rule_set.clone(), - term: next_term.clone(), - }); - } - } - } - let next_state_id = self.build_recursive_lalr(next_rule_set, states, state_map)?; states[state_id] diff --git a/rusty_lr_core/src/builder/state.rs b/rusty_lr_core/src/builder/state.rs index 734eb99..e779a9d 100644 --- a/rusty_lr_core/src/builder/state.rs +++ b/rusty_lr_core/src/builder/state.rs @@ -1,12 +1,15 @@ use crate::hashmap::HashMap; use crate::rule::LookaheadRuleRefSet; -/// state in DFA +use std::collections::BTreeSet; +use std::hash::Hash; + +/// state in DFA building #[derive(Debug, Clone)] pub struct State { pub shift_goto_map_term: HashMap, pub shift_goto_map_nonterm: HashMap, - pub reduce_map: HashMap, + pub reduce_map: HashMap>, pub ruleset: LookaheadRuleRefSet, } impl State { @@ -21,11 +24,36 @@ impl State { /// We have two different `State` types. One in the `crate::builder` module and one in the `crate`. /// This state in `crate::builder` is used to build the DFA, which contains the lookaheads of the rules. /// This method converts the `State` in `crate::builder` to the `State` in `crate`. - pub fn to_export(self) -> crate::State { - crate::State { + pub fn to_export(self) -> crate::lr::State + where + Term: Hash + Eq, + { + crate::lr::State { + shift_goto_map_term: self.shift_goto_map_term, + shift_goto_map_nonterm: self.shift_goto_map_nonterm, + reduce_map: self + .reduce_map + .into_iter() + .map(|(k, v)| (k, v.into_iter().next().unwrap())) + .collect(), + ruleset: self.ruleset.rules.into_keys().collect(), + } + } + /// We have two different `State` types. One in the `crate::builder` module and one in the `crate`. + /// This state in `crate::builder` is used to build the DFA, which contains the lookaheads of the rules. + /// This method converts the `State` in `crate::builder` to the `State` in `crate`. + pub fn to_export_glr(self) -> crate::glr::State + where + Term: Hash + Eq, + { + crate::glr::State { shift_goto_map_term: self.shift_goto_map_term, shift_goto_map_nonterm: self.shift_goto_map_nonterm, - reduce_map: self.reduce_map, + reduce_map: self + .reduce_map + .into_iter() + .map(|(k, v)| -> (Term, Vec) { (k, v.into_iter().collect()) }) + .collect(), ruleset: self.ruleset.rules.into_keys().collect(), } } diff --git a/rusty_lr_core/src/glr/context.rs b/rusty_lr_core/src/glr/context.rs new file mode 100644 index 0000000..e973eca --- /dev/null +++ b/rusty_lr_core/src/glr/context.rs @@ -0,0 +1,15 @@ +use super::node::NodeSet; + +/// Context trait for GLR parser. +/// This handles the divergence and merging of the parser. +pub trait Context { + type Node; + + /// take list of current nodes + fn take_current_nodes(&mut self) -> NodeSet; + /// check if current nodes is empty + fn is_empty(&self) -> bool; + + /// get mutable reference of current nodes + fn get_current_nodes_mut(&mut self) -> &mut NodeSet; +} diff --git a/rusty_lr_core/src/glr/error.rs b/rusty_lr_core/src/glr/error.rs new file mode 100644 index 0000000..7cd1f45 --- /dev/null +++ b/rusty_lr_core/src/glr/error.rs @@ -0,0 +1,155 @@ +use crate::ProductionRule; + +use std::collections::BTreeSet; +use std::fmt::Debug; +use std::fmt::Display; + +/// Error when there is an invalid terminal feeded to the parser. +#[derive(Debug)] +pub struct InvalidTerminalError { + /// The terminal that feeded to the parser. + pub term: Term, + /// The expected terminals, Along all the paths. + pub expected: Vec, + /// The reduce action errors. + pub reduce_errors: Vec, +} + +impl Display + for InvalidTerminalError +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.message()) + } +} + +impl std::error::Error + for InvalidTerminalError +{ + fn cause(&self) -> Option<&dyn std::error::Error> { + None + } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } + fn description(&self) -> &str { + "Invalid terminal feeded" + } +} + +impl InvalidTerminalError { + /// Generate brief error message. + pub fn message(&self) -> String + where + Term: Display, + ReduceActionError: Display, + { + let mut message = format!("Invalid Terminal: {}. ", self.term); + + if self.expected.is_empty() { + message.push_str("No expected token"); + } else { + let expected: BTreeSet = + self.expected.iter().map(|t| format!("{}", t)).collect(); + message.push_str("Expected one of: "); + let len = expected.len(); + for (id, term) in expected.into_iter().enumerate() { + message.push_str(&term); + if id < len - 1 { + message.push_str(", "); + } + } + } + for error in &self.reduce_errors { + message.push_str(&format!("\nReduce action error: {}", error)); + } + message + } +} + +/// Error when there are multiple paths to represent the same string you feeded to the parser. +#[derive(Debug)] +pub struct MultiplePathError { + pub rule1: ProductionRule, + pub rule2: ProductionRule, +} + +impl Display for MultiplePathError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.message()) + } +} + +impl MultiplePathError { + pub fn message(&self) -> String + where + Term: Display, + NonTerm: Display, + { + format!( + "Multiple path detected:\n{}\nand\n{}", + self.rule1, self.rule2 + ) + } +} + +impl std::error::Error + for MultiplePathError +{ + fn cause(&self) -> Option<&dyn std::error::Error> { + None + } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } + fn description(&self) -> &str { + "Multiple path detected" + } +} + +#[derive(Debug)] +pub enum ParseError { + /// Error when there is no valid path to represent the string you feeded to the parser. + InvalidTerminal(InvalidTerminalError), + /// Error when there are multiple paths to represent the same string you feeded to the parser. + MultiplePath(MultiplePathError), +} + +impl Display + for ParseError +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ParseError::InvalidTerminal(err) => write!(f, "{}", err), + ParseError::MultiplePath(err) => write!(f, "{}", err), + } + } +} + +impl + std::error::Error for ParseError +{ + fn cause(&self) -> Option<&dyn std::error::Error> { + None + } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } + fn description(&self) -> &str { + "Parse error" + } +} + +impl ParseError { + pub fn message(&self) -> String + where + Term: Display, + NonTerm: Display, + ReduceActionError: Display, + { + match self { + ParseError::InvalidTerminal(err) => err.message(), + ParseError::MultiplePath(err) => err.message(), + } + } +} diff --git a/rusty_lr_core/src/glr/mod.rs b/rusty_lr_core/src/glr/mod.rs new file mode 100644 index 0000000..6da0edd --- /dev/null +++ b/rusty_lr_core/src/glr/mod.rs @@ -0,0 +1,152 @@ +pub(crate) mod context; +pub(crate) mod error; +pub(crate) mod parser; +pub(crate) mod state; + +pub mod node; + +pub use context::Context; +pub use error::InvalidTerminalError; +pub use error::MultiplePathError; +pub use error::ParseError; +pub use parser::Parser; +pub use state::State; + +use std::hash::Hash; +use std::rc::Rc; + +use node::Node; + +/// feed one terminal to parser, and update state stack. +/// For GLR parsing, this function will create multiple path if needed. +pub fn feed + Hash + Eq, C: Context>( + parser: &P, + context: &mut C, + term: P::Term, + userdata: &mut N::UserData, +) -> Result<(), ParseError> +where + P::Term: Hash + Eq + Clone, + P::NonTerm: Hash + Eq + Clone, +{ + let current_nodes = context.take_current_nodes(); + let mut reduce_errors = Vec::new(); + let mut states_list = Vec::with_capacity(current_nodes.nodes.len()); + for node in current_nodes.nodes.into_iter() { + states_list.push(node.state()); + feed_impl(parser, node, context, &term, userdata, &mut reduce_errors)?; + } + if context.is_empty() { + let mut expected = parser.get_states()[states_list[0]].expected(); + for state in states_list.into_iter().skip(1) { + expected = expected + .union(&parser.get_states()[state].expected()) + .cloned() + .collect(); + } + Err(ParseError::InvalidTerminal(InvalidTerminalError { + term, + expected: expected.into_iter().cloned().collect(), + reduce_errors, + })) + } else { + Ok(()) + } +} +/// feed one terminal to parser, and update state stack +fn feed_impl + Hash + Eq, C: Context>( + parser: &P, + mut node: Rc, + context: &mut C, + term: &P::Term, + userdata: &mut N::UserData, + reduce_errors: &mut Vec, +) -> Result<(), ParseError> +where + P::Term: Hash + Eq + Clone, + P::NonTerm: Hash + Eq + Clone, +{ + node = lookahead_impl( + parser, + Rc::clone(&node), + context, + term, + userdata, + reduce_errors, + )?; + + if let Some(next_state_id) = parser.get_states()[node.state()].shift_goto_term(&term) { + let node_rule = node.rule(); + let new_node = N::make_term_children(node, next_state_id, term.clone()); + // check conflict + if let Some(old) = context.get_current_nodes_mut().nodes.take(&new_node) { + let rule1 = old.parent().unwrap().rule().unwrap(); + let rule2 = node_rule.unwrap(); + + return Err(ParseError::MultiplePath(MultiplePathError { + rule1: parser.get_rules()[rule1].clone(), + rule2: parser.get_rules()[rule2].clone(), + })); + } else { + context + .get_current_nodes_mut() + .nodes + .insert(Rc::new(new_node)); + } + } + Ok(()) +} +/// give lookahead token to parser, and check if there is any reduce action +fn lookahead_impl + Hash + Eq, C: Context>( + parser: &P, + node: Rc, + context: &mut C, + term: &P::Term, + userdata: &mut N::UserData, + reduce_errors: &mut Vec, +) -> Result, ParseError> +where + P::Term: Hash + Eq + Clone, + P::NonTerm: Hash + Eq + Clone, +{ + if let Some(reduce_rules) = parser.get_states()[node.state()].reduce(&term) { + for reduce_rule in reduce_rules.iter().copied() { + let mut children_reversed = Vec::new(); + let mut n = Rc::clone(&node); + let rule = &parser.get_rules()[reduce_rule]; + for _ in 0..rule.rule.len() { + let parent = Rc::clone(n.parent().unwrap()); + children_reversed.push(n); + n = parent; + } + + if let Some(next_shift_nonterm) = + parser.get_states()[n.state()].shift_goto_nonterm(&rule.name) + { + match N::make_nonterm_children( + n, + next_shift_nonterm, + reduce_rule, + children_reversed, + term, + userdata, + ) { + Ok(new_node) => { + feed_impl( + parser, + Rc::new(new_node), + context, + term, + userdata, + reduce_errors, + )?; + } + Err(err) => { + reduce_errors.push(err); + } + } + } + } + } + Ok(node) +} diff --git a/rusty_lr_core/src/glr/node.rs b/rusty_lr_core/src/glr/node.rs new file mode 100644 index 0000000..97641bf --- /dev/null +++ b/rusty_lr_core/src/glr/node.rs @@ -0,0 +1,73 @@ +use std::{hash::Hash, rc::Rc}; + +use crate::HashSet; + +pub trait Node +where + Self: Sized, +{ + type Term; + type ReduceActionError; + type UserData; + + /// Get state index of this node + fn state(&self) -> usize; + /// Get parent node + fn parent(&self) -> Option<&Rc>; + + /// Make new node with terminal-shift action + fn make_term_children(parent: Rc, state: usize, term: Self::Term) -> Self; + /// Make new node with non-terminal shift action + fn make_nonterm_children( + parent: Rc, + state: usize, + rule: usize, + children_reversed: Vec>, + lookahead: &Self::Term, + userdata: &mut Self::UserData, + ) -> Result; + + /// Get rule index of this node. + /// This is only valid for non-terminal shift node. + fn rule(&self) -> Option; +} + +pub fn hash_node(node: &N, state: &mut H) { + node.state().hash(state); + if let Some(parent) = node.parent() { + hash_node(parent.as_ref(), state); + } +} +pub fn eq_node(node1: &N, node2: &N) -> bool { + if node1.state() != node2.state() { + return false; + } + match (node1.parent(), node2.parent()) { + (Some(parent1), Some(parent2)) => eq_node(parent1.as_ref(), parent2.as_ref()), + (None, None) => true, + _ => false, + } +} + +pub struct NodeSet { + /// Set of nodes. + /// Node is equal if their state-stack from the root is equal. + pub nodes: HashSet>, +} +impl Default for NodeSet { + fn default() -> Self { + NodeSet::new() + } +} + +impl NodeSet { + pub fn new() -> Self { + NodeSet { + nodes: Default::default(), + } + } + + pub fn is_empty(&self) -> bool { + self.nodes.is_empty() + } +} diff --git a/rusty_lr_core/src/glr/parser.rs b/rusty_lr_core/src/glr/parser.rs new file mode 100644 index 0000000..2e946e8 --- /dev/null +++ b/rusty_lr_core/src/glr/parser.rs @@ -0,0 +1,13 @@ +use crate::glr::State; +use crate::ProductionRule; + +/// Parser trait for GLR parser +pub trait Parser { + type Term; + type NonTerm; + + /// get list of production rules + fn get_rules(&self) -> &[ProductionRule]; + /// get list of states + fn get_states(&self) -> &[State]; +} diff --git a/rusty_lr_core/src/glr/state.rs b/rusty_lr_core/src/glr/state.rs new file mode 100644 index 0000000..ca0b695 --- /dev/null +++ b/rusty_lr_core/src/glr/state.rs @@ -0,0 +1,101 @@ +use std::collections::BTreeSet; +use std::hash::Hash; + +use crate::ShiftedRuleRef; +use crate::{HashMap, HashSet}; + +/// State in DFA. +/// This accepts multiple reduce for single terminal. +/// For GLR parser. +#[derive(Debug, Clone)] +pub struct State { + pub shift_goto_map_term: HashMap, + pub shift_goto_map_nonterm: HashMap, + pub reduce_map: HashMap>, + pub ruleset: BTreeSet, +} +impl State { + pub fn new() -> Self { + State { + shift_goto_map_term: Default::default(), + shift_goto_map_nonterm: Default::default(), + reduce_map: Default::default(), + ruleset: Default::default(), + } + } + + /// feed one teminal and get action + pub fn shift_goto_term(&self, term: &Term) -> Option + where + Term: Hash + Eq, + { + self.shift_goto_map_term.get(term).copied() + } + /// feed one non-teminal and get action + pub fn shift_goto_nonterm(&self, nonterm: &NonTerm) -> Option + where + NonTerm: Hash + Eq, + { + self.shift_goto_map_nonterm.get(nonterm).copied() + } + /// feed one token and get action + pub fn reduce(&self, term: &Term) -> Option<&[usize]> + where + Term: Hash + Eq, + { + self.reduce_map.get(term).map(|v| v.as_slice()) + } + + /// check if this state is accept state. + /// Augmented -> Start EOF . is accept state. + pub fn is_accept(&self) -> bool { + self.reduce_map.is_empty() + && self.shift_goto_map_term.is_empty() + && self.shift_goto_map_nonterm.is_empty() + } + + /// get expected terms set + pub fn expected(&self) -> HashSet<&Term> + where + Term: Hash + Eq, + { + HashSet::from_iter( + self.shift_goto_map_term + .keys() + .chain(self.reduce_map.keys()), + ) + } + + /// Map terminal and non-terminal symbols to another type. + /// This is useful when exporting & importing rules. + pub fn map( + self, + term_map: impl Fn(Term) -> NewTerm, + nonterm_map: impl Fn(NonTerm) -> NewNonTerm, + ) -> State { + State { + shift_goto_map_term: self + .shift_goto_map_term + .into_iter() + .map(|(term, state)| (term_map(term), state)) + .collect(), + shift_goto_map_nonterm: self + .shift_goto_map_nonterm + .into_iter() + .map(|(nonterm, state)| (nonterm_map(nonterm), state)) + .collect(), + reduce_map: self + .reduce_map + .into_iter() + .map(|(term, rule)| (term_map(term), rule)) + .collect(), + ruleset: self.ruleset, + } + } +} + +impl Default for State { + fn default() -> Self { + Self::new() + } +} diff --git a/rusty_lr_core/src/lib.rs b/rusty_lr_core/src/lib.rs index 2ce5464..a0fde4f 100644 --- a/rusty_lr_core/src/lib.rs +++ b/rusty_lr_core/src/lib.rs @@ -3,22 +3,23 @@ //! This crate is private and not intended to be used directly. //! Please use the [`rusty_lr`](https://crates.io/crates/rusty_lr) crate instead. -pub(crate) mod error; pub(crate) mod hashmap; pub(crate) mod rule; -pub(crate) mod state; pub(crate) mod token; /// module for build DFA tables from CFG #[cfg(feature = "builder")] pub mod builder; +/// module for LR(1), LALR(1) parser +pub mod lr; + +/// module for GLR parser +pub mod glr; + pub use hashmap::HashMap; pub use hashmap::HashSet; -pub use error::GetContext; -pub use error::GetParser; - pub use rule::ProductionRule; pub use rule::LookaheadRule; @@ -27,9 +28,24 @@ pub use rule::ShiftedRule; pub use rule::ShiftedRuleRef; pub use rule::ReduceType; -pub use state::State; pub use token::Token; -pub use error::DefaultReduceActionError; -pub use error::InvalidTerminalError; -pub use error::ParseError; +/// Default error type for reduce action +#[derive(Debug)] +pub struct DefaultReduceActionError; +impl std::fmt::Display for DefaultReduceActionError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Default reduce action error") + } +} +impl std::error::Error for DefaultReduceActionError { + fn cause(&self) -> Option<&dyn std::error::Error> { + None + } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } + fn description(&self) -> &str { + "Default reduce action error" + } +} diff --git a/rusty_lr_core/src/lr/context.rs b/rusty_lr_core/src/lr/context.rs new file mode 100644 index 0000000..4fe0cdb --- /dev/null +++ b/rusty_lr_core/src/lr/context.rs @@ -0,0 +1,22 @@ +/// Context trait for LR parser. +/// This hadles actual data stack for reduce action. +pub trait Context { + type Term; + type ReduceActionError; + type UserData; + + /// reduce action, this will be automatically called by parser + fn reduce( + &mut self, + ruleid: usize, + userdata: &mut Self::UserData, + lookahead: &Self::Term, + ) -> Result<(), Self::ReduceActionError>; + /// push terminal to data stack, this will be automatically called by parser + fn push(&mut self, term: Self::Term); + + /// get current state stack + fn get_state_stack(&self) -> &[usize]; + /// get current state stack mutable reference + fn get_state_stack_mut(&mut self) -> &mut Vec; +} diff --git a/rusty_lr_core/src/error.rs b/rusty_lr_core/src/lr/error.rs similarity index 85% rename from rusty_lr_core/src/error.rs rename to rusty_lr_core/src/lr/error.rs index 9a5408c..8f81672 100644 --- a/rusty_lr_core/src/error.rs +++ b/rusty_lr_core/src/lr/error.rs @@ -4,18 +4,11 @@ use std::fmt::Display; use std::hash::Hash; use crate::rule::ShiftedRuleRef2; -use crate::state::State; -use crate::ProductionRule; use crate::ShiftedRuleRef; use crate::Token; -pub trait GetContext { - fn get_state_stack(&self) -> &[usize]; -} -pub trait GetParser { - fn get_rules(&self) -> &[ProductionRule]; - fn get_states(&self) -> &[State]; -} +use super::Context; +use super::Parser; /// Error type for feed(), when invalid terminal is feeded #[derive(Debug)] @@ -50,8 +43,8 @@ impl InvalidTerminalError { /// Each ruleset in the returned `Vec` contains every rule that the state was trying to parse, that is, only the rules with shifted > 0. /// 0'th index is the latest, that is, the last element of `Vec` will hold the initial state's ruleset. pub fn backtrace( - parser: &impl GetParser, - context: &impl GetContext, + parser: &impl Parser, + context: &impl Context, ) -> Vec> where NonTerm: PartialEq, @@ -141,8 +134,8 @@ impl InvalidTerminalError { /// Generate long, detailed error message. pub fn long_message( &self, - parser: &impl GetParser, - context: &impl GetContext, + parser: &impl Parser, + context: &impl Context, ) -> String where Term: Display + Hash + Eq, @@ -211,8 +204,8 @@ impl ParseError { /// Generate long, detailed error message. pub fn long_message( &self, - parser: &impl GetParser, - context: &impl GetContext, + parser: &impl Parser, + context: &impl Context, ) -> String where Term: Display + Hash + Eq, @@ -227,23 +220,3 @@ impl ParseError { } } } - -/// Default error type for reduce action -#[derive(Debug)] -pub struct DefaultReduceActionError; -impl Display for DefaultReduceActionError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Default reduce action error") - } -} -impl std::error::Error for DefaultReduceActionError { - fn cause(&self) -> Option<&dyn std::error::Error> { - None - } - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - None - } - fn description(&self) -> &str { - "Default reduce action error" - } -} diff --git a/rusty_lr_core/src/lr/mod.rs b/rusty_lr_core/src/lr/mod.rs new file mode 100644 index 0000000..af7627d --- /dev/null +++ b/rusty_lr_core/src/lr/mod.rs @@ -0,0 +1,79 @@ +pub(crate) mod context; +pub(crate) mod error; +pub(crate) mod parser; +pub(crate) mod state; + +use std::hash::Hash; + +pub use context::Context; +pub use error::InvalidTerminalError; +pub use error::ParseError; +pub use parser::Parser; +pub use state::State; + +/// feed one terminal to parser, and update state & data stack +pub fn feed>( + parser: &P, + context: &mut C, + mut term: P::Term, + data: &mut C::UserData, +) -> Result<(), ParseError> +where + P::Term: Hash + Eq + Clone, + P::NonTerm: Hash + Eq, +{ + term = lookahead(parser, context, term, data)?; + let state = &parser.get_states()[*context.get_state_stack().last().unwrap()]; + if let Some(next_state_id) = state.shift_goto_term(&term) { + context.get_state_stack_mut().push(next_state_id); + context.push(term); + Ok(()) + } else { + let error = InvalidTerminalError { + term, + expected: state.expected().into_iter().cloned().collect(), + }; + Err(ParseError::InvalidTerminal(error)) + } +} +/// give lookahead token to parser, and check if there is any reduce action +fn lookahead>( + parser: &P, + context: &mut C, + term: P::Term, + data: &mut C::UserData, +) -> Result> +where + P::Term: Hash + Eq + Clone, + P::NonTerm: Hash + Eq, +{ + if let Some(reduce_rule) = + parser.get_states()[*context.get_state_stack().last().unwrap()].reduce(&term) + { + let rule = &parser.get_rules()[reduce_rule]; + { + let new_len = context.get_state_stack().len() - rule.rule.len(); + context.get_state_stack_mut().truncate(new_len); + } + context + .reduce(reduce_rule, data, &term) + .map_err(ParseError::ReduceAction)?; + if let Some(next_state_id) = parser.get_states()[*context.get_state_stack().last().unwrap()] + .shift_goto_nonterm(&rule.name) + { + context.get_state_stack_mut().push(next_state_id); + lookahead(parser, context, term, data) + } else { + Err(ParseError::InvalidTerminal(InvalidTerminalError { + term, + expected: parser.get_states()[*context.get_state_stack().last().unwrap()] + .expected() + .into_iter() + .cloned() + .collect(), + })) + } + } else { + Ok(term) + } +} diff --git a/rusty_lr_core/src/lr/parser.rs b/rusty_lr_core/src/lr/parser.rs new file mode 100644 index 0000000..23fd3d6 --- /dev/null +++ b/rusty_lr_core/src/lr/parser.rs @@ -0,0 +1,13 @@ +use super::State; +use crate::ProductionRule; + +/// Parser trait for LR parser +pub trait Parser { + type Term; + type NonTerm; + + /// get list of production rules + fn get_rules(&self) -> &[ProductionRule]; + /// get list of states + fn get_states(&self) -> &[State]; +} diff --git a/rusty_lr_core/src/state.rs b/rusty_lr_core/src/lr/state.rs similarity index 97% rename from rusty_lr_core/src/state.rs rename to rusty_lr_core/src/lr/state.rs index 743501a..dadfa3c 100644 --- a/rusty_lr_core/src/state.rs +++ b/rusty_lr_core/src/lr/state.rs @@ -2,8 +2,9 @@ use std::collections::BTreeSet; use std::fmt::Display; use std::hash::Hash; -use super::hashmap::{HashMap, HashSet}; -use super::rule::ShiftedRuleRef; +use crate::HashMap; +use crate::HashSet; +use crate::ShiftedRuleRef; /// state in DFA #[derive(Debug, Clone)] diff --git a/rusty_lr_derive/Cargo.toml b/rusty_lr_derive/Cargo.toml index 26191ba..b9b71e2 100644 --- a/rusty_lr_derive/Cargo.toml +++ b/rusty_lr_derive/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "rusty_lr_derive" -version = "1.11.0" +version = "1.12.0" edition = "2021" license = "MIT" description = "proc-macro definitions for rusty_lr" repository = "https://github.com/ehwan/RustyLR" readme = "../README.md" -keywords = ["parser", "yacc", "context-free-grammar", "lr", "compiler"] +keywords = ["parser", "bison", "context-free-grammar", "lr", "compiler"] categories = ["parsing"] [lib] @@ -15,4 +15,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.86" # rusty_lr_parser = { path = "../rusty_lr_parser" } -rusty_lr_parser = "3.9" +rusty_lr_parser = "3.10" diff --git a/rusty_lr_executable/Cargo.toml b/rusty_lr_executable/Cargo.toml index 26d1c45..ada35a8 100644 --- a/rusty_lr_executable/Cargo.toml +++ b/rusty_lr_executable/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "rustylr" -version = "0.12.0" +version = "0.13.0" edition = "2021" license = "MIT" description = "executable for rusty_lr" repository = "https://github.com/ehwan/RustyLR" readme = "../README.md" -keywords = ["parser", "yacc", "context-free-grammar", "lr", "compiler"] +keywords = ["parser", "bison", "context-free-grammar", "lr", "compiler"] categories = ["parsing"] [dependencies] clap = { version = "4.5.7", features = ["derive"] } -rusty_lr_buildscript = "0.6" +rusty_lr_buildscript = "0.7" # rusty_lr_buildscript = { path = "../rusty_lr_buildscript" } diff --git a/rusty_lr_parser/Cargo.toml b/rusty_lr_parser/Cargo.toml index 32a7fe8..8c75005 100644 --- a/rusty_lr_parser/Cargo.toml +++ b/rusty_lr_parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty_lr_parser" -version = "3.9.0" +version = "3.10.0" edition = "2021" license = "MIT" description = "macro line parser for rusty_lr" @@ -12,5 +12,5 @@ categories = ["parsing"] [dependencies] proc-macro2 = "1.0.86" quote = "1.0" -rusty_lr_core = { version = "2.4", features = ["fxhash", "builder"] } +rusty_lr_core = { version = "2.5", features = ["fxhash", "builder"] } # rusty_lr_core = { path = "../rusty_lr_core", features = ["fxhash", "builder"] } diff --git a/rusty_lr_parser/src/emit.rs b/rusty_lr_parser/src/emit.rs index 09330a6..e1ba26a 100644 --- a/rusty_lr_parser/src/emit.rs +++ b/rusty_lr_parser/src/emit.rs @@ -31,19 +31,40 @@ impl Grammar { let parse_error_typename = format_ident!("{}ParseError", start_rule_name); let invalid_terminal_error = format_ident!("{}InvalidTerminalError", start_rule_name); - quote! { - /// type alias for CFG production rule - #[allow(non_camel_case_types,dead_code)] - pub type #rule_typename = #module_prefix::ProductionRule<#token_typename, #enum_name>; - /// type alias for DFA state - #[allow(non_camel_case_types,dead_code)] - pub type #state_typename = #module_prefix::State<#token_typename, #enum_name>; - /// type alias for `ParseError` - #[allow(non_camel_case_types,dead_code)] - pub type #parse_error_typename = #module_prefix::ParseError<#token_typename, #reduce_error_typename>; - /// type alias for `InvalidTerminalError` - #[allow(non_camel_case_types,dead_code)] - pub type #invalid_terminal_error = #module_prefix::InvalidTerminalError<#token_typename>; + if self.glr { + let multiple_path_error = format_ident!("{}MultiplePathError", start_rule_name); + quote! { + /// type alias for CFG production rule + #[allow(non_camel_case_types,dead_code)] + pub type #rule_typename = #module_prefix::ProductionRule<#token_typename, #enum_name>; + /// type alias for DFA state + #[allow(non_camel_case_types,dead_code)] + pub type #state_typename = #module_prefix::glr::State<#token_typename, #enum_name>; + /// type alias for `ParseError` + #[allow(non_camel_case_types,dead_code)] + pub type #parse_error_typename = #module_prefix::glr::ParseError<#token_typename, #enum_name, #reduce_error_typename>; + /// type alias for `InvalidTerminalError` + #[allow(non_camel_case_types,dead_code)] + pub type #invalid_terminal_error = #module_prefix::glr::InvalidTerminalError<#token_typename, #reduce_error_typename>; + /// type alias for `MultiplePathError` + #[allow(non_camel_case_types,dead_code)] + pub type #multiple_path_error = #module_prefix::glr::MultiplePathError<#token_typename, #enum_name>; + } + } else { + quote! { + /// type alias for CFG production rule + #[allow(non_camel_case_types,dead_code)] + pub type #rule_typename = #module_prefix::ProductionRule<#token_typename, #enum_name>; + /// type alias for DFA state + #[allow(non_camel_case_types,dead_code)] + pub type #state_typename = #module_prefix::lr::State<#token_typename, #enum_name>; + /// type alias for `ParseError` + #[allow(non_camel_case_types,dead_code)] + pub type #parse_error_typename = #module_prefix::lr::ParseError<#token_typename, #reduce_error_typename>; + /// type alias for `InvalidTerminalError` + #[allow(non_camel_case_types,dead_code)] + pub type #invalid_terminal_error = #module_prefix::lr::InvalidTerminalError<#token_typename>; + } } } @@ -165,7 +186,7 @@ impl Grammar { let states: Vec<_> = dfa .states .into_iter() - .map(|s| s.to_export().map(term_mapper, nonterm_mapper)) + .map(|s| s.to_export_glr().map(term_mapper, nonterm_mapper)) .collect(); (rules, states) }; @@ -255,11 +276,13 @@ impl Grammar { } let mut reduce_map_by_rule_id = BTreeMap::new(); - for (term, ruleid) in state.reduce_map.into_iter() { - reduce_map_by_rule_id - .entry(ruleid) - .or_insert_with(BTreeSet::new) - .insert(term); + for (term, ruleids) in state.reduce_map.into_iter() { + for ruleid in ruleids.into_iter() { + reduce_map_by_rule_id + .entry(ruleid) + .or_insert_with(BTreeSet::new) + .insert(term); + } } { let mut terminalsetid_rule_comma_separated = TokenStream::new(); @@ -346,6 +369,31 @@ impl Grammar { }); } } + let init_reduce_map = if self.glr { + quote! { + let mut reduce_map = #module_prefix::HashMap::default(); + for (terminal_set_id, ruleid) in reduce_map_.iter() { + for term in RUSTYLR_REDUCE_TERMINALS_CACHE[*terminal_set_id as usize].iter() { + reduce_map.entry( __rustylr_terminals[*term as usize].clone() ) + .or_insert_with( Vec::new ) + .push( *ruleid as usize ); + } + } + } + } else { + quote! { + let mut reduce_map = #module_prefix::HashMap::default(); + for (terminal_set_id, ruleid) in reduce_map_.iter() { + reduce_map.extend( + RUSTYLR_REDUCE_TERMINALS_CACHE[*terminal_set_id as usize].iter().map( + | term_idx | { + (__rustylr_terminals[*term_idx as usize].clone(), *ruleid as usize) + } + ) + ); + } + } + }; Ok(quote! { let __rustylr_terminals = vec![#comma_separated_terminals]; @@ -388,16 +436,7 @@ impl Grammar { ) ).map( | (shift_goto_map_term, (shift_goto_map_nonterm, (reduce_map_, (ruleset,ruleset0_id)))) | { - let mut reduce_map = #module_prefix::HashMap::default(); - for (terminal_set_id, ruleid) in reduce_map_.iter() { - reduce_map.extend( - RUSTYLR_REDUCE_TERMINALS_CACHE[*terminal_set_id as usize].iter().map( - | term_idx | { - (__rustylr_terminals[*term_idx as usize].clone(), *ruleid as usize) - } - ) - ); - } + #init_reduce_map let mut ruleset: std::collections::BTreeSet<#module_prefix::ShiftedRuleRef> = ruleset.iter().map( @@ -444,7 +483,6 @@ impl Grammar { let parseerror_typename = format_ident!("{}ParseError", self.start_rule_name); let rule_typename = format_ident!("{}Rule", self.start_rule_name); let state_typename = format_ident!("{}State", self.start_rule_name); - let invalid_terminal_error = format_ident!("{}InvalidTerminalError", self.start_rule_name); let parser_struct_name = format_ident!("{}Parser", self.start_rule_name); let context_struct_name = format_ident!("{}Context", self.start_rule_name); @@ -489,14 +527,16 @@ impl Grammar { // TokenStream for userdata parameter definition, if defined let user_data_parameter_name = Ident::new(utils::USER_DATA_PARAMETER_NAME, Span::call_site()); - let (user_data_parameter_def, user_data_var) = + let (user_data_typename, user_data_parameter_def, user_data_var, user_data_dummy) = if let Some(user_data) = &self.userdata_typename { ( + user_data.clone(), quote! { #user_data_parameter_name: &mut #user_data, }, quote! { #user_data_parameter_name, }, + quote! { #user_data_parameter_name }, ) } else { - (quote! {}, quote! {}) + (quote! {()}, quote! {}, quote! {}, quote! {&mut ()}) }; let mut ruleid: usize = 0; @@ -550,7 +590,7 @@ impl Grammar { case_streams.extend(quote! { #ruleid => { - self.#reduce_fn_ident( #user_data_var )?; + self.#reduce_fn_ident( lookahead, #user_data_var ) } }); @@ -564,7 +604,7 @@ impl Grammar { // typename is defined, reduce action must be defined if let Some(action) = &rule.reduce_action { fn_reduce_for_each_rule_stream.extend(quote! { - fn #reduce_fn_ident(&mut self, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { + fn #reduce_fn_ident(&mut self, lookahead: &#token_typename, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { #token_pop_stream self.#stack_name.push(#action); Ok(()) @@ -589,7 +629,7 @@ impl Grammar { } if let Some(unique_mapto) = unique_mapto { fn_reduce_for_each_rule_stream.extend(quote! { - fn #reduce_fn_ident(&mut self, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { + fn #reduce_fn_ident(&mut self, lookahead: &#token_typename, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { #token_pop_stream self.#stack_name.push(#unique_mapto); Ok(()) @@ -607,7 +647,7 @@ impl Grammar { // just execute action if let Some(action) = &rule.reduce_action { fn_reduce_for_each_rule_stream.extend(quote! { - fn #reduce_fn_ident(&mut self, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { + fn #reduce_fn_ident(&mut self, lookahead: &#token_typename, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { #token_pop_stream #action Ok(()) @@ -615,7 +655,7 @@ impl Grammar { }); } else { fn_reduce_for_each_rule_stream.extend(quote! { - fn #reduce_fn_ident(&mut self, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { + fn #reduce_fn_ident(&mut self, lookahead: &#token_typename, #user_data_parameter_def) -> Result<(), #reduce_error_typename> { #token_pop_stream Ok(()) } @@ -693,11 +733,22 @@ impl Grammar { #fn_reduce_for_each_rule_stream - /// reduce items in stack, this function is called automatically by parser - pub fn reduce(&mut self, - rulelen: usize, + /// pop value from start rule + #[inline] + pub fn accept(&mut self) #return_start_rule_typename { + #pop_from_start_rule_stack + } + } + + impl #module_prefix::lr::Context for #context_struct_name { + type Term = #token_typename; + type ReduceActionError = #reduce_error_typename; + type UserData = #user_data_typename; + + fn reduce(&mut self, rustylr_macro_generated_ruleid__: usize, - #user_data_parameter_def + data: &mut #user_data_typename, + lookahead: &#token_typename, ) -> Result<(), #reduce_error_typename> { match rustylr_macro_generated_ruleid__ { #case_streams @@ -705,36 +756,40 @@ impl Grammar { unreachable!( "Invalid Rule: {}", rustylr_macro_generated_ruleid__ ); } } - Ok(()) } - - /// pop value from start rule - #[inline] - pub fn accept(&mut self) #return_start_rule_typename { - #pop_from_start_rule_stack - } - - /// push terminal symbol to stack, this function is called automatically by parser - #[inline] - pub fn push( &mut self, term: #token_typename ) { + fn push( &mut self, term: #token_typename ) { self.#terms_stack_name.push(term); } - } - impl #module_prefix::GetContext<#token_typename, #nonterminals_enum_name> for #context_struct_name { + fn get_state_stack(&self) -> &[usize] { &self.state_stack } + fn get_state_stack_mut(&mut self) -> &mut Vec { + &mut self.state_stack + } } + /// struct that holds parser data, DFA tables #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] - #[derive(Clone)] pub struct #parser_struct_name { /// production rules pub rules: Vec<#rule_typename>, /// states pub states: Vec<#state_typename>, } + impl #module_prefix::lr::Parser for #parser_struct_name { + type Term = #token_typename; + type NonTerm = #nonterminals_enum_name; + + fn get_rules(&self) -> &[#rule_typename] { + &self.rules + } + fn get_states(&self) -> &[#state_typename] { + &self.states + } + } + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] impl #parser_struct_name { /// feed one terminal to parser, and update state stack @@ -744,27 +799,12 @@ impl Grammar { term: #token_typename, #user_data_parameter_def ) -> Result<(), #parseerror_typename> { - // reduce if possible - self.lookahead(context, &term, #user_data_var)?; - - // fetch state from state stack - let state = &self.states[*context.state_stack.last().unwrap()]; - - // feed token to current state and get action - // there must be no reduce/shift conflict ( that is, both shift and reduce are possible with this term ), - // since it is resolved in state generation ( Grammar::build() ) - if let Some(next_state_id) = state.shift_goto_term(&term) { - context.state_stack.push(next_state_id); - context.push( term ); - - Ok(()) - }else { - let error = #invalid_terminal_error { - term, - expected: state.expected().into_iter().cloned().collect(), - }; - Err(#parseerror_typename::InvalidTerminal(error)) - } + #module_prefix::lr::feed( + self, + context, + term, + #user_data_dummy, + ) } /// Create new context for parsing #[inline] @@ -772,74 +812,444 @@ impl Grammar { #context_struct_name::new() } + /// Create new parser instance. + /// Parser can be reused with different context, for multiple parsing. + pub fn new() -> Self { + #grammar_emit + Self { + rules, + states, + } + } + } - /// give lookahead token to parser, and check if there is any reduce action - fn lookahead( - &self, - context: &mut #context_struct_name, - term: &#token_typename, - #user_data_parameter_def - ) -> Result<(), #parseerror_typename> { - // fetch state from state stack - let state = &self.states[*context.state_stack.last().unwrap()]; - - // feed token to current state and get action - // there must be no reduce/shift conflict ( that is, both shift and reduce are possible with this term ), - // since it is resolved in state generation ( Grammar::build() ) - if let Some(reduce_rule) = state.reduce(term) { - // reduce items in stack - let rule = &self.rules[reduce_rule]; - context - .state_stack - .truncate(context.state_stack.len() - rule.rule.len()); - context.reduce( - self.rules[reduce_rule].rule.len(), - reduce_rule, - #user_data_var - ).map_err(#parseerror_typename::ReduceAction)?; - - - // feed reduced token - self.feed_nonterm(context, &rule.name)?; - - // original lookahead token is not shifted, so feed it again - self.lookahead(context, term, #user_data_var)?; + }) + } + + fn emit_parser_glr(&self, grammar_emit: TokenStream) -> Result> { + let module_prefix = &self.module_prefix; + let nonterminals_enum_name = utils::generate_enum_name(&self.start_rule_name); + let reduce_error_typename = &self.error_typename; + let parseerror_typename = format_ident!("{}ParseError", self.start_rule_name); + let rule_typename = format_ident!("{}Rule", self.start_rule_name); + let state_typename = format_ident!("{}State", self.start_rule_name); + let parser_struct_name = format_ident!("{}Parser", self.start_rule_name); + let node_struct_name = format_ident!("{}Node", self.start_rule_name); + let node_enum_name = format_ident!("{}NodeEnum", self.start_rule_name); + let context_struct_name = format_ident!("{}Context", self.start_rule_name); + let token_typename = &self.token_typename; + + // ===================================================================== + // =========================Writing Parser============================== + // ===================================================================== + + let terms_enum_name = Ident::new("__Terminals", Span::call_site()); + + // TokenStream for userdata parameter definition, if defined + let user_data_parameter_name = + Ident::new(utils::USER_DATA_PARAMETER_NAME, Span::call_site()); + let (user_data_typename, user_data_parameter_def, user_data_var, user_data_dummy) = + if let Some(user_data) = &self.userdata_typename { + ( + user_data.clone(), + quote! { #user_data_parameter_name: &mut #user_data, }, + quote! { #user_data_parameter_name, }, + quote! { #user_data_parameter_name }, + ) + } else { + (quote! {()}, quote! {}, quote! {}, quote! {&mut ()}) + }; + + let mut ruleid: usize = 0; + let mut case_streams = quote! {}; + + // TokenStream to define reduce function for each production rule + let mut fn_reduce_for_each_rule_stream = TokenStream::new(); + + for name in self.rules_index.iter() { + let rules = self.rules.get(name).unwrap(); + for (rule_local_id, rule) in rules.rule_lines.iter().enumerate() { + let mut extract_data_from_node_enum = TokenStream::new(); + for token in rule.tokens.iter() { + if self.terminals.contains_key(&token.token) { + match &token.mapto { + Some(mapto) => { + extract_data_from_node_enum.extend(quote! { + let mut #mapto = if let #node_enum_name::#terms_enum_name(#mapto) = + #node_struct_name::unwrap_or_clone(__children_reversed.pop().unwrap()) { + #mapto + } else { + unreachable!() + }; + }); + } + None => { + extract_data_from_node_enum.extend(quote! { + __children_reversed.pop(); + }); + } + } + } else if let Some(_) = self.nonterm_typenames.get(&token.token) { + // if is defined for this nonterm, + // extract data from enum + + let variant_name = &token.token; + + match &token.mapto { + Some(mapto) => { + extract_data_from_node_enum.extend(quote! { + let mut #mapto = if let #node_enum_name::#variant_name(#mapto) = + #node_struct_name::unwrap_or_clone(__children_reversed.pop().unwrap()) { + #mapto + } else { + unreachable!() + }; + }); + } + None => { + extract_data_from_node_enum.extend(quote! { + __children_reversed.pop(); + }); + } + } + } else { + extract_data_from_node_enum.extend(quote! { + __children_reversed.pop(); + }); + } + } + + let reduce_fn_ident = format_ident!("reduce_{}_{}", name, rule_local_id); + + case_streams.extend(quote! { + #ruleid => { + Self::#reduce_fn_ident( parent, state, children_reversed, lookahead, #user_data_var ) + } + }); + + // if typename is defined for this rule, push result of action to stack + // else, just execute action + let typename = self.nonterm_typenames.get(name); + if typename.is_some() { + // typename is defined, reduce action must be defined + if let Some(action) = &rule.reduce_action { + fn_reduce_for_each_rule_stream.extend(quote! { + fn #reduce_fn_ident( + __rustylr_parent: std::rc::Rc, + __rustylr_state: usize, + mut __children_reversed: Vec>, + lookahead: &#token_typename, + #user_data_parameter_def + ) -> Result { + #extract_data_from_node_enum + + Ok( + Self { + data: Some(#node_enum_name::#name(#action)), + state: __rustylr_state, + parent: Some(__rustylr_parent), + rule: Some(#ruleid), + } + ) + } + }); + } else { + // action is not defined, + + // check for special case: + // only one token in this rule have defined (include terminal) + // the unique value will be pushed to stack + let mut unique_mapto = None; + for token in rule.tokens.iter() { + if token.mapto.is_some() { + if unique_mapto.is_some() { + unique_mapto = None; + break; + } else { + unique_mapto = token.mapto.as_ref(); + } + } + } + if let Some(unique_mapto) = unique_mapto { + fn_reduce_for_each_rule_stream.extend(quote! { + fn #reduce_fn_ident( + __rustylr_parent: std::rc::Rc, + __rustylr_state: usize, + mut __children_reversed: Vec>, + lookahead: &#token_typename, + #user_data_parameter_def + ) -> Result { + #extract_data_from_node_enum + + Ok( + Self { + data: Some(#node_enum_name::#name(#unique_mapto)), + state: __rustylr_state, + parent: Some(__rustylr_parent), + rule: Some(#ruleid), + } + ) + } + }); + } else { + return Err(Box::new(EmitError::RuleTypeDefinedButActionNotDefined { + name: name.clone(), + rule_local_id, + })); + } + } + } else { + // is not defined, + // just execute action + if let Some(action) = &rule.reduce_action { + fn_reduce_for_each_rule_stream.extend(quote! { + + fn #reduce_fn_ident( + __rustylr_parent: std::rc::Rc, + __rustylr_state: usize, + mut __children_reversed: Vec>, + lookahead: &#token_typename, + #user_data_parameter_def + ) -> Result { + #extract_data_from_node_enum + #action + + Ok( + Self { + data: Some(#node_enum_name::#name), + state: __rustylr_state, + parent: Some(__rustylr_parent), + rule: Some(#ruleid), + } + ) + } + }); + } else { + fn_reduce_for_each_rule_stream.extend(quote! { + fn #reduce_fn_ident( + __rustylr_parent: std::rc::Rc, + __rustylr_state: usize, + mut __children_reversed: Vec>, + lookahead: &#token_typename, + #user_data_parameter_def + ) -> Result { + #extract_data_from_node_enum + + Ok( + Self { + data: Some(#node_enum_name::#name), + state: __rustylr_state, + parent: Some(__rustylr_parent), + rule: Some(#ruleid), + } + ) + } + }); + } } - Ok(()) + + ruleid += 1; } + } - /// feed one non-terminal to parser, and update state stack - fn feed_nonterm( - &self, - context: &mut #context_struct_name, - nonterm: &#nonterminals_enum_name, - ) -> Result<(), #parseerror_typename> { - // fetch state from state stack - let state = &self.states[*context.state_stack.last().unwrap()]; - - // feed token to current state and get action - // for shift/reduce confict, shift has higher priority - if let Some(next_state_id) = state.shift_goto_nonterm(nonterm) { - context.state_stack.push(next_state_id); - }else { - unreachable!( "Invalid NonTerminal: {}", nonterm ); + let mut derives_stream = TokenStream::new(); + for derive in &self.derives { + derives_stream.extend(quote! { + #derive, + }); + } + derives_stream = if self.derives.is_empty() { + TokenStream::new() + } else { + quote! { + #[derive(#derives_stream)] + } + }; + + let (start_typename, start_extract) = + if let Some(start_typename) = self.nonterm_typenames.get(&self.start_rule_name) { + let startname = &self.start_rule_name; + ( + start_typename.clone(), + quote! { + let rc = self.current_nodes.nodes.into_iter().next().unwrap(); + let parent = std::rc::Rc::into_inner(rc).unwrap().parent.unwrap(); + let data_enum = std::rc::Rc::into_inner(parent).unwrap().data.unwrap(); + if let #node_enum_name::#startname(start) = data_enum { + start + } else { + unreachable!() + } + }, + ) + } else { + (quote! {()}, quote! {()}) + }; + + // enum data type + let mut enum_variants_stream = quote! { + #terms_enum_name(#token_typename), + }; + for name in self.rules_index.iter() { + if let Some(typename) = self.nonterm_typenames.get(name) { + enum_variants_stream.extend(quote! { + #name(#typename), + }); + } else { + enum_variants_stream.extend(quote! { + #name, + }); + } + } + + Ok(quote! { + /// enum for each non-terminal and terminal symbol, that actually hold data + #[allow(unused_braces, unused_parens, non_snake_case, non_camel_case_types)] + #[derive(Clone)] + pub enum #node_enum_name { + #enum_variants_stream + } + + + /// Each node represents single state transition. + /// Either shifting one terminal or non-temrinal symbol. + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] + #derives_stream + pub struct #node_struct_name { + data: Option<#node_enum_name>, + state: usize, + parent: Option>, + rule: Option, + } + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut, dead_code)] + impl #node_struct_name { + #fn_reduce_for_each_rule_stream + + #[inline] + fn unwrap_or_clone( node: std::rc::Rc ) -> #node_enum_name { + match std::rc::Rc::try_unwrap(node) { + Ok(node) => node.data.unwrap(), + Err(rc_node) => rc_node.data.as_ref().unwrap().clone() } - Ok(()) } + } + impl std::hash::Hash for #node_struct_name { + fn hash(&self, state: &mut H) { + #module_prefix::glr::node::hash_node( self, state ); + } + } + impl std::cmp::PartialEq for #node_struct_name { + fn eq(&self, other: &Self) -> bool { + #module_prefix::glr::node::eq_node( self, other ) + } + } + impl std::cmp::Eq for #node_struct_name {} + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] + impl #module_prefix::glr::node::Node for #node_struct_name { + type Term = #token_typename; + type ReduceActionError = #reduce_error_typename; + type UserData = #user_data_typename; - /// Create new parser instance. - /// Parser can be reused with different context, for multiple parsing. + fn state(&self) -> usize { + self.state + } + fn parent(&self) -> Option<&std::rc::Rc> { + self.parent.as_ref() + } + + fn make_term_children(parent: std::rc::Rc, state: usize, term: #token_typename) -> Self { + Self { + data: Some(#node_enum_name::#terms_enum_name(term)), + state, + parent: Some(parent), + rule: None, + } + } + fn make_nonterm_children( + parent: std::rc::Rc, + state: usize, + ruleid: usize, + children_reversed: Vec>, + lookahead: &Self::Term, + data: &mut #user_data_typename, + ) -> Result { + match ruleid { + #case_streams + _ => { + unreachable!( "Invalid Rule: {}", ruleid ); + } + } + } + + fn rule(&self) -> Option { + self.rule + } + } + + + + /// Context is holding multiple nodes, that represents current state of parser. + /// If there are multiple nodes, it means parser is in ambiguous state. + /// It must be resolved(merged) into single node by feeding more terminal symbols. + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] + #derives_stream + pub struct #context_struct_name { + pub current_nodes: #module_prefix::glr::node::NodeSet<#node_struct_name>, + } + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut, dead_code)] + impl #context_struct_name { pub fn new() -> Self { - #grammar_emit + let mut nodeset = #module_prefix::glr::node::NodeSet::new(); + nodeset.nodes.insert( + std::rc::Rc::new( + #node_struct_name { + data: None, + state: 0, + parent: None, + rule: None, + } + ) + ); Self { - rules, - states, + current_nodes: nodeset, } } + + /// pop value from start rule + #[inline] + pub fn accept(self) -> #start_typename { + #start_extract + } + } + impl #module_prefix::glr::Context for #context_struct_name { + type Node = #node_struct_name; + + fn take_current_nodes(&mut self) -> #module_prefix::glr::node::NodeSet<#node_struct_name> { + std::mem::take( &mut self.current_nodes ) + } + fn is_empty(&self) -> bool { + self.current_nodes.is_empty() + } + + fn get_current_nodes_mut(&mut self) -> &mut #module_prefix::glr::node::NodeSet<#node_struct_name> { + &mut self.current_nodes + } + } + + + /// struct that holds parser data, DFA tables + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] + pub struct #parser_struct_name { + /// production rules + pub rules: Vec<#rule_typename>, + /// states + pub states: Vec<#state_typename>, } + impl #module_prefix::glr::Parser for #parser_struct_name { + type Term = #token_typename; + type NonTerm = #nonterminals_enum_name; - impl #module_prefix::GetParser<#token_typename, #nonterminals_enum_name> for #parser_struct_name { fn get_rules(&self) -> &[#rule_typename] { &self.rules } @@ -847,6 +1257,41 @@ impl Grammar { &self.states } } + + /// Parser is holding DFA state tables and production rules + #[allow(unused_braces, unused_parens, unused_variables, non_snake_case, unused_mut)] + impl #parser_struct_name { + /// feed one terminal to parser, and update state stack + pub fn feed( + &self, + context: &mut #context_struct_name, + term: #token_typename, + #user_data_parameter_def + ) -> Result<(), #parseerror_typename> { + #module_prefix::glr::feed( + self, + context, + term, + #user_data_dummy, + ) + } + /// Create new context for parsing + #[inline] + pub fn begin(&self) -> #context_struct_name { + #context_struct_name::new() + } + + /// Create new parser instance. + /// Parser can be reused with different context, for multiple parsing. + pub fn new() -> Self { + #grammar_emit + Self { + rules, + states, + } + } + } + }) } @@ -854,7 +1299,11 @@ impl Grammar { let type_alias_emit = self.emit_type_alises(); let enum_emit = self.emit_nonterm_enum(); let grammar_emit = self.emit_grammar_compiletime(lalr)?; - let parser_emit = self.emit_parser(grammar_emit)?; + let parser_emit = if self.glr { + self.emit_parser_glr(grammar_emit)? + } else { + self.emit_parser(grammar_emit)? + }; Ok(quote! { #type_alias_emit diff --git a/rusty_lr_parser/src/grammar.rs b/rusty_lr_parser/src/grammar.rs index 482e2af..ce48ab9 100644 --- a/rusty_lr_parser/src/grammar.rs +++ b/rusty_lr_parser/src/grammar.rs @@ -52,6 +52,9 @@ pub struct Grammar { pub(crate) pattern_map: HashMap, /// span range that generated rule was originated from pub generated_root_span: HashMap, + + /// whether to generate GLR parser + pub(crate) glr: bool, } impl Grammar { @@ -197,6 +200,7 @@ impl Grammar { rules_index: Default::default(), pattern_map: Default::default(), generated_root_span: Default::default(), + glr: grammar_args.glr, }; for (index, (ident, typename)) in grammar_args.terminals.into_iter().enumerate() { @@ -373,6 +377,9 @@ impl Grammar { pub fn create_grammar(&self) -> rusty_lr_core::builder::Grammar { let mut grammar: rusty_lr_core::builder::Grammar = rusty_lr_core::builder::Grammar::new(); + if self.glr { + grammar.allow_conflict(); + } // reduce types for (term, reduce_type) in self.reduce_types.iter() { diff --git a/rusty_lr_parser/src/parser/args.rs b/rusty_lr_parser/src/parser/args.rs index 60b24e8..15f5740 100644 --- a/rusty_lr_parser/src/parser/args.rs +++ b/rusty_lr_parser/src/parser/args.rs @@ -177,4 +177,5 @@ pub struct GrammarArgs { pub reduce_types: Vec<(TerminalSetOrIdent, ReduceType)>, pub derives: Vec, pub rules: Vec, + pub glr: bool, } diff --git a/rusty_lr_parser/src/parser/lexer.rs b/rusty_lr_parser/src/parser/lexer.rs index 49d21ae..3440d0b 100644 --- a/rusty_lr_parser/src/parser/lexer.rs +++ b/rusty_lr_parser/src/parser/lexer.rs @@ -53,6 +53,7 @@ pub enum Lexed { UserData(Punct, Ident), // %userdata ErrorType(Punct, Ident), // %err %error ModulePrefix(Punct, Ident), // %moduleprefix + GLR(Punct, Ident), // %glr Derive(Punct, Ident), // %derive Eof, } @@ -124,6 +125,10 @@ impl Lexed { stream.append(punct); stream.append(ident); } + Lexed::GLR(punct, ident) => { + stream.append(punct); + stream.append(ident); + } Lexed::Derive(punct, ident) => { stream.append(punct); stream.append(ident); @@ -172,6 +177,7 @@ impl Lexed { Lexed::UserData(punct, ident) => ident.span(), Lexed::ErrorType(punct, ident) => ident.span(), Lexed::ModulePrefix(punct, ident) => ident.span(), + Lexed::GLR(punct, ident) => ident.span(), Lexed::Derive(punct, ident) => ident.span(), Lexed::Eof => Span::call_site(), @@ -217,6 +223,7 @@ impl std::fmt::Display for Lexed { Lexed::UserData(_, _) => write!(f, "%userdata"), Lexed::ErrorType(_, _) => write!(f, "%error"), Lexed::ModulePrefix(_, _) => write!(f, "%moduleprefix"), + Lexed::GLR(_, _) => write!(f, "%glr"), Lexed::Derive(_, _) => write!(f, "%derive"), Lexed::Eof => write!(f, ""), @@ -246,6 +253,7 @@ fn ident_to_keyword(percent: Punct, ident: Ident) -> Option { "userdata" => Some(Lexed::UserData(percent, ident)), "err" | "error" => Some(Lexed::ErrorType(percent, ident)), "moduleprefix" => Some(Lexed::ModulePrefix(percent, ident)), + "glr" => Some(Lexed::GLR(percent, ident)), "derive" => Some(Lexed::Derive(percent, ident)), _ => None, } diff --git a/rusty_lr_parser/src/parser/parser.rs b/rusty_lr_parser/src/parser/parser.rs index d832281..49a8995 100644 --- a/rusty_lr_parser/src/parser/parser.rs +++ b/rusty_lr_parser/src/parser/parser.rs @@ -21,8 +21,7 @@ use rusty_lr_core::ReduceType; // bootstrap the parser for the grammar // this define the actual parser for proc-macro line parsing - -// rusty_lr_expand parser.rs parser_expanded.rs +// This should be changed to GLR parser in the future macro_rules! punct( ($l:literal) => { @@ -75,6 +74,7 @@ macro_rules! punct( %token userdata Lexed::UserData(punct!('%'),Ident::new("id", Span::call_site())); %token errortype Lexed::ErrorType(punct!('%'),Ident::new("id", Span::call_site())); %token moduleprefix Lexed::ModulePrefix(punct!('%'),Ident::new("id", Span::call_site())); +%token glr Lexed::GLR(punct!('%'),Ident::new("id", Span::call_site())); %token derive Lexed::Derive(punct!('%'),Ident::new("id", Span::call_site())); %eof Lexed::Eof; @@ -317,6 +317,8 @@ ErrorDef((Span,TokenStream)): errortype RustCode semicolon { (errortype.span(), ModulePrefixDef((Span,TokenStream)): moduleprefix RustCode semicolon { (moduleprefix.span(), RustCode) }; +GLR: glr semicolon; + DeriveDef(TokenStream): derive RustCode semicolon { RustCode }; @@ -330,6 +332,7 @@ GrammarLine : Rule { data.rules.push(Rule); } | ReduceDef { data.reduce_types.push(ReduceDef); } | ErrorDef { data.error_typename.push(ErrorDef); } | ModulePrefixDef { data.module_prefix.push(ModulePrefixDef); } +| GLR { data.glr = true; } | DeriveDef { data.derives.push(DeriveDef); } ; diff --git a/rusty_lr_parser/src/parser/parser_expanded.rs b/rusty_lr_parser/src/parser/parser_expanded.rs index 6b9900e..211df07 100644 --- a/rusty_lr_parser/src/parser/parser_expanded.rs +++ b/rusty_lr_parser/src/parser/parser_expanded.rs @@ -1,4 +1,4 @@ -// This file was generated by rustylr 0.11.0 +// This file was generated by rustylr 0.12.0 // // Input file: ../rusty_lr_parser/src/parser/parser.rs // Output file: parser_expanded.rs @@ -90,6 +90,7 @@ ReduceType -> right ReduceDef -> ReduceType TerminalSetOrIdent semicolon ErrorDef -> errortype RustCode semicolon ModulePrefixDef -> moduleprefix RustCode semicolon +GLR -> glr semicolon DeriveDef -> derive RustCode semicolon GrammarLine -> Rule GrammarLine -> TokenDef @@ -100,6 +101,7 @@ GrammarLine -> UserDataDef GrammarLine -> ReduceDef GrammarLine -> ErrorDef GrammarLine -> ModulePrefixDef +GrammarLine -> GLR GrammarLine -> DeriveDef Grammar -> _GrammarLine_Plus8 _GrammarLine_Plus8 -> GrammarLine @@ -113,14 +115,14 @@ Augmented -> Grammar eof pub type GrammarRule = ::rusty_lr_core::ProductionRule; #[doc = r" type alias for DFA state"] #[allow(non_camel_case_types, dead_code)] -pub type GrammarState = ::rusty_lr_core::State; +pub type GrammarState = ::rusty_lr_core::lr::State; #[doc = r" type alias for `ParseError`"] #[allow(non_camel_case_types, dead_code)] pub type GrammarParseError = - ::rusty_lr_core::ParseError; + ::rusty_lr_core::lr::ParseError; #[doc = r" type alias for `InvalidTerminalError`"] #[allow(non_camel_case_types, dead_code)] -pub type GrammarInvalidTerminalError = ::rusty_lr_core::InvalidTerminalError; +pub type GrammarInvalidTerminalError = ::rusty_lr_core::lr::InvalidTerminalError; #[doc = r" An enum that represents non-terminal symbols"] #[allow(non_camel_case_types)] #[derive( @@ -162,6 +164,7 @@ pub enum GrammarNonTerminals { ReduceDef, ErrorDef, ModulePrefixDef, + GLR, DeriveDef, GrammarLine, Grammar, @@ -199,6 +202,7 @@ impl std::fmt::Display for GrammarNonTerminals { GrammarNonTerminals::ReduceDef => write!(f, "ReduceDef"), GrammarNonTerminals::ErrorDef => write!(f, "ErrorDef"), GrammarNonTerminals::ModulePrefixDef => write!(f, "ModulePrefixDef"), + GrammarNonTerminals::GLR => write!(f, "GLR"), GrammarNonTerminals::DeriveDef => write!(f, "DeriveDef"), GrammarNonTerminals::GrammarLine => write!(f, "GrammarLine"), GrammarNonTerminals::Grammar => write!(f, "Grammar"), @@ -279,6 +283,7 @@ impl GrammarContext { } fn reduce_Rule_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -310,6 +315,7 @@ impl GrammarContext { } fn reduce_RuleType_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut parengroup = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -324,6 +330,7 @@ impl GrammarContext { } fn reduce_RuleType_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { self.__rustylr_generated_stack_2.push({ None }); @@ -331,6 +338,7 @@ impl GrammarContext { } fn reduce_RuleLines_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut RuleLine = self.__rustylr_generated_stack_4.pop().unwrap(); @@ -347,6 +355,7 @@ impl GrammarContext { } fn reduce_RuleLines_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut RuleLine = self.__rustylr_generated_stack_4.pop().unwrap(); @@ -355,6 +364,7 @@ impl GrammarContext { } fn reduce_RuleLine_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut Action = self.__rustylr_generated_stack_2.pop().unwrap(); @@ -370,6 +380,7 @@ impl GrammarContext { } fn reduce__TokenMapped_Plus0_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_stack_6.pop().unwrap(); @@ -378,6 +389,7 @@ impl GrammarContext { } fn reduce__TokenMapped_Plus0_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_stack_6.pop().unwrap(); @@ -390,6 +402,7 @@ impl GrammarContext { } fn reduce__TokenMapped_Star1_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut Ap = self.__rustylr_generated_stack_5.pop().unwrap(); @@ -398,6 +411,7 @@ impl GrammarContext { } fn reduce__TokenMapped_Star1_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { self.__rustylr_generated_stack_5.push({ vec![] }); @@ -405,6 +419,7 @@ impl GrammarContext { } fn reduce_TokenMapped_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut Pattern = self.__rustylr_generated_stack_11.pop().unwrap(); @@ -413,6 +428,7 @@ impl GrammarContext { } fn reduce_TokenMapped_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut Pattern = self.__rustylr_generated_stack_11.pop().unwrap(); @@ -429,6 +445,7 @@ impl GrammarContext { } fn reduce_TerminalSetItem_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut ident = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -444,6 +461,7 @@ impl GrammarContext { } fn reduce_TerminalSetItem_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut last = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -466,6 +484,7 @@ impl GrammarContext { } fn reduce_TerminalSet_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut rbracket = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -494,6 +513,7 @@ impl GrammarContext { } fn reduce__caret_Option2_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -502,6 +522,7 @@ impl GrammarContext { } fn reduce__caret_Option2_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { self.__rustylr_generated_stack_9.push({ None }); @@ -509,6 +530,7 @@ impl GrammarContext { } fn reduce__TerminalSetItem_Plus3_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_stack_7.pop().unwrap(); @@ -517,6 +539,7 @@ impl GrammarContext { } fn reduce__TerminalSetItem_Plus3_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_stack_7.pop().unwrap(); @@ -529,6 +552,7 @@ impl GrammarContext { } fn reduce__TerminalSetItem_Star4_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut Ap = self.__rustylr_generated_stack_10.pop().unwrap(); @@ -537,6 +561,7 @@ impl GrammarContext { } fn reduce__TerminalSetItem_Star4_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { self.__rustylr_generated_stack_10.push({ vec![] }); @@ -544,6 +569,7 @@ impl GrammarContext { } fn reduce_Pattern_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut ident = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -558,6 +584,7 @@ impl GrammarContext { } fn reduce_Pattern_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut plus = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -573,6 +600,7 @@ impl GrammarContext { } fn reduce_Pattern_2( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut star = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -588,6 +616,7 @@ impl GrammarContext { } fn reduce_Pattern_3( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut question = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -603,6 +632,7 @@ impl GrammarContext { } fn reduce_Pattern_4( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut exclamation = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -618,6 +648,7 @@ impl GrammarContext { } fn reduce_Pattern_5( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut TerminalSet = self.__rustylr_generated_stack_8.pop().unwrap(); @@ -627,6 +658,7 @@ impl GrammarContext { } fn reduce_Pattern_6( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut TerminalSetOrIdent = self.__rustylr_generated_stack_18.pop().unwrap(); @@ -638,6 +670,7 @@ impl GrammarContext { } fn reduce_Pattern_7( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut rparen = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -660,6 +693,7 @@ impl GrammarContext { } fn reduce__Pattern_Plus5_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_stack_11.pop().unwrap(); @@ -668,6 +702,7 @@ impl GrammarContext { } fn reduce__Pattern_Plus5_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_stack_11.pop().unwrap(); @@ -680,6 +715,7 @@ impl GrammarContext { } fn reduce_Action_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut bracegroup = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -694,6 +730,7 @@ impl GrammarContext { } fn reduce_Action_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { self.__rustylr_generated_stack_2.push({ None }); @@ -701,6 +738,7 @@ impl GrammarContext { } fn reduce_TokenDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -718,6 +756,7 @@ impl GrammarContext { } fn reduce_RustCode_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut t = self.__rustylr_generated_stack_15.pop().unwrap(); @@ -732,6 +771,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -740,6 +780,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -748,6 +789,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_2( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -756,6 +798,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_3( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -764,6 +807,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_4( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -772,6 +816,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_5( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -780,6 +825,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_6( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -788,6 +834,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_7( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -796,6 +843,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_8( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -804,6 +852,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_9( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -812,6 +861,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_10( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -820,6 +870,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_11( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -828,6 +879,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_12( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -836,6 +888,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_13( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -844,6 +897,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_14( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -852,6 +906,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_15( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -860,6 +915,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_16( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -868,6 +924,7 @@ impl GrammarContext { } fn reduce__TerminalSet6_17( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut term = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -876,6 +933,7 @@ impl GrammarContext { } fn reduce___TerminalSet6_Plus7_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -884,6 +942,7 @@ impl GrammarContext { } fn reduce___TerminalSet6_Plus7_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut A = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -896,6 +955,7 @@ impl GrammarContext { } fn reduce_StartDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -912,6 +972,7 @@ impl GrammarContext { } fn reduce_EofDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -923,6 +984,7 @@ impl GrammarContext { } fn reduce_TokenTypeDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -934,6 +996,7 @@ impl GrammarContext { } fn reduce_UserDataDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -945,6 +1008,7 @@ impl GrammarContext { } fn reduce_TerminalSetOrIdent_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut TerminalSet = self.__rustylr_generated_stack_8.pop().unwrap(); @@ -954,6 +1018,7 @@ impl GrammarContext { } fn reduce_TerminalSetOrIdent_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut ident = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -968,6 +1033,7 @@ impl GrammarContext { } fn reduce_ReduceType_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut left = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -976,6 +1042,7 @@ impl GrammarContext { } fn reduce_ReduceType_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut right = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -985,6 +1052,7 @@ impl GrammarContext { } fn reduce_ReduceDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -996,6 +1064,7 @@ impl GrammarContext { } fn reduce_ErrorDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -1007,6 +1076,7 @@ impl GrammarContext { } fn reduce_ModulePrefixDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -1016,8 +1086,18 @@ impl GrammarContext { .push({ (moduleprefix.span(), RustCode) }); Ok(()) } + fn reduce_GLR_0( + &mut self, + lookahead: &Lexed, + data: &mut GrammarArgs, + ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { + let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); + let mut glr = self.__rustylr_generated_terminal_stack.pop().unwrap(); + Ok(()) + } fn reduce_DeriveDef_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut semicolon = self.__rustylr_generated_terminal_stack.pop().unwrap(); @@ -1028,6 +1108,7 @@ impl GrammarContext { } fn reduce_GrammarLine_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut Rule = self.__rustylr_generated_stack_1.pop().unwrap(); @@ -1038,6 +1119,7 @@ impl GrammarContext { } fn reduce_GrammarLine_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut TokenDef = self.__rustylr_generated_stack_13.pop().unwrap(); @@ -1048,6 +1130,7 @@ impl GrammarContext { } fn reduce_GrammarLine_2( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut StartDef = self.__rustylr_generated_stack_16.pop().unwrap(); @@ -1058,6 +1141,7 @@ impl GrammarContext { } fn reduce_GrammarLine_3( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut EofDef = self.__rustylr_generated_stack_17.pop().unwrap(); @@ -1068,6 +1152,7 @@ impl GrammarContext { } fn reduce_GrammarLine_4( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut TokenTypeDef = self.__rustylr_generated_stack_17.pop().unwrap(); @@ -1078,6 +1163,7 @@ impl GrammarContext { } fn reduce_GrammarLine_5( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut UserDataDef = self.__rustylr_generated_stack_17.pop().unwrap(); @@ -1088,6 +1174,7 @@ impl GrammarContext { } fn reduce_GrammarLine_6( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut ReduceDef = self.__rustylr_generated_stack_20.pop().unwrap(); @@ -1098,6 +1185,7 @@ impl GrammarContext { } fn reduce_GrammarLine_7( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut ErrorDef = self.__rustylr_generated_stack_17.pop().unwrap(); @@ -1108,6 +1196,7 @@ impl GrammarContext { } fn reduce_GrammarLine_8( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut ModulePrefixDef = self.__rustylr_generated_stack_17.pop().unwrap(); @@ -1118,6 +1207,17 @@ impl GrammarContext { } fn reduce_GrammarLine_9( &mut self, + lookahead: &Lexed, + data: &mut GrammarArgs, + ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { + { + data.glr = true; + } + Ok(()) + } + fn reduce_GrammarLine_10( + &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { let mut DeriveDef = self.__rustylr_generated_stack_14.pop().unwrap(); @@ -1128,299 +1228,145 @@ impl GrammarContext { } fn reduce_Grammar_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { Ok(()) } fn reduce__GrammarLine_Plus8_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { Ok(()) } fn reduce__GrammarLine_Plus8_1( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { Ok(()) } fn reduce_Augmented_0( &mut self, + lookahead: &Lexed, data: &mut GrammarArgs, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { self.__rustylr_generated_terminal_stack.pop(); Ok(()) } - #[doc = r" reduce items in stack, this function is called automatically by parser"] - pub fn reduce( + #[doc = r" pop value from start rule"] + #[inline] + pub fn accept(&mut self) {} +} +impl ::rusty_lr_core::lr::Context for GrammarContext { + type Term = Lexed; + type ReduceActionError = ::rusty_lr_core::DefaultReduceActionError; + type UserData = GrammarArgs; + fn reduce( &mut self, - rulelen: usize, rustylr_macro_generated_ruleid__: usize, data: &mut GrammarArgs, + lookahead: &Lexed, ) -> Result<(), ::rusty_lr_core::DefaultReduceActionError> { match rustylr_macro_generated_ruleid__ { - 0usize => { - self.reduce_Rule_0(data)?; - } - 1usize => { - self.reduce_RuleType_0(data)?; - } - 2usize => { - self.reduce_RuleType_1(data)?; - } - 3usize => { - self.reduce_RuleLines_0(data)?; - } - 4usize => { - self.reduce_RuleLines_1(data)?; - } - 5usize => { - self.reduce_RuleLine_0(data)?; - } - 6usize => { - self.reduce__TokenMapped_Plus0_0(data)?; - } - 7usize => { - self.reduce__TokenMapped_Plus0_1(data)?; - } - 8usize => { - self.reduce__TokenMapped_Star1_0(data)?; - } - 9usize => { - self.reduce__TokenMapped_Star1_1(data)?; - } - 10usize => { - self.reduce_TokenMapped_0(data)?; - } - 11usize => { - self.reduce_TokenMapped_1(data)?; - } - 12usize => { - self.reduce_TerminalSetItem_0(data)?; - } - 13usize => { - self.reduce_TerminalSetItem_1(data)?; - } - 14usize => { - self.reduce_TerminalSet_0(data)?; - } - 15usize => { - self.reduce__caret_Option2_0(data)?; - } - 16usize => { - self.reduce__caret_Option2_1(data)?; - } - 17usize => { - self.reduce__TerminalSetItem_Plus3_0(data)?; - } - 18usize => { - self.reduce__TerminalSetItem_Plus3_1(data)?; - } - 19usize => { - self.reduce__TerminalSetItem_Star4_0(data)?; - } - 20usize => { - self.reduce__TerminalSetItem_Star4_1(data)?; - } - 21usize => { - self.reduce_Pattern_0(data)?; - } - 22usize => { - self.reduce_Pattern_1(data)?; - } - 23usize => { - self.reduce_Pattern_2(data)?; - } - 24usize => { - self.reduce_Pattern_3(data)?; - } - 25usize => { - self.reduce_Pattern_4(data)?; - } - 26usize => { - self.reduce_Pattern_5(data)?; - } - 27usize => { - self.reduce_Pattern_6(data)?; - } - 28usize => { - self.reduce_Pattern_7(data)?; - } - 29usize => { - self.reduce__Pattern_Plus5_0(data)?; - } - 30usize => { - self.reduce__Pattern_Plus5_1(data)?; - } - 31usize => { - self.reduce_Action_0(data)?; - } - 32usize => { - self.reduce_Action_1(data)?; - } - 33usize => { - self.reduce_TokenDef_0(data)?; - } - 34usize => { - self.reduce_RustCode_0(data)?; - } - 35usize => { - self.reduce__TerminalSet6_0(data)?; - } - 36usize => { - self.reduce__TerminalSet6_1(data)?; - } - 37usize => { - self.reduce__TerminalSet6_2(data)?; - } - 38usize => { - self.reduce__TerminalSet6_3(data)?; - } - 39usize => { - self.reduce__TerminalSet6_4(data)?; - } - 40usize => { - self.reduce__TerminalSet6_5(data)?; - } - 41usize => { - self.reduce__TerminalSet6_6(data)?; - } - 42usize => { - self.reduce__TerminalSet6_7(data)?; - } - 43usize => { - self.reduce__TerminalSet6_8(data)?; - } - 44usize => { - self.reduce__TerminalSet6_9(data)?; - } - 45usize => { - self.reduce__TerminalSet6_10(data)?; - } - 46usize => { - self.reduce__TerminalSet6_11(data)?; - } - 47usize => { - self.reduce__TerminalSet6_12(data)?; - } - 48usize => { - self.reduce__TerminalSet6_13(data)?; - } - 49usize => { - self.reduce__TerminalSet6_14(data)?; - } - 50usize => { - self.reduce__TerminalSet6_15(data)?; - } - 51usize => { - self.reduce__TerminalSet6_16(data)?; - } - 52usize => { - self.reduce__TerminalSet6_17(data)?; - } - 53usize => { - self.reduce___TerminalSet6_Plus7_0(data)?; - } - 54usize => { - self.reduce___TerminalSet6_Plus7_1(data)?; - } - 55usize => { - self.reduce_StartDef_0(data)?; - } - 56usize => { - self.reduce_EofDef_0(data)?; - } - 57usize => { - self.reduce_TokenTypeDef_0(data)?; - } - 58usize => { - self.reduce_UserDataDef_0(data)?; - } - 59usize => { - self.reduce_TerminalSetOrIdent_0(data)?; - } - 60usize => { - self.reduce_TerminalSetOrIdent_1(data)?; - } - 61usize => { - self.reduce_ReduceType_0(data)?; - } - 62usize => { - self.reduce_ReduceType_1(data)?; - } - 63usize => { - self.reduce_ReduceDef_0(data)?; - } - 64usize => { - self.reduce_ErrorDef_0(data)?; - } - 65usize => { - self.reduce_ModulePrefixDef_0(data)?; - } - 66usize => { - self.reduce_DeriveDef_0(data)?; - } - 67usize => { - self.reduce_GrammarLine_0(data)?; - } - 68usize => { - self.reduce_GrammarLine_1(data)?; - } - 69usize => { - self.reduce_GrammarLine_2(data)?; - } - 70usize => { - self.reduce_GrammarLine_3(data)?; - } - 71usize => { - self.reduce_GrammarLine_4(data)?; - } - 72usize => { - self.reduce_GrammarLine_5(data)?; - } - 73usize => { - self.reduce_GrammarLine_6(data)?; - } - 74usize => { - self.reduce_GrammarLine_7(data)?; - } - 75usize => { - self.reduce_GrammarLine_8(data)?; - } - 76usize => { - self.reduce_GrammarLine_9(data)?; - } - 77usize => { - self.reduce_Grammar_0(data)?; - } - 78usize => { - self.reduce__GrammarLine_Plus8_0(data)?; - } - 79usize => { - self.reduce__GrammarLine_Plus8_1(data)?; - } - 80usize => { - self.reduce_Augmented_0(data)?; - } + 0usize => self.reduce_Rule_0(lookahead, data), + 1usize => self.reduce_RuleType_0(lookahead, data), + 2usize => self.reduce_RuleType_1(lookahead, data), + 3usize => self.reduce_RuleLines_0(lookahead, data), + 4usize => self.reduce_RuleLines_1(lookahead, data), + 5usize => self.reduce_RuleLine_0(lookahead, data), + 6usize => self.reduce__TokenMapped_Plus0_0(lookahead, data), + 7usize => self.reduce__TokenMapped_Plus0_1(lookahead, data), + 8usize => self.reduce__TokenMapped_Star1_0(lookahead, data), + 9usize => self.reduce__TokenMapped_Star1_1(lookahead, data), + 10usize => self.reduce_TokenMapped_0(lookahead, data), + 11usize => self.reduce_TokenMapped_1(lookahead, data), + 12usize => self.reduce_TerminalSetItem_0(lookahead, data), + 13usize => self.reduce_TerminalSetItem_1(lookahead, data), + 14usize => self.reduce_TerminalSet_0(lookahead, data), + 15usize => self.reduce__caret_Option2_0(lookahead, data), + 16usize => self.reduce__caret_Option2_1(lookahead, data), + 17usize => self.reduce__TerminalSetItem_Plus3_0(lookahead, data), + 18usize => self.reduce__TerminalSetItem_Plus3_1(lookahead, data), + 19usize => self.reduce__TerminalSetItem_Star4_0(lookahead, data), + 20usize => self.reduce__TerminalSetItem_Star4_1(lookahead, data), + 21usize => self.reduce_Pattern_0(lookahead, data), + 22usize => self.reduce_Pattern_1(lookahead, data), + 23usize => self.reduce_Pattern_2(lookahead, data), + 24usize => self.reduce_Pattern_3(lookahead, data), + 25usize => self.reduce_Pattern_4(lookahead, data), + 26usize => self.reduce_Pattern_5(lookahead, data), + 27usize => self.reduce_Pattern_6(lookahead, data), + 28usize => self.reduce_Pattern_7(lookahead, data), + 29usize => self.reduce__Pattern_Plus5_0(lookahead, data), + 30usize => self.reduce__Pattern_Plus5_1(lookahead, data), + 31usize => self.reduce_Action_0(lookahead, data), + 32usize => self.reduce_Action_1(lookahead, data), + 33usize => self.reduce_TokenDef_0(lookahead, data), + 34usize => self.reduce_RustCode_0(lookahead, data), + 35usize => self.reduce__TerminalSet6_0(lookahead, data), + 36usize => self.reduce__TerminalSet6_1(lookahead, data), + 37usize => self.reduce__TerminalSet6_2(lookahead, data), + 38usize => self.reduce__TerminalSet6_3(lookahead, data), + 39usize => self.reduce__TerminalSet6_4(lookahead, data), + 40usize => self.reduce__TerminalSet6_5(lookahead, data), + 41usize => self.reduce__TerminalSet6_6(lookahead, data), + 42usize => self.reduce__TerminalSet6_7(lookahead, data), + 43usize => self.reduce__TerminalSet6_8(lookahead, data), + 44usize => self.reduce__TerminalSet6_9(lookahead, data), + 45usize => self.reduce__TerminalSet6_10(lookahead, data), + 46usize => self.reduce__TerminalSet6_11(lookahead, data), + 47usize => self.reduce__TerminalSet6_12(lookahead, data), + 48usize => self.reduce__TerminalSet6_13(lookahead, data), + 49usize => self.reduce__TerminalSet6_14(lookahead, data), + 50usize => self.reduce__TerminalSet6_15(lookahead, data), + 51usize => self.reduce__TerminalSet6_16(lookahead, data), + 52usize => self.reduce__TerminalSet6_17(lookahead, data), + 53usize => self.reduce___TerminalSet6_Plus7_0(lookahead, data), + 54usize => self.reduce___TerminalSet6_Plus7_1(lookahead, data), + 55usize => self.reduce_StartDef_0(lookahead, data), + 56usize => self.reduce_EofDef_0(lookahead, data), + 57usize => self.reduce_TokenTypeDef_0(lookahead, data), + 58usize => self.reduce_UserDataDef_0(lookahead, data), + 59usize => self.reduce_TerminalSetOrIdent_0(lookahead, data), + 60usize => self.reduce_TerminalSetOrIdent_1(lookahead, data), + 61usize => self.reduce_ReduceType_0(lookahead, data), + 62usize => self.reduce_ReduceType_1(lookahead, data), + 63usize => self.reduce_ReduceDef_0(lookahead, data), + 64usize => self.reduce_ErrorDef_0(lookahead, data), + 65usize => self.reduce_ModulePrefixDef_0(lookahead, data), + 66usize => self.reduce_GLR_0(lookahead, data), + 67usize => self.reduce_DeriveDef_0(lookahead, data), + 68usize => self.reduce_GrammarLine_0(lookahead, data), + 69usize => self.reduce_GrammarLine_1(lookahead, data), + 70usize => self.reduce_GrammarLine_2(lookahead, data), + 71usize => self.reduce_GrammarLine_3(lookahead, data), + 72usize => self.reduce_GrammarLine_4(lookahead, data), + 73usize => self.reduce_GrammarLine_5(lookahead, data), + 74usize => self.reduce_GrammarLine_6(lookahead, data), + 75usize => self.reduce_GrammarLine_7(lookahead, data), + 76usize => self.reduce_GrammarLine_8(lookahead, data), + 77usize => self.reduce_GrammarLine_9(lookahead, data), + 78usize => self.reduce_GrammarLine_10(lookahead, data), + 79usize => self.reduce_Grammar_0(lookahead, data), + 80usize => self.reduce__GrammarLine_Plus8_0(lookahead, data), + 81usize => self.reduce__GrammarLine_Plus8_1(lookahead, data), + 82usize => self.reduce_Augmented_0(lookahead, data), _ => { unreachable!("Invalid Rule: {}", rustylr_macro_generated_ruleid__); } } - Ok(()) } - #[doc = r" pop value from start rule"] - #[inline] - pub fn accept(&mut self) {} - #[doc = r" push terminal symbol to stack, this function is called automatically by parser"] - #[inline] - pub fn push(&mut self, term: Lexed) { + fn push(&mut self, term: Lexed) { self.__rustylr_generated_terminal_stack.push(term); } -} -impl ::rusty_lr_core::GetContext for GrammarContext { fn get_state_stack(&self) -> &[usize] { &self.state_stack } + fn get_state_stack_mut(&mut self) -> &mut Vec { + &mut self.state_stack + } } #[doc = r" struct that holds parser data, DFA tables"] #[allow( @@ -1430,13 +1376,22 @@ impl ::rusty_lr_core::GetContext for GrammarContext non_snake_case, unused_mut )] -#[derive(Clone)] pub struct GrammarParser { #[doc = r" production rules"] pub rules: Vec, #[doc = r" states"] pub states: Vec, } +impl ::rusty_lr_core::lr::Parser for GrammarParser { + type Term = Lexed; + type NonTerm = GrammarNonTerminals; + fn get_rules(&self) -> &[GrammarRule] { + &self.rules + } + fn get_states(&self) -> &[GrammarState] { + &self.states + } +} #[allow( unused_braces, unused_parens, @@ -1452,60 +1407,13 @@ impl GrammarParser { term: Lexed, data: &mut GrammarArgs, ) -> Result<(), GrammarParseError> { - self.lookahead(context, &term, data)?; - let state = &self.states[*context.state_stack.last().unwrap()]; - if let Some(next_state_id) = state.shift_goto_term(&term) { - context.state_stack.push(next_state_id); - context.push(term); - Ok(()) - } else { - let error = GrammarInvalidTerminalError { - term, - expected: state.expected().into_iter().cloned().collect(), - }; - Err(GrammarParseError::InvalidTerminal(error)) - } + ::rusty_lr_core::lr::feed(self, context, term, data) } #[doc = r" Create new context for parsing"] #[inline] pub fn begin(&self) -> GrammarContext { GrammarContext::new() } - #[doc = r" give lookahead token to parser, and check if there is any reduce action"] - fn lookahead( - &self, - context: &mut GrammarContext, - term: &Lexed, - data: &mut GrammarArgs, - ) -> Result<(), GrammarParseError> { - let state = &self.states[*context.state_stack.last().unwrap()]; - if let Some(reduce_rule) = state.reduce(term) { - let rule = &self.rules[reduce_rule]; - context - .state_stack - .truncate(context.state_stack.len() - rule.rule.len()); - context - .reduce(self.rules[reduce_rule].rule.len(), reduce_rule, data) - .map_err(GrammarParseError::ReduceAction)?; - self.feed_nonterm(context, &rule.name)?; - self.lookahead(context, term, data)?; - } - Ok(()) - } - #[doc = r" feed one non-terminal to parser, and update state stack"] - fn feed_nonterm( - &self, - context: &mut GrammarContext, - nonterm: &GrammarNonTerminals, - ) -> Result<(), GrammarParseError> { - let state = &self.states[*context.state_stack.last().unwrap()]; - if let Some(next_state_id) = state.shift_goto_nonterm(nonterm) { - context.state_stack.push(next_state_id); - } else { - unreachable!("Invalid NonTerminal: {}", nonterm); - } - Ok(()) - } #[doc = r" Create new parser instance."] #[doc = r" Parser can be reused with different context, for multiple parsing."] pub fn new() -> Self { @@ -1544,6 +1452,7 @@ impl GrammarParser { Lexed::UserData(punct!('%'), Ident::new("id", Span::call_site())), Lexed::ErrorType(punct!('%'), Ident::new("id", Span::call_site())), Lexed::ModulePrefix(punct!('%'), Ident::new("id", Span::call_site())), + Lexed::GLR(punct!('%'), Ident::new("id", Span::call_site())), Lexed::Derive(punct!('%'), Ident::new("id", Span::call_site())), Lexed::Eof, ]; @@ -1729,6 +1638,10 @@ impl GrammarParser { ], &[ ::rusty_lr_core::Token::Term(34u16), + ::rusty_lr_core::Token::Term(2u16), + ], + &[ + ::rusty_lr_core::Token::Term(35u16), ::rusty_lr_core::Token::NonTerm(GrammarNonTerminals::RustCode), ::rusty_lr_core::Token::Term(2u16), ], @@ -1755,6 +1668,7 @@ impl GrammarParser { &[::rusty_lr_core::Token::NonTerm( GrammarNonTerminals::ModulePrefixDef, )], + &[::rusty_lr_core::Token::NonTerm(GrammarNonTerminals::GLR)], &[::rusty_lr_core::Token::NonTerm( GrammarNonTerminals::DeriveDef, )], @@ -1770,7 +1684,7 @@ impl GrammarParser { ], &[ ::rusty_lr_core::Token::NonTerm(GrammarNonTerminals::Grammar), - ::rusty_lr_core::Token::Term(35u16), + ::rusty_lr_core::Token::Term(36u16), ], ]; const RUSTYLR_RULES_NAME: &[GrammarNonTerminals] = &[ @@ -1840,6 +1754,7 @@ impl GrammarParser { GrammarNonTerminals::ReduceDef, GrammarNonTerminals::ErrorDef, GrammarNonTerminals::ModulePrefixDef, + GrammarNonTerminals::GLR, GrammarNonTerminals::DeriveDef, GrammarNonTerminals::GrammarLine, GrammarNonTerminals::GrammarLine, @@ -1851,6 +1766,7 @@ impl GrammarParser { GrammarNonTerminals::GrammarLine, GrammarNonTerminals::GrammarLine, GrammarNonTerminals::GrammarLine, + GrammarNonTerminals::GrammarLine, GrammarNonTerminals::Grammar, GrammarNonTerminals::_GrammarLine_Plus8, GrammarNonTerminals::_GrammarLine_Plus8, @@ -1881,6 +1797,7 @@ impl GrammarParser { ], &[ 0u16, 25u16, 26u16, 27u16, 28u16, 29u16, 30u16, 31u16, 32u16, 33u16, 34u16, 35u16, + 36u16, ], &[2u16], &[1u16], @@ -1895,13 +1812,13 @@ impl GrammarParser { &[0u16, 2u16, 3u16, 16u16, 19u16, 23u16], &[2u16, 3u16], &[0u16, 23u16], - &[35u16], + &[36u16], ]; const RUSTYLR_RULESET_SHIFTED0_CACHE: &[&[u16]] = &[ &[ 0u16, 33u16, 55u16, 56u16, 57u16, 58u16, 61u16, 62u16, 63u16, 64u16, 65u16, 66u16, 67u16, 68u16, 69u16, 70u16, 71u16, 72u16, 73u16, 74u16, 75u16, 76u16, 77u16, 78u16, - 79u16, 80u16, + 79u16, 80u16, 81u16, 82u16, ], &[ 34u16, 35u16, 36u16, 37u16, 38u16, 39u16, 40u16, 41u16, 42u16, 43u16, 44u16, 45u16, @@ -1937,22 +1854,24 @@ impl GrammarParser { &[31u16, 32u16], &[ 0u16, 33u16, 55u16, 56u16, 57u16, 58u16, 61u16, 62u16, 63u16, 64u16, 65u16, 66u16, - 67u16, 68u16, 69u16, 70u16, 71u16, 72u16, 73u16, 74u16, 75u16, 76u16, 78u16, 79u16, + 67u16, 68u16, 69u16, 70u16, 71u16, 72u16, 73u16, 74u16, 75u16, 76u16, 77u16, 78u16, + 80u16, 81u16, ], ]; const RUSTYLR_SHIFT_TERM_MAP: &[&[(u16, u16)]] = &[ &[ - (0u16, 31u16), - (25u16, 93u16), - (26u16, 97u16), - (27u16, 101u16), - (28u16, 98u16), + (0u16, 33u16), + (25u16, 95u16), + (26u16, 99u16), + (27u16, 103u16), + (28u16, 100u16), (29u16, 25u16), - (30u16, 105u16), - (31u16, 108u16), + (30u16, 107u16), + (31u16, 110u16), (32u16, 28u16), - (33u16, 94u16), - (34u16, 1u16), + (33u16, 96u16), + (34u16, 31u16), + (35u16, 1u16), ], &[ (0u16, 8u16), @@ -2060,99 +1979,101 @@ impl GrammarParser { ], &[(2u16, 30u16)], &[], - &[(15u16, 32u16)], + &[(2u16, 32u16)], &[], - &[(1u16, 34u16)], - &[(0u16, 35u16), (19u16, 49u16), (23u16, 38u16)], - &[(5u16, 36u16)], - &[(0u16, 37u16), (19u16, 49u16), (23u16, 38u16)], + &[(15u16, 34u16)], &[], - &[(9u16, 39u16)], + &[(1u16, 36u16)], + &[(0u16, 37u16), (19u16, 51u16), (23u16, 40u16)], + &[(5u16, 38u16)], + &[(0u16, 39u16), (19u16, 51u16), (23u16, 40u16)], + &[], + &[(9u16, 41u16)], &[], - &[(0u16, 41u16)], - &[(10u16, 42u16)], &[(0u16, 43u16)], + &[(10u16, 44u16)], + &[(0u16, 45u16)], &[], &[], - &[(0u16, 41u16)], + &[(0u16, 43u16)], &[], - &[(24u16, 48u16)], + &[(24u16, 50u16)], &[], - &[(0u16, 50u16), (19u16, 55u16), (23u16, 51u16)], + &[(0u16, 52u16), (19u16, 57u16), (23u16, 53u16)], &[], - &[(9u16, 39u16)], - &[(0u16, 41u16)], - &[(24u16, 54u16)], + &[(9u16, 41u16)], + &[(0u16, 43u16)], + &[(24u16, 56u16)], &[], - &[(0u16, 50u16), (19u16, 55u16), (23u16, 51u16)], + &[(0u16, 52u16), (19u16, 57u16), (23u16, 53u16)], &[ - (6u16, 58u16), - (7u16, 64u16), - (8u16, 59u16), - (11u16, 57u16), - (12u16, 60u16), + (6u16, 60u16), + (7u16, 66u16), + (8u16, 61u16), + (11u16, 59u16), + (12u16, 62u16), ], &[], &[], &[], - &[(0u16, 61u16), (23u16, 51u16)], + &[(0u16, 63u16), (23u16, 53u16)], &[], &[], &[], &[], &[], &[ - (0u16, 50u16), - (19u16, 55u16), - (20u16, 67u16), - (23u16, 51u16), + (0u16, 52u16), + (19u16, 57u16), + (20u16, 69u16), + (23u16, 53u16), ], &[], &[ - (6u16, 58u16), - (7u16, 64u16), - (8u16, 59u16), - (11u16, 57u16), - (12u16, 60u16), + (6u16, 60u16), + (7u16, 66u16), + (8u16, 61u16), + (11u16, 59u16), + (12u16, 62u16), ], &[ - (0u16, 50u16), - (19u16, 55u16), - (20u16, 70u16), - (23u16, 51u16), + (0u16, 52u16), + (19u16, 57u16), + (20u16, 72u16), + (23u16, 53u16), ], &[], &[ - (6u16, 73u16), - (7u16, 79u16), - (8u16, 74u16), - (11u16, 72u16), - (12u16, 75u16), + (6u16, 75u16), + (7u16, 81u16), + (8u16, 76u16), + (11u16, 74u16), + (12u16, 77u16), ], &[], &[], &[], - &[(0u16, 76u16), (23u16, 38u16)], + &[(0u16, 78u16), (23u16, 40u16)], &[], &[], &[], &[], &[], &[ - (6u16, 73u16), - (7u16, 79u16), - (8u16, 74u16), - (11u16, 72u16), - (12u16, 75u16), + (6u16, 75u16), + (7u16, 81u16), + (8u16, 76u16), + (11u16, 74u16), + (12u16, 77u16), ], &[], - &[(2u16, 92u16), (3u16, 84u16)], - &[(0u16, 35u16), (19u16, 49u16), (23u16, 38u16)], + &[(2u16, 94u16), (3u16, 86u16)], + &[(0u16, 37u16), (19u16, 51u16), (23u16, 40u16)], &[], &[], - &[(0u16, 35u16), (19u16, 49u16), (23u16, 38u16)], + &[(0u16, 37u16), (19u16, 51u16), (23u16, 40u16)], &[], - &[(16u16, 90u16)], + &[(16u16, 92u16)], &[], &[], &[], @@ -2177,13 +2098,13 @@ impl GrammarParser { (17u16, 3u16), (18u16, 11u16), ], - &[(2u16, 96u16)], + &[(2u16, 98u16)], &[], &[], - &[(0u16, 99u16)], - &[(2u16, 100u16)], + &[(0u16, 101u16)], + &[(2u16, 102u16)], &[], - &[(0u16, 102u16)], + &[(0u16, 104u16)], &[ (0u16, 8u16), (1u16, 5u16), @@ -2204,7 +2125,7 @@ impl GrammarParser { (17u16, 3u16), (18u16, 11u16), ], - &[(2u16, 104u16)], + &[(2u16, 106u16)], &[], &[ (0u16, 8u16), @@ -2226,7 +2147,7 @@ impl GrammarParser { (17u16, 3u16), (18u16, 11u16), ], - &[(2u16, 107u16)], + &[(2u16, 109u16)], &[], &[ (0u16, 8u16), @@ -2248,36 +2169,38 @@ impl GrammarParser { (17u16, 3u16), (18u16, 11u16), ], - &[(2u16, 110u16)], + &[(2u16, 112u16)], + &[], &[], &[], &[], &[], - &[(35u16, 115u16)], + &[(36u16, 118u16)], &[], &[ - (0u16, 31u16), - (25u16, 93u16), - (26u16, 97u16), - (27u16, 101u16), - (28u16, 98u16), + (0u16, 33u16), + (25u16, 95u16), + (26u16, 99u16), + (27u16, 103u16), + (28u16, 100u16), (29u16, 25u16), - (30u16, 105u16), - (31u16, 108u16), + (30u16, 107u16), + (31u16, 110u16), (32u16, 28u16), - (33u16, 94u16), - (34u16, 1u16), + (33u16, 96u16), + (34u16, 31u16), + (35u16, 1u16), ], &[], &[], - &[(0u16, 120u16), (23u16, 121u16)], + &[(0u16, 123u16), (23u16, 124u16)], &[], - &[(9u16, 39u16)], - &[(0u16, 41u16)], - &[(24u16, 124u16)], + &[(9u16, 41u16)], + &[(0u16, 43u16)], + &[(24u16, 127u16)], &[], &[], - &[(2u16, 127u16)], + &[(2u16, 130u16)], &[], &[], &[], @@ -2289,20 +2212,21 @@ impl GrammarParser { ]; const RUSTYLR_SHIFT_NONTERM_MAP: &[&[(GrammarNonTerminals, u16)]] = &[ &[ - (GrammarNonTerminals::DeriveDef, 111u16), - (GrammarNonTerminals::EofDef, 112u16), - (GrammarNonTerminals::ErrorDef, 113u16), - (GrammarNonTerminals::Grammar, 114u16), - (GrammarNonTerminals::GrammarLine, 116u16), - (GrammarNonTerminals::ModulePrefixDef, 117u16), - (GrammarNonTerminals::ReduceDef, 118u16), - (GrammarNonTerminals::ReduceType, 119u16), - (GrammarNonTerminals::Rule, 128u16), - (GrammarNonTerminals::StartDef, 129u16), - (GrammarNonTerminals::TokenDef, 130u16), - (GrammarNonTerminals::TokenTypeDef, 131u16), - (GrammarNonTerminals::UserDataDef, 132u16), - (GrammarNonTerminals::_GrammarLine_Plus8, 134u16), + (GrammarNonTerminals::DeriveDef, 113u16), + (GrammarNonTerminals::EofDef, 114u16), + (GrammarNonTerminals::ErrorDef, 115u16), + (GrammarNonTerminals::GLR, 116u16), + (GrammarNonTerminals::Grammar, 117u16), + (GrammarNonTerminals::GrammarLine, 119u16), + (GrammarNonTerminals::ModulePrefixDef, 120u16), + (GrammarNonTerminals::ReduceDef, 121u16), + (GrammarNonTerminals::ReduceType, 122u16), + (GrammarNonTerminals::Rule, 131u16), + (GrammarNonTerminals::StartDef, 132u16), + (GrammarNonTerminals::TokenDef, 133u16), + (GrammarNonTerminals::TokenTypeDef, 134u16), + (GrammarNonTerminals::UserDataDef, 135u16), + (GrammarNonTerminals::_GrammarLine_Plus8, 137u16), ], &[ (GrammarNonTerminals::RustCode, 20u16), @@ -2346,65 +2270,67 @@ impl GrammarParser { ], &[], &[], - &[(GrammarNonTerminals::RuleType, 33u16)], + &[], + &[], + &[(GrammarNonTerminals::RuleType, 35u16)], &[], &[], &[ - (GrammarNonTerminals::Pattern, 81u16), - (GrammarNonTerminals::RuleLine, 82u16), - (GrammarNonTerminals::RuleLines, 83u16), - (GrammarNonTerminals::TerminalSet, 80u16), - (GrammarNonTerminals::TokenMapped, 86u16), - (GrammarNonTerminals::_TokenMapped_Plus0, 87u16), - (GrammarNonTerminals::_TokenMapped_Star1, 89u16), + (GrammarNonTerminals::Pattern, 83u16), + (GrammarNonTerminals::RuleLine, 84u16), + (GrammarNonTerminals::RuleLines, 85u16), + (GrammarNonTerminals::TerminalSet, 82u16), + (GrammarNonTerminals::TokenMapped, 88u16), + (GrammarNonTerminals::_TokenMapped_Plus0, 89u16), + (GrammarNonTerminals::_TokenMapped_Star1, 91u16), ], &[], &[ - (GrammarNonTerminals::Pattern, 71u16), - (GrammarNonTerminals::TerminalSet, 80u16), + (GrammarNonTerminals::Pattern, 73u16), + (GrammarNonTerminals::TerminalSet, 82u16), ], &[], - &[(GrammarNonTerminals::_caret_Option2, 40u16)], + &[(GrammarNonTerminals::_caret_Option2, 42u16)], &[], &[ - (GrammarNonTerminals::TerminalSetItem, 44u16), - (GrammarNonTerminals::_TerminalSetItem_Plus3, 45u16), - (GrammarNonTerminals::_TerminalSetItem_Star4, 47u16), + (GrammarNonTerminals::TerminalSetItem, 46u16), + (GrammarNonTerminals::_TerminalSetItem_Plus3, 47u16), + (GrammarNonTerminals::_TerminalSetItem_Star4, 49u16), ], &[], &[], &[], &[], - &[(GrammarNonTerminals::TerminalSetItem, 46u16)], + &[(GrammarNonTerminals::TerminalSetItem, 48u16)], &[], &[], &[], &[ - (GrammarNonTerminals::Pattern, 56u16), - (GrammarNonTerminals::TerminalSet, 65u16), - (GrammarNonTerminals::_Pattern_Plus5, 69u16), + (GrammarNonTerminals::Pattern, 58u16), + (GrammarNonTerminals::TerminalSet, 67u16), + (GrammarNonTerminals::_Pattern_Plus5, 71u16), ], &[], - &[(GrammarNonTerminals::_caret_Option2, 52u16)], + &[(GrammarNonTerminals::_caret_Option2, 54u16)], &[ - (GrammarNonTerminals::TerminalSetItem, 44u16), - (GrammarNonTerminals::_TerminalSetItem_Plus3, 45u16), - (GrammarNonTerminals::_TerminalSetItem_Star4, 53u16), + (GrammarNonTerminals::TerminalSetItem, 46u16), + (GrammarNonTerminals::_TerminalSetItem_Plus3, 47u16), + (GrammarNonTerminals::_TerminalSetItem_Star4, 55u16), ], &[], &[], &[ - (GrammarNonTerminals::Pattern, 56u16), - (GrammarNonTerminals::TerminalSet, 65u16), - (GrammarNonTerminals::_Pattern_Plus5, 66u16), + (GrammarNonTerminals::Pattern, 58u16), + (GrammarNonTerminals::TerminalSet, 67u16), + (GrammarNonTerminals::_Pattern_Plus5, 68u16), ], &[], &[], &[], &[], &[ - (GrammarNonTerminals::TerminalSet, 62u16), - (GrammarNonTerminals::TerminalSetOrIdent, 63u16), + (GrammarNonTerminals::TerminalSet, 64u16), + (GrammarNonTerminals::TerminalSetOrIdent, 65u16), ], &[], &[], @@ -2412,14 +2338,14 @@ impl GrammarParser { &[], &[], &[ - (GrammarNonTerminals::Pattern, 68u16), - (GrammarNonTerminals::TerminalSet, 65u16), + (GrammarNonTerminals::Pattern, 70u16), + (GrammarNonTerminals::TerminalSet, 67u16), ], &[], &[], &[ - (GrammarNonTerminals::Pattern, 68u16), - (GrammarNonTerminals::TerminalSet, 65u16), + (GrammarNonTerminals::Pattern, 70u16), + (GrammarNonTerminals::TerminalSet, 67u16), ], &[], &[], @@ -2427,8 +2353,8 @@ impl GrammarParser { &[], &[], &[ - (GrammarNonTerminals::TerminalSet, 77u16), - (GrammarNonTerminals::TerminalSetOrIdent, 78u16), + (GrammarNonTerminals::TerminalSet, 79u16), + (GrammarNonTerminals::TerminalSetOrIdent, 80u16), ], &[], &[], @@ -2439,28 +2365,28 @@ impl GrammarParser { &[], &[], &[ - (GrammarNonTerminals::Pattern, 81u16), - (GrammarNonTerminals::RuleLine, 85u16), - (GrammarNonTerminals::TerminalSet, 80u16), - (GrammarNonTerminals::TokenMapped, 86u16), - (GrammarNonTerminals::_TokenMapped_Plus0, 87u16), - (GrammarNonTerminals::_TokenMapped_Star1, 89u16), + (GrammarNonTerminals::Pattern, 83u16), + (GrammarNonTerminals::RuleLine, 87u16), + (GrammarNonTerminals::TerminalSet, 82u16), + (GrammarNonTerminals::TokenMapped, 88u16), + (GrammarNonTerminals::_TokenMapped_Plus0, 89u16), + (GrammarNonTerminals::_TokenMapped_Star1, 91u16), ], &[], &[], &[ - (GrammarNonTerminals::Pattern, 81u16), - (GrammarNonTerminals::TerminalSet, 80u16), - (GrammarNonTerminals::TokenMapped, 88u16), + (GrammarNonTerminals::Pattern, 83u16), + (GrammarNonTerminals::TerminalSet, 82u16), + (GrammarNonTerminals::TokenMapped, 90u16), ], &[], - &[(GrammarNonTerminals::Action, 91u16)], + &[(GrammarNonTerminals::Action, 93u16)], &[], &[], &[], &[], &[ - (GrammarNonTerminals::RustCode, 95u16), + (GrammarNonTerminals::RustCode, 97u16), (GrammarNonTerminals::_TerminalSet6, 22u16), (GrammarNonTerminals::__TerminalSet6_Plus7, 23u16), ], @@ -2472,21 +2398,21 @@ impl GrammarParser { &[], &[], &[ - (GrammarNonTerminals::RustCode, 103u16), + (GrammarNonTerminals::RustCode, 105u16), (GrammarNonTerminals::_TerminalSet6, 22u16), (GrammarNonTerminals::__TerminalSet6_Plus7, 23u16), ], &[], &[], &[ - (GrammarNonTerminals::RustCode, 106u16), + (GrammarNonTerminals::RustCode, 108u16), (GrammarNonTerminals::_TerminalSet6, 22u16), (GrammarNonTerminals::__TerminalSet6_Plus7, 23u16), ], &[], &[], &[ - (GrammarNonTerminals::RustCode, 109u16), + (GrammarNonTerminals::RustCode, 111u16), (GrammarNonTerminals::_TerminalSet6, 22u16), (GrammarNonTerminals::__TerminalSet6_Plus7, 23u16), ], @@ -2497,33 +2423,35 @@ impl GrammarParser { &[], &[], &[], + &[], &[ - (GrammarNonTerminals::DeriveDef, 111u16), - (GrammarNonTerminals::EofDef, 112u16), - (GrammarNonTerminals::ErrorDef, 113u16), - (GrammarNonTerminals::GrammarLine, 116u16), - (GrammarNonTerminals::ModulePrefixDef, 117u16), - (GrammarNonTerminals::ReduceDef, 118u16), - (GrammarNonTerminals::ReduceType, 119u16), - (GrammarNonTerminals::Rule, 128u16), - (GrammarNonTerminals::StartDef, 129u16), - (GrammarNonTerminals::TokenDef, 130u16), - (GrammarNonTerminals::TokenTypeDef, 131u16), - (GrammarNonTerminals::UserDataDef, 132u16), - (GrammarNonTerminals::_GrammarLine_Plus8, 133u16), + (GrammarNonTerminals::DeriveDef, 113u16), + (GrammarNonTerminals::EofDef, 114u16), + (GrammarNonTerminals::ErrorDef, 115u16), + (GrammarNonTerminals::GLR, 116u16), + (GrammarNonTerminals::GrammarLine, 119u16), + (GrammarNonTerminals::ModulePrefixDef, 120u16), + (GrammarNonTerminals::ReduceDef, 121u16), + (GrammarNonTerminals::ReduceType, 122u16), + (GrammarNonTerminals::Rule, 131u16), + (GrammarNonTerminals::StartDef, 132u16), + (GrammarNonTerminals::TokenDef, 133u16), + (GrammarNonTerminals::TokenTypeDef, 134u16), + (GrammarNonTerminals::UserDataDef, 135u16), + (GrammarNonTerminals::_GrammarLine_Plus8, 136u16), ], &[], &[], &[ - (GrammarNonTerminals::TerminalSet, 125u16), - (GrammarNonTerminals::TerminalSetOrIdent, 126u16), + (GrammarNonTerminals::TerminalSet, 128u16), + (GrammarNonTerminals::TerminalSetOrIdent, 129u16), ], &[], - &[(GrammarNonTerminals::_caret_Option2, 122u16)], + &[(GrammarNonTerminals::_caret_Option2, 125u16)], &[ - (GrammarNonTerminals::TerminalSetItem, 44u16), - (GrammarNonTerminals::_TerminalSetItem_Plus3, 45u16), - (GrammarNonTerminals::_TerminalSetItem_Star4, 123u16), + (GrammarNonTerminals::TerminalSetItem, 46u16), + (GrammarNonTerminals::_TerminalSetItem_Plus3, 47u16), + (GrammarNonTerminals::_TerminalSetItem_Star4, 126u16), ], &[], &[], @@ -2560,7 +2488,7 @@ impl GrammarParser { &[(0u16, 51u16)], &[(0u16, 52u16)], &[], - &[(1u16, 66u16)], + &[(1u16, 67u16)], &[(0u16, 53u16)], &[(2u16, 34u16)], &[(0u16, 54u16)], @@ -2570,6 +2498,8 @@ impl GrammarParser { &[], &[], &[(1u16, 64u16)], + &[], + &[(1u16, 66u16)], &[(3u16, 2u16)], &[(3u16, 1u16)], &[], @@ -2650,14 +2580,15 @@ impl GrammarParser { &[], &[], &[(1u16, 58u16)], - &[(1u16, 76u16)], - &[(1u16, 70u16)], - &[(1u16, 74u16)], + &[(1u16, 78u16)], + &[(1u16, 71u16)], + &[(1u16, 75u16)], + &[(1u16, 77u16)], &[], &[], - &[(13u16, 78u16)], - &[(1u16, 75u16)], - &[(1u16, 73u16)], + &[(13u16, 80u16)], + &[(1u16, 76u16)], + &[(1u16, 74u16)], &[], &[(2u16, 60u16)], &[(6u16, 16u16)], @@ -2667,17 +2598,17 @@ impl GrammarParser { &[(2u16, 59u16)], &[], &[(1u16, 63u16)], - &[(1u16, 67u16)], - &[(1u16, 69u16)], &[(1u16, 68u16)], - &[(1u16, 71u16)], + &[(1u16, 70u16)], + &[(1u16, 69u16)], &[(1u16, 72u16)], + &[(1u16, 73u16)], + &[(13u16, 81u16)], &[(13u16, 79u16)], - &[(13u16, 77u16)], ]; const RUSTYLR_RULESET_MAP: &[&[(u16, u16)]] = &[ &[], - &[(66u16, 1u16)], + &[(67u16, 1u16)], &[(35u16, 1u16)], &[(36u16, 1u16)], &[(37u16, 1u16)], @@ -2696,8 +2627,8 @@ impl GrammarParser { &[(50u16, 1u16)], &[(51u16, 1u16)], &[(52u16, 1u16)], - &[(66u16, 2u16)], - &[(66u16, 3u16)], + &[(67u16, 2u16)], + &[(67u16, 3u16)], &[(53u16, 1u16)], &[(34u16, 1u16), (54u16, 1u16)], &[(54u16, 2u16)], @@ -2707,6 +2638,8 @@ impl GrammarParser { &[(64u16, 1u16)], &[(64u16, 2u16)], &[(64u16, 3u16)], + &[(66u16, 1u16)], + &[(66u16, 2u16)], &[(0u16, 1u16)], &[(1u16, 1u16)], &[(0u16, 2u16)], @@ -2815,14 +2748,15 @@ impl GrammarParser { &[(58u16, 1u16)], &[(58u16, 2u16)], &[(58u16, 3u16)], + &[(78u16, 1u16)], + &[(71u16, 1u16)], + &[(75u16, 1u16)], + &[(77u16, 1u16)], + &[(82u16, 1u16)], + &[(82u16, 2u16)], + &[(80u16, 1u16), (81u16, 1u16)], &[(76u16, 1u16)], - &[(70u16, 1u16)], &[(74u16, 1u16)], - &[(80u16, 1u16)], - &[(80u16, 2u16)], - &[(78u16, 1u16), (79u16, 1u16)], - &[(75u16, 1u16)], - &[(73u16, 1u16)], &[(63u16, 1u16)], &[(60u16, 1u16)], &[(14u16, 1u16)], @@ -2832,25 +2766,25 @@ impl GrammarParser { &[(59u16, 1u16)], &[(63u16, 2u16)], &[(63u16, 3u16)], - &[(67u16, 1u16)], - &[(69u16, 1u16)], &[(68u16, 1u16)], - &[(71u16, 1u16)], + &[(70u16, 1u16)], + &[(69u16, 1u16)], &[(72u16, 1u16)], - &[(79u16, 2u16)], - &[(77u16, 1u16)], + &[(73u16, 1u16)], + &[(81u16, 2u16)], + &[(79u16, 1u16)], ]; const RUSTYLR_RULESET_SHIFTED0_MAP: &[u16] = &[ 0u16, 1u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 3u16, 2u16, 1u16, 2u16, 2u16, - 1u16, 2u16, 2u16, 4u16, 2u16, 2u16, 5u16, 2u16, 6u16, 2u16, 7u16, 2u16, 8u16, 2u16, - 2u16, 2u16, 2u16, 9u16, 2u16, 2u16, 2u16, 10u16, 2u16, 7u16, 8u16, 2u16, 2u16, 10u16, - 2u16, 2u16, 2u16, 2u16, 11u16, 2u16, 2u16, 2u16, 2u16, 2u16, 6u16, 2u16, 2u16, 6u16, - 2u16, 2u16, 2u16, 2u16, 2u16, 11u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, - 12u16, 2u16, 2u16, 13u16, 2u16, 14u16, 2u16, 2u16, 2u16, 2u16, 1u16, 2u16, 2u16, 2u16, - 2u16, 2u16, 2u16, 2u16, 1u16, 2u16, 2u16, 1u16, 2u16, 2u16, 1u16, 2u16, 2u16, 2u16, - 2u16, 2u16, 2u16, 2u16, 15u16, 2u16, 2u16, 11u16, 2u16, 7u16, 8u16, 2u16, 2u16, 2u16, - 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, + 1u16, 2u16, 2u16, 2u16, 2u16, 4u16, 2u16, 2u16, 5u16, 2u16, 6u16, 2u16, 7u16, 2u16, + 8u16, 2u16, 2u16, 2u16, 2u16, 9u16, 2u16, 2u16, 2u16, 10u16, 2u16, 7u16, 8u16, 2u16, + 2u16, 10u16, 2u16, 2u16, 2u16, 2u16, 11u16, 2u16, 2u16, 2u16, 2u16, 2u16, 6u16, 2u16, + 2u16, 6u16, 2u16, 2u16, 2u16, 2u16, 2u16, 11u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, + 2u16, 2u16, 12u16, 2u16, 2u16, 13u16, 2u16, 14u16, 2u16, 2u16, 2u16, 2u16, 1u16, 2u16, + 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 1u16, 2u16, 2u16, 1u16, 2u16, 2u16, 1u16, 2u16, + 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 15u16, 2u16, 2u16, 11u16, 2u16, 7u16, 8u16, + 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, 2u16, ]; let states: Vec = RUSTYLR_SHIFT_TERM_MAP .iter() @@ -2920,12 +2854,4 @@ impl GrammarParser { Self { rules, states } } } -impl ::rusty_lr_core::GetParser for GrammarParser { - fn get_rules(&self) -> &[GrammarRule] { - &self.rules - } - fn get_states(&self) -> &[GrammarState] { - &self.states - } -} // ==============================Generated Codes End===============================