diff --git a/cfgrammar/src/lib/yacc/ast.rs b/cfgrammar/src/lib/yacc/ast.rs index b9a4aab60..58bb39b5b 100644 --- a/cfgrammar/src/lib/yacc/ast.rs +++ b/cfgrammar/src/lib/yacc/ast.rs @@ -14,6 +14,7 @@ use crate::Span; /// Contains a `GrammarAST` structure produced from a grammar source file. /// As well as any errors which occurred during the construction of the AST. pub struct ASTWithValidityInfo { + yacc_kind: YaccKind, ast: GrammarAST, errs: Vec, } @@ -25,16 +26,18 @@ impl ASTWithValidityInfo { /// `Ok(YaccGrammar)` or an `Err` which includes these errors. pub fn new(yacc_kind: YaccKind, s: &str) -> Self { let mut errs = Vec::new(); - let ast = match yacc_kind { - YaccKind::Original(_) | YaccKind::Grmtools | YaccKind::Eco => { - let mut yp = YaccParser::new(yacc_kind, s.to_string()); - yp.parse().map_err(|e| errs.extend(e)).ok(); - let mut ast = yp.ast(); - ast.complete_and_validate().map_err(|e| errs.push(e)).ok(); - ast - } + let (ast, yacc_kind) = { + let mut yp = YaccParser::new(yacc_kind, s.to_string()); + yp.parse().map_err(|e| errs.extend(e)).ok(); + let (yacc_kind, mut ast) = yp.finish(); + ast.complete_and_validate().map_err(|e| errs.push(e)).ok(); + (ast, yacc_kind) }; - ASTWithValidityInfo { ast, errs } + ASTWithValidityInfo { + ast, + errs, + yacc_kind, + } } /// Returns a `GrammarAST` constructed as the result of parsing a source file. @@ -55,6 +58,10 @@ impl ASTWithValidityInfo { pub fn errors(&self) -> &[YaccGrammarError] { self.errs.as_slice() } + + pub fn yacc_kind(&self) -> &YaccKind { + &self.yacc_kind + } } /// An AST representing a grammar. This is built up gradually: when it is finished, the diff --git a/cfgrammar/src/lib/yacc/grammar.rs b/cfgrammar/src/lib/yacc/grammar.rs index 8c20196e9..716c66d92 100644 --- a/cfgrammar/src/lib/yacc/grammar.rs +++ b/cfgrammar/src/lib/yacc/grammar.rs @@ -106,12 +106,11 @@ where /// though the actual name is a fresh name that is guaranteed to be unique) that references the /// user defined start rule. pub fn new_with_storaget(yacc_kind: YaccKind, s: &str) -> YaccGrammarResult { - let ast_validation = ast::ASTWithValidityInfo::new(yacc_kind, s); - Self::new_from_ast_with_validity_info(yacc_kind, &ast_validation) + let ast_validation = ast::ASTWithValidityInfo::new(yacc_kind.clone(), s); + Self::new_from_ast_with_validity_info(&ast_validation) } pub fn new_from_ast_with_validity_info( - yacc_kind: YaccKind, ast_validation: &ast::ASTWithValidityInfo, ) -> YaccGrammarResult { if !ast_validation.is_valid() { @@ -149,7 +148,10 @@ where let implicit_rule; let implicit_start_rule; - match yacc_kind { + match ast_validation.yacc_kind() { + YaccKind::SelfDescribing(_) => { + unimplemented!("Concrete YaccKind must be known by this point") + } YaccKind::Original(_) | YaccKind::Grmtools => { implicit_rule = None; implicit_start_rule = None; diff --git a/cfgrammar/src/lib/yacc/mod.rs b/cfgrammar/src/lib/yacc/mod.rs index 8a2bfcd12..df76fecab 100644 --- a/cfgrammar/src/lib/yacc/mod.rs +++ b/cfgrammar/src/lib/yacc/mod.rs @@ -15,7 +15,7 @@ pub use self::{ use serde::{Deserialize, Serialize}; /// The particular Yacc variant this grammar makes use of. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum YaccKind { /// The original Yacc style as documented by @@ -26,6 +26,21 @@ pub enum YaccKind { Grmtools, /// The variant used in the [Eco language composition editor](http://soft-dev.org/src/eco/) Eco, + /// A `SelfDescribing` grammar starts with an initial `%grmtools` directive specifying it's + /// yacckind. + /// + /// For example: + /// ``` yacc + /// %grmtools { + /// yacckind Original(NoAction) + /// } + /// ... + /// ``` + /// + /// The `Option>` value if specified will be used as the default format. + /// If the default kind is `None` and the file does not specify a yacc kind produce a + /// `MissingYaccKind` error. + SelfDescribing(Option>), } #[derive(Clone, Copy, Debug)] diff --git a/cfgrammar/src/lib/yacc/parser.rs b/cfgrammar/src/lib/yacc/parser.rs index 3bac4398e..b92b4e80f 100644 --- a/cfgrammar/src/lib/yacc/parser.rs +++ b/cfgrammar/src/lib/yacc/parser.rs @@ -14,7 +14,7 @@ use std::{ pub type YaccGrammarResult = Result>; -use crate::{Span, Spanned}; +use crate::{yacc::YaccOriginalActionKind, Span, Spanned}; use super::{ ast::{GrammarAST, Symbol}, @@ -33,6 +33,7 @@ pub enum YaccGrammarErrorKind { MissingColon, MissingRightArrow, MismatchedBrace, + MissingGrmtoolsHeader, NonEmptyProduction, PrematureEnd, ProductionNotTerminated, @@ -44,6 +45,7 @@ pub enum YaccGrammarErrorKind { DuplicateImplicitTokensDeclaration, DuplicateExpectDeclaration, DuplicateExpectRRDeclaration, + DuplicateGrmtoolsHeaderKey, DuplicateStartDeclaration, DuplicateActiontypeDeclaration, DuplicateEPP, @@ -51,6 +53,8 @@ pub enum YaccGrammarErrorKind { InvalidString, NoStartRule, UnknownSymbol, + InvalidYaccKind, + InvalidGrmtoolsHeaderKey, InvalidStartRule(String), UnknownRuleRef(String), UnknownToken(String), @@ -88,6 +92,7 @@ impl fmt::Display for YaccGrammarErrorKind { YaccGrammarErrorKind::IncompleteComment => "Incomplete comment", YaccGrammarErrorKind::IncompleteAction => "Incomplete action", YaccGrammarErrorKind::MissingColon => "Missing ':'", + YaccGrammarErrorKind::MissingGrmtoolsHeader => "Missing '%grmtools' header section", YaccGrammarErrorKind::MissingRightArrow => "Missing '->'", YaccGrammarErrorKind::MismatchedBrace => "Mismatched brace", YaccGrammarErrorKind::NonEmptyProduction => "%empty used in non-empty production", @@ -104,6 +109,9 @@ impl fmt::Display for YaccGrammarErrorKind { YaccGrammarErrorKind::DuplicateExpectRRDeclaration => { "Duplicate %expect-rr declaration" } + YaccGrammarErrorKind::DuplicateGrmtoolsHeaderKey => { + "Duplicate header key in %grmtools section" + } YaccGrammarErrorKind::DuplicateImplicitTokensDeclaration => { "Duplicated %implicit_tokens declaration" } @@ -118,9 +126,11 @@ impl fmt::Display for YaccGrammarErrorKind { YaccGrammarErrorKind::InvalidString => "Invalid string", YaccGrammarErrorKind::NoStartRule => return write!(f, "No start rule specified"), YaccGrammarErrorKind::UnknownSymbol => "Unknown symbol, expected a rule or token", + YaccGrammarErrorKind::InvalidGrmtoolsHeaderKey => "Invalid key in %grmtools section", YaccGrammarErrorKind::InvalidStartRule(name) => { return write!(f, "Start rule '{}' does not appear in grammar", name) } + YaccGrammarErrorKind::InvalidYaccKind => "Invalid yacc kind", YaccGrammarErrorKind::UnknownRuleRef(name) => { return write!(f, "Unknown reference to rule '{}'", name) } @@ -229,6 +239,7 @@ impl Spanned for YaccGrammarError { | YaccGrammarErrorKind::IncompleteComment | YaccGrammarErrorKind::IncompleteAction | YaccGrammarErrorKind::MissingColon + | YaccGrammarErrorKind::MissingGrmtoolsHeader | YaccGrammarErrorKind::MissingRightArrow | YaccGrammarErrorKind::MismatchedBrace | YaccGrammarErrorKind::NonEmptyProduction @@ -241,7 +252,9 @@ impl Spanned for YaccGrammarError { | YaccGrammarErrorKind::InvalidString | YaccGrammarErrorKind::NoStartRule | YaccGrammarErrorKind::UnknownSymbol + | YaccGrammarErrorKind::InvalidGrmtoolsHeaderKey | YaccGrammarErrorKind::InvalidStartRule(_) + | YaccGrammarErrorKind::InvalidYaccKind | YaccGrammarErrorKind::UnknownRuleRef(_) | YaccGrammarErrorKind::UnknownToken(_) | YaccGrammarErrorKind::NoPrecForToken(_) @@ -253,6 +266,7 @@ impl Spanned for YaccGrammarError { | YaccGrammarErrorKind::DuplicateImplicitTokensDeclaration | YaccGrammarErrorKind::DuplicateStartDeclaration | YaccGrammarErrorKind::DuplicateActiontypeDeclaration + | YaccGrammarErrorKind::DuplicateGrmtoolsHeaderKey | YaccGrammarErrorKind::DuplicateEPP => SpansKind::DuplicationError, } } @@ -307,10 +321,32 @@ impl YaccParser { pub(crate) fn parse(&mut self) -> YaccGrammarResult { let mut errs: Vec = Vec::new(); + let mut result = self.parse_grmtools_header(0); + + if result.is_ok() { + while let YaccKind::SelfDescribing(default) = &self.yacc_kind { + // Validate that YaccKind was specified + if let Some(default) = default { + self.yacc_kind = *default.clone() + } else { + result = Err(self.mk_error(YaccGrammarErrorKind::InvalidYaccKind, 0)); + break; + } + } + } // We pass around an index into the *bytes* of self.src. We guarantee that at all times // this points to the beginning of a UTF-8 character (since multibyte characters exist, not // every byte within the string is also a valid character). - let mut result = self.parse_declarations(0, &mut errs); + result = self.parse_declarations( + match result { + Ok(i) => i, + Err(e) => { + errs.push(e); + return Err(errs); + } + }, + &mut errs, + ); result = self.parse_rules(match result { Ok(i) => i, Err(e) => { @@ -339,8 +375,105 @@ impl YaccParser { } } - pub(crate) fn ast(self) -> GrammarAST { - self.ast + fn parse_yacckind( + &mut self, + i: usize, + update_yacc_kind: bool, + ) -> Result { + // Compares haystack converted to lowercase to needle (assumed to be lowercase). + fn starts_with_lower(needle: &'static str, haystack: &'_ str) -> bool { + if let Some((prefix, _)) = haystack.split_at_checked(needle.len()) { + prefix.to_lowercase() == needle + } else { + false + } + } + + const YACC_KINDS: [(&str, YaccKind); 5] = [ + ("grmtools", YaccKind::Grmtools), + ( + "original(noaction)", + YaccKind::Original(YaccOriginalActionKind::NoAction), + ), + ( + "original(useraction)", + YaccKind::Original(YaccOriginalActionKind::UserAction), + ), + ( + "original(genericparsetree)", + YaccKind::Original(YaccOriginalActionKind::GenericParseTree), + ), + ("Eco", YaccKind::Eco), + ]; + let j = self.parse_ws(i, false)?; + let s = &self.src[i..]; + for (kind_name, kind) in YACC_KINDS { + if starts_with_lower(kind_name, s) { + if update_yacc_kind { + self.yacc_kind = kind; + } + let end_pos = j + kind_name.len(); + return Ok(end_pos); + } + } + // This strikes me as an interesting case where we know the start pos of the + // invalid yacc kind value, but do not know the end, we could `self.parse_to_eol()`. + Err(self.mk_error(YaccGrammarErrorKind::InvalidYaccKind, i)) + } + + fn parse_grmtools_header(&mut self, mut i: usize) -> Result { + let mut yacc_kind_key_span = None; + let (update_yacc_kind, require_yacc_kind) = + if let YaccKind::SelfDescribing(default) = &self.yacc_kind { + // 1. Override the self.yacc_kind with one in the header. + // 2. Throw an `MissingYaccKind` errors only if default.is_none(). + (true, default.is_none()) + } else { + (false, false) + }; + + i = self.parse_ws(i, true)?; + if let Some(j) = self.lookahead_is("%grmtools", i) { + i = self.parse_ws(j, true)?; + if let Some(j) = self.lookahead_is("{", i) { + i = self.parse_ws(j, true)?; + while self.lookahead_is("}", i).is_none() { + let key_start_pos = i; + let (key_end_pos, key) = self.parse_name(i)?; + i = self.parse_ws(key_end_pos, false)?; + if key == "yacckind" { + let val_end_pos = self.parse_yacckind(i, update_yacc_kind)?; + if let Some(orig) = yacc_kind_key_span { + let dupe = Span::new(key_start_pos, key_end_pos); + return Err(YaccGrammarError { + kind: YaccGrammarErrorKind::DuplicateGrmtoolsHeaderKey, + spans: vec![orig, dupe], + }); + } else { + yacc_kind_key_span = Some(Span::new(key_start_pos, key_end_pos)); + i = self.parse_ws(val_end_pos, true)?; + } + } else { + return Err(YaccGrammarError { + kind: YaccGrammarErrorKind::InvalidGrmtoolsHeaderKey, + spans: vec![Span::new(key_start_pos, key_end_pos)], + }); + } + } + if let Some(i) = self.lookahead_is("}", i) { + return Ok(i); + } + } else if require_yacc_kind { + return Err(self.mk_error(YaccGrammarErrorKind::MissingGrmtoolsHeader, i)); + } + } else if require_yacc_kind { + return Err(self.mk_error(YaccGrammarErrorKind::MissingGrmtoolsHeader, i)); + } + Ok(i) + } + + pub(crate) fn finish(self) -> (YaccKind, GrammarAST) { + (self.yacc_kind, self.ast) } fn parse_declarations( @@ -623,6 +756,9 @@ impl YaccParser { self.ast.start = Some((rn.clone(), span)); } match self.yacc_kind { + YaccKind::SelfDescribing(_) => { + unimplemented!("Concrete YaccKind must be known at this point") + } YaccKind::Original(_) | YaccKind::Eco => { if self.ast.get_rule(&rn).is_none() { self.ast.add_rule( @@ -1011,7 +1147,7 @@ mod test { fn parse(yacc_kind: YaccKind, s: &str) -> Result> { let mut yp = YaccParser::new(yacc_kind, s.to_string()); yp.parse()?; - Ok(yp.ast()) + Ok(yp.finish().1) } fn rule(n: &str) -> Symbol { @@ -2635,4 +2771,152 @@ B"; "; parse(YaccKind::Original(YaccOriginalActionKind::NoAction), src).unwrap(); } + + #[test] + fn test_self_describing_yacckind() { + let srcs = [ + r#"%grmtools { + yacckind Original(NoAction) + } + %% + S: "()";"#, + r#"%grmtools { yacckind Original(NoAction) } + %% + S: "()";"#, + r#"%grmtools {yacckind Original(NoAction)} + %% + S: "()";"#, + r#"%grmtools + {yacckind Original(NoAction)} + %% + S: "()";"#, + r#" + %grmtools { + yacckind Original(UserAction) + } + %% + S: "()";"#, + r#"%grmtools { + yacckind Grmtools + } + %start S + %% + S -> (): "()" { () };"#, + r#"%grmtools { + yacckind grmtools + } + %start S + %% + S -> (): "()" { () };"#, + ]; + for yacc_src in srcs { + parse(YaccKind::SelfDescribing(None), yacc_src).unwrap(); + parse( + YaccKind::SelfDescribing(Some(Box::new(YaccKind::SelfDescribing(None)))), + yacc_src, + ) + .unwrap(); + } + + let fallback_srcs = [ + r#"%start S + %% + S: "()";"#, + r#"%grmtools { + } + %start S + %% + S: "()";"#, + ]; + for yacc_src in fallback_srcs { + parse( + YaccKind::SelfDescribing(Some(Box::new(YaccKind::Original( + YaccOriginalActionKind::NoAction, + )))), + yacc_src, + ) + .unwrap(); + } + } + + #[test] + fn test_self_describing_yacckind_errs() { + let src = r#"%grmtools { + invalid value + } + %% + S: "()";"#; + parse(YaccKind::SelfDescribing(None), src).expect_error_at_line_col( + src, + YaccGrammarErrorKind::InvalidGrmtoolsHeaderKey, + 2, + 33, + ); + + let src = r#"%grmtools { + yacckind Grmtools + yacckind Grmtools + } + %% + S: "()";"#; + parse(YaccKind::SelfDescribing(None), src).expect_error_at_lines_cols( + src, + YaccGrammarErrorKind::DuplicateGrmtoolsHeaderKey, + &mut [(2, 33), (3, 33)].into_iter(), + ); + + let src = r#"%grmtools { + yacckind invalid_yacc_kind + } + %% + S: "()";"#; + parse(YaccKind::SelfDescribing(None), src).expect_error_at_line_col( + src, + YaccGrammarErrorKind::InvalidYaccKind, + 2, + 42, + ); + // Invalid brace after %grmtools [ + let src = r#"%grmtools [ + yacckind Grmtools + } + %% + S: "()";"#; + parse(YaccKind::SelfDescribing(None), src).expect_error_at_line_col( + src, + YaccGrammarErrorKind::MissingGrmtoolsHeader, + 1, + 11, + ); + + // Missing the %grmtools header entirely. + let src = r#"%start S + %% + S: "()";"#; + + parse(YaccKind::SelfDescribing(None), src).expect_error_at_line_col( + src, + YaccGrammarErrorKind::MissingGrmtoolsHeader, + 1, + 1, + ); + // Empty %grmtools header with no yacckind. + let src = r#"%grmtools { + } + %start S + %% + S: "()";"#; + + parse(YaccKind::SelfDescribing(None), src).expect_error_at_line_col( + src, + YaccGrammarErrorKind::InvalidYaccKind, + 1, + 1, + ); + parse( + YaccKind::SelfDescribing(Some(Box::new(YaccKind::SelfDescribing(None)))), + src, + ) + .expect_error_at_line_col(src, YaccGrammarErrorKind::InvalidYaccKind, 1, 1); + } } diff --git a/lrpar/cttests/src/cgen_helper.rs b/lrpar/cttests/src/cgen_helper.rs index b90755574..8f04d4f18 100644 --- a/lrpar/cttests/src/cgen_helper.rs +++ b/lrpar/cttests/src/cgen_helper.rs @@ -18,18 +18,19 @@ pub(crate) fn run_test_path>(path: P) -> Result<(), Box { - YaccKind::Original(YaccOriginalActionKind::NoAction) + let yacckind = match docs[0]["yacckind"].as_str() { + Some("Original(YaccOriginalActionKind::NoAction)") => { + Some(YaccKind::Original(YaccOriginalActionKind::NoAction)) } - "Original(YaccOriginalActionKind::UserAction)" => { - YaccKind::Original(YaccOriginalActionKind::UserAction) + Some("Original(YaccOriginalActionKind::UserAction)") => { + Some(YaccKind::Original(YaccOriginalActionKind::UserAction)) } - "Grmtools" => YaccKind::Grmtools, - "Original(YaccOriginalActionKind::GenericParseTree)" => { - YaccKind::Original(YaccOriginalActionKind::GenericParseTree) + Some("Grmtools") => Some(YaccKind::Grmtools), + Some("Original(YaccOriginalActionKind::GenericParseTree)") => { + Some(YaccKind::Original(YaccOriginalActionKind::GenericParseTree)) } - s => panic!("YaccKind '{}' not supported", s), + None => None, + s => panic!("YaccKind '{:?}' not supported", s), }; let (negative_yacc_flags, positive_yacc_flags) = &docs[0]["yacc_flags"] .as_vec() @@ -88,8 +89,11 @@ pub(crate) fn run_test_path>(path: P) -> Result<(), Box>::new() - .yacckind(yacckind) + let mut cp_build = CTParserBuilder::>::new(); + if let Some(yacckind) = yacckind { + cp_build = cp_build.yacckind(yacckind) + } + cp_build = cp_build .grammar_path(pg.to_str().unwrap()) .output_path(&outp); if let Some(flag) = check_flag(yacc_flags, "error_on_conflicts") { diff --git a/lrpar/examples/calc_actions/src/calc.y b/lrpar/examples/calc_actions/src/calc.y index 41176308f..987419d43 100644 --- a/lrpar/examples/calc_actions/src/calc.y +++ b/lrpar/examples/calc_actions/src/calc.y @@ -1,3 +1,7 @@ +%grmtools { + yacckind Grmtools +} + %start Expr %avoid_insert "INT" %% diff --git a/lrpar/src/lib/ctbuilder.rs b/lrpar/src/lib/ctbuilder.rs index f7003b50c..08bb0bb24 100644 --- a/lrpar/src/lib/ctbuilder.rs +++ b/lrpar/src/lib/ctbuilder.rs @@ -391,7 +391,7 @@ where /// # Panics /// /// If `StorageT` is not big enough to index the grammar's tokens, rules, or productions. - pub fn build(self) -> Result, Box> { + pub fn build(mut self) -> Result, Box> { let grmp = self .grammar_path .as_ref() @@ -400,11 +400,10 @@ where .output_path .as_ref() .expect("output_path must be specified before processing."); - let yk = match self.yacckind { - None => panic!("yacckind must be specified before processing."), - Some(YaccKind::Original(x)) => YaccKind::Original(x), - Some(YaccKind::Grmtools) => YaccKind::Grmtools, + let yk = match self.yacckind.clone() { + None => YaccKind::SelfDescribing(None), Some(YaccKind::Eco) => panic!("Eco compile-time grammar generation not supported."), + Some(x) => x, }; { @@ -417,7 +416,8 @@ where let inc = read_to_string(grmp).map_err(|e| format!("When reading '{}': {e}", grmp.display()))?; - let ast_validation = ASTWithValidityInfo::new(yk, &inc); + let ast_validation = ASTWithValidityInfo::new(yk.clone(), &inc); + self.yacckind = Some(ast_validation.yacc_kind().clone()); let warnings = ast_validation.ast().warnings(); let spanned_fmt = |x: &dyn Spanned, inc: &str, line_cache: &NewlineCache| { if let Some((line, column)) = @@ -429,7 +429,7 @@ where } }; - let res = YaccGrammar::::new_from_ast_with_validity_info(yk, &ast_validation); + let res = YaccGrammar::::new_from_ast_with_validity_info(&ast_validation); let grm = match res { Ok(_) if self.warnings_are_errors && !warnings.is_empty() => { let mut line_cache = NewlineCache::new(); @@ -656,7 +656,7 @@ where output_path: self.output_path.clone(), mod_name: self.mod_name, recoverer: self.recoverer, - yacckind: self.yacckind, + yacckind: self.yacckind.clone(), error_on_conflicts: self.error_on_conflicts, warnings_are_errors: self.warnings_are_errors, show_warnings: self.show_warnings, @@ -696,7 +696,7 @@ where outs.push_str(&self.gen_parse_function(grm, stable)?); outs.push_str(&self.gen_rule_consts(grm)); outs.push_str(&self.gen_token_epp(grm)); - match self.yacckind.unwrap() { + match self.yacckind.clone().unwrap() { YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => { outs.push_str(&self.gen_wrappers(grm)); } @@ -771,7 +771,10 @@ where serialize_bin_output(grm, GRM_CONST_NAME, &mut outs)?; serialize_bin_output(stable, STABLE_CONST_NAME, &mut outs)?; - match self.yacckind.unwrap() { + match self.yacckind.clone().unwrap() { + YaccKind::SelfDescribing(_) => { + unimplemented!("Concrete YaccKind must be known at this point") + } YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => { let parse_param = match grm.parse_param() { Some((name, tyname)) => format!(", {}: {}", name, tyname), @@ -832,7 +835,10 @@ where RecoveryKind::CPCTPlus => "CPCTPlus", RecoveryKind::None => "None", }; - match self.yacckind.unwrap() { + match self.yacckind.clone().unwrap() { + YaccKind::SelfDescribing(_) => { + unimplemented!("Concrete YaccKind must be known at this point") + } YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => { // action function references let wrappers = grm diff --git a/lrtable/src/lib/statetable.rs b/lrtable/src/lib/statetable.rs index 37fdf269f..1a790e0d8 100644 --- a/lrtable/src/lib/statetable.rs +++ b/lrtable/src/lib/statetable.rs @@ -1001,8 +1001,8 @@ D : D; let src = "%% S: S | ;"; let yk = YaccKind::Original(YaccOriginalActionKind::NoAction); - let ast_validity = ASTWithValidityInfo::new(yk, src); - let grm = YaccGrammar::::new_from_ast_with_validity_info(yk, &ast_validity).unwrap(); + let ast_validity = ASTWithValidityInfo::new(yk.clone(), src); + let grm = YaccGrammar::::new_from_ast_with_validity_info(&ast_validity).unwrap(); let sg = pager_stategraph(&grm); match StateTable::new(&grm, &sg) { Ok(_) => panic!("Expected accept reduce conflict"), @@ -1053,8 +1053,8 @@ S: S | ;"; S: T | ; T: S | ;"; let yk = YaccKind::Original(YaccOriginalActionKind::NoAction); - let ast_validity = ASTWithValidityInfo::new(yk, src); - let grm = YaccGrammar::::new_from_ast_with_validity_info(yk, &ast_validity).unwrap(); + let ast_validity = ASTWithValidityInfo::new(yk.clone(), src); + let grm = YaccGrammar::::new_from_ast_with_validity_info(&ast_validity).unwrap(); let sg = pager_stategraph(&grm); match StateTable::new(&grm, &sg) { Ok(_) => panic!("Expected accept reduce conflict"), diff --git a/nimbleparse/src/main.rs b/nimbleparse/src/main.rs index 88683d8dd..35ce7cddc 100644 --- a/nimbleparse/src/main.rs +++ b/nimbleparse/src/main.rs @@ -123,7 +123,9 @@ fn main() { }; let yacckind = match matches.opt_str("y") { - None => YaccKind::Original(YaccOriginalActionKind::GenericParseTree), + None => YaccKind::SelfDescribing(Some(Box::new(YaccKind::Original( + YaccOriginalActionKind::GenericParseTree, + )))), Some(s) => match &*s.to_lowercase() { "eco" => YaccKind::Eco, "grmtools" => YaccKind::Grmtools, @@ -152,9 +154,9 @@ fn main() { let yacc_y_path = PathBuf::from(&matches.free[1]); let yacc_src = read_file(&yacc_y_path); - let ast_validation = ASTWithValidityInfo::new(yacckind, &yacc_src); + let ast_validation = ASTWithValidityInfo::new(yacckind.clone(), &yacc_src); let warnings = ast_validation.ast().warnings(); - let res = YaccGrammar::new_from_ast_with_validity_info(yacckind, &ast_validation); + let res = YaccGrammar::new_from_ast_with_validity_info(&ast_validation); let mut yacc_diagnostic_formatter: Option = None; let grm = match res { Ok(x) => {