From 15cd813be822ea856f44265a3f7fc7a39eecdd1c Mon Sep 17 00:00:00 2001 From: matt rice Date: Tue, 25 Aug 2026 11:11:31 -0700 Subject: [PATCH] Allow crate name in grmtools section entries. This allows entries in the grmtools section to specified including `crate_name.entry_name:` For backwards compatibility it infers the crate name from the known entries. This cannot currently be used by crates outside grmtools without error. In the future this may be relaxed. --- cfgrammar/src/lib/header.rs | 57 +++++++++++++++++++++++-- cfgrammar/src/lib/yacc/ast.rs | 4 +- doc/src/lexextensions.md | 32 +++++++------- doc/src/yaccextensions.md | 8 ++-- lrlex/src/lib/codegen.rs | 4 +- lrlex/src/lib/ctbuilder.rs | 28 ++++++------ lrlex/src/lib/lexer.rs | 36 ++++++++-------- lrlex/src/main.rs | 4 +- lrpar/cttests/src/grmtools_section.test | 29 ++++++++++++- lrpar/src/lib/codegen.rs | 13 +++--- lrpar/src/lib/ctbuilder.rs | 6 +-- nimbleparse/src/main.rs | 24 +++++------ 12 files changed, 161 insertions(+), 84 deletions(-) diff --git a/cfgrammar/src/lib/header.rs b/cfgrammar/src/lib/header.rs index 458f3d864..fcd8963ea 100644 --- a/cfgrammar/src/lib/header.rs +++ b/cfgrammar/src/lib/header.rs @@ -6,7 +6,7 @@ use crate::{ }, }; use regex::{Regex, RegexBuilder}; -use std::{error::Error, fmt, sync::LazyLock}; +use std::{collections::HashMap, error::Error, fmt, sync::LazyLock}; /// An error regarding the `%grmtools` header section. /// @@ -239,13 +239,53 @@ impl Namespaced { static RE_LEADING_WS: LazyLock = LazyLock::new(|| Regex::new(r"^[\p{Pattern_White_Space}]*").unwrap()); static RE_NAME: LazyLock = LazyLock::new(|| { - RegexBuilder::new(r"^[A-Z][A-Z_]*") + RegexBuilder::new(r"^[A-Z][A-Z_\.]*") + .case_insensitive(true) + .build() + .unwrap() +}); +#[doc(hidden)] +pub static RE_CRATE_DOT: LazyLock = LazyLock::new(|| { + RegexBuilder::new(r"^[A-Z][A-Z_]*\.") .case_insensitive(true) .build() .unwrap() }); static RE_DIGITS: LazyLock = LazyLock::new(|| Regex::new(r"^[0-9]+").unwrap()); static RE_STRING: LazyLock = LazyLock::new(|| Regex::new(r#"^\"(\\.|[^"\\])*\""#).unwrap()); +#[doc(hidden)] +pub static CRATE_KEY_MAP: LazyLock> = LazyLock::new(|| { + let mut map = HashMap::new(); + let cfgrammar = ["yacckind"]; + let lrpar = ["recoverer", "test_files", "serialisation_format"]; + + let lrlex = ["lexerkind", "allow_wholeline_comments", "posix_escapes"]; + let regex = [ + "case_insensitive", + "dot_matches_new_line", + "multi_line", + "octal", + "swap_greed", + "ignore_whitespace", + "unicode", + "size_limit", + "dfa_size_limit", + "nest_limit", + ]; + for s in cfgrammar { + map.insert(s, "cfgrammar"); + } + for s in lrpar { + map.insert(s, "lrpar"); + } + for s in lrlex { + map.insert(s, "lrlex"); + } + for s in regex { + map.insert(s, "regex"); + } + map +}); const MAGIC: &str = "%grmtools"; @@ -429,7 +469,18 @@ impl<'input> GrmtoolsSectionParser<'input> { i = self.parse_ws(j); while self.lookahead_is("}", i).is_none() && i < self.src.len() { let (key, key_loc, val, j) = match self.parse_key_value(i) { - Ok((key, key_loc, val, pos)) => (key, key_loc, val, pos), + Ok((key, key_loc, val, pos)) => { + let key = if !RE_CRATE_DOT.is_match(&key) { + if let Some(crate_name) = CRATE_KEY_MAP.get(key.as_str()) { + format!("{crate_name}.{key}") + } else { + key + } + } else { + key + }; + (key, key_loc, val, pos) + } Err(e) => { errs.push(e); return Err(errs); diff --git a/cfgrammar/src/lib/yacc/ast.rs b/cfgrammar/src/lib/yacc/ast.rs index a3ae7415a..fb1ef5cb2 100644 --- a/cfgrammar/src/lib/yacc/ast.rs +++ b/cfgrammar/src/lib/yacc/ast.rs @@ -118,7 +118,7 @@ impl FromStr for ASTWithValidityInfo { let (header, _) = GrmtoolsSectionParser::new(src, true) .parse() .map_err(|mut errs| errs.drain(..).map(|e| e.into()).collect::>())?; - if let Some(HeaderValue(_, yk_val)) = header.get("yacckind") { + if let Some(HeaderValue(_, yk_val)) = header.get("cfgrammar.yacckind") { let yacc_kind = YaccKind::try_from(yk_val).map_err(|e| vec![e.into()])?; let ast = { // We don't want to strip off the header so that span's will be correct. @@ -138,7 +138,7 @@ impl FromStr for ASTWithValidityInfo { } else { Err(vec![ HeaderError { - kind: HeaderErrorKind::InvalidEntry("yacckind"), + kind: HeaderErrorKind::InvalidEntry("cfgrammar.yacckind"), locations: vec![Span::new(0, 0)], } .into(), diff --git a/doc/src/lexextensions.md b/doc/src/lexextensions.md index b6354c2b2..5e7f08c0d 100644 --- a/doc/src/lexextensions.md +++ b/doc/src/lexextensions.md @@ -26,26 +26,26 @@ other flags should specify their value immediately after the flag name. ## List of flags: -| Flag | Value | Required | Regex[^regex] | -|-------------------------------|-----------|----------|---------------| -| `lexerkind` | [LexerKind](lexcompatibility.md#lexerkinds) | ✗ | ✗ | -| `posix_escapes`[^†] | bool | ✗ | ✗ | -| `allow_wholeline_comment`[^‡] | bool | ✗ | ✗ | -| `case_insensitive` | bool | ✗ | ✓ | -| `dot_matches_new_line` | bool | ✗ | ✓ | -| `multi_line` | bool | ✗ | ✓ | -| `octal` | bool | ✗ | ✓ | -| `swap_greed` | bool | ✗ | ✓ | -| `ignore_whitespace` | bool | ✗ | ✓ | -| `unicode` | bool | ✗ | ✓ | -| `size_limit` | usize | ✗ | ✓ | -| `dfa_size_limit` | usize | ✗ | ✓ | -| `nest_limit` | u32 | ✗ | ✓ | +| Flag | Value | Required | +|-------------------------------|-----------|----------| +| `lrlex.lexerkind` | [LexerKind](lexcompatibility.md#lexerkinds) | ✗ | +| `lrlex.posix_escapes`[^†] | bool | ✗ | +| `lrlex.allow_wholeline_comments`[^‡] | bool | ✗ | +| `regex.case_insensitive` | bool | ✗ | +| `regex.dot_matches_new_line` | bool | ✗ | +| `regex.multi_line` | bool | ✗ | +| `regex.octal` | bool | ✗ | +| `regex.swap_greed` | bool | ✗ | +| `regex.ignore_whitespace` | bool | ✗ | +| `regex.unicode` | bool | ✗ | +| `regex.size_limit` | usize | ✗ | +| `regex.dfa_size_limit` | usize | ✗ | +| `regex.nest_limit` | u32 | ✗ | [^†]: Enable compatibility with posix escape sequences. [^‡]: Enables rust style `// comments` at the start of lines. Which requires escaping of `/` when used in a regex. -[^regex]: ✓ Flag gets passed directly to `regex::RegexBuilder`. +[^regex]: Flag gets passed directly to `regex::RegexBuilder`. ## Flags affecting Posix compatibility diff --git a/doc/src/yaccextensions.md b/doc/src/yaccextensions.md index 59cc1c201..0ae957a53 100644 --- a/doc/src/yaccextensions.md +++ b/doc/src/yaccextensions.md @@ -5,10 +5,10 @@ But a default can be set or forced by using a `YaccKindResolver`. | Flag | Value | Required | |------------------|-------------------------------------------------|--------------| -| `yacckind` | [YaccKind](yacccompatibility.md#yacckinds) | ✓ | -| `recoverykind` | [RecoveryKind](errorrecovery.md#recoverykinds) | ✗ | -| `test_files`[^†] | Array of string values | ✗ | -| `serialisation_format`[^⹋] | `lrpar::SerialisationFormat` | ✗ | +| `cfgrammar.yacckind` | [YaccKind](yacccompatibility.md#yacckinds) | ✓ | +| `lrpar.recoverykind` | [RecoveryKind](errorrecovery.md#recoverykinds) | ✗ | +| `lrpar.test_files`[^†] | Array of string values | ✗ | +| `lrpar.serialisation_format`[^⹋] | `lrpar::SerialisationFormat` | ✗ | [^†]: Strings containing globs are resolved relative to the yacc `.y` source file. `test_files` is currently experimental. diff --git a/lrlex/src/lib/codegen.rs b/lrlex/src/lib/codegen.rs index 570745345..73e28bd02 100644 --- a/lrlex/src/lib/codegen.rs +++ b/lrlex/src/lib/codegen.rs @@ -195,11 +195,11 @@ where { self.merge_headers()?; let mod_name = self.resolve_mod_name(&args)?; - self.header.mark_used(&"lexerkind".to_string()); + self.header.mark_used(&"lrlex.lexerkind".to_string()); let lexerkind = match args.lexerkind { Some(lexerkind) => lexerkind, None => { - if let Some(HeaderValue(_, lk_val)) = self.header.get("lexerkind") { + if let Some(HeaderValue(_, lk_val)) = self.header.get("lrlex.lexerkind") { LexerKind::try_from(lk_val)? } else { LexerKind::LRNonStreamingLexer diff --git a/lrlex/src/lib/ctbuilder.rs b/lrlex/src/lib/ctbuilder.rs index 9040a8638..58cad2a37 100644 --- a/lrlex/src/lib/ctbuilder.rs +++ b/lrlex/src/lib/ctbuilder.rs @@ -504,9 +504,9 @@ where .map(|(x, y)| (&**x, *y)) .collect::>(); closure_lexerdef.set_rule_ids(&owned_map); - yacc_header.mark_used(&"test_files".to_string()); + yacc_header.mark_used(&"lrpar.test_files".to_string()); let grammar = rtpb.grammar(); - let test_glob = yacc_header.get("test_files"); + let test_glob = yacc_header.get("lrpar.test_files"); let mut err_str = None; let add_error_line = |err_str: &mut Option, line| { if let Some(err_str) = err_str { @@ -841,7 +841,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn allow_wholeline_comments(mut self, flag: bool) -> Self { - let key = "allow_wholeline_comments".to_string(); + let key = "lrlex.allow_wholeline_comments".to_string(); self.header.insert( key, HeaderValue( @@ -857,7 +857,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn dot_matches_new_line(mut self, flag: bool) -> Self { - let key = "dot_matches_new_line".to_string(); + let key = "regex.dot_matches_new_line".to_string(); self.header.insert( key, HeaderValue( @@ -873,7 +873,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn multi_line(mut self, flag: bool) -> Self { - let key = "multi_line".to_string(); + let key = "regex.multi_line".to_string(); self.header.insert( key, HeaderValue( @@ -889,7 +889,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn posix_escapes(mut self, flag: bool) -> Self { - let key = "posix_escapes".to_string(); + let key = "lrlex.posix_escapes".to_string(); self.header.insert( key, HeaderValue( @@ -905,7 +905,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn octal(mut self, flag: bool) -> Self { - let key = "octal".to_string(); + let key = "regex.octal".to_string(); self.header.insert( key, HeaderValue( @@ -921,7 +921,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn swap_greed(mut self, flag: bool) -> Self { - let key = "swap_greed".to_string(); + let key = "regex.swap_greed".to_string(); self.header.insert( key, HeaderValue( @@ -937,7 +937,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn ignore_whitespace(mut self, flag: bool) -> Self { - let key = "ignore_whitespace".to_string(); + let key = "regex.ignore_whitespace".to_string(); self.header.insert( key, HeaderValue( @@ -953,7 +953,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn unicode(mut self, flag: bool) -> Self { - let key = "unicode".to_string(); + let key = "regex.unicode".to_string(); self.header.insert( key, HeaderValue( @@ -969,7 +969,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn case_insensitive(mut self, flag: bool) -> Self { - let key = "case_insensitive".to_string(); + let key = "regex.case_insensitive".to_string(); self.header.insert( key, HeaderValue( @@ -985,7 +985,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn size_limit(mut self, sz: usize) -> Self { - let key = "size_limit".to_string(); + let key = "regex.size_limit".to_string(); self.header.insert( key, HeaderValue( @@ -1004,7 +1004,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn dfa_size_limit(mut self, sz: usize) -> Self { - let key = "dfa_size_limit".to_string(); + let key = "regex.dfa_size_limit".to_string(); self.header.insert( key, HeaderValue( @@ -1023,7 +1023,7 @@ where /// /// Setting this flag will override the same flag within a `%grmtools` section. pub fn nest_limit(mut self, lim: u32) -> Self { - let key = "nest_limit".to_string(); + let key = "regex.nest_limit".to_string(); self.header.insert( key, HeaderValue( diff --git a/lrlex/src/lib/lexer.rs b/lrlex/src/lib/lexer.rs index 60cd726ca..cc20e9c73 100644 --- a/lrlex/src/lib/lexer.rs +++ b/lrlex/src/lib/lexer.rs @@ -64,9 +64,9 @@ impl TryFrom<&mut Header> for LexFlags { nest_limit, } = &mut lex_flags; macro_rules! cvt_flag { - ($it:ident) => { - header.mark_used(&stringify!($it).to_string()); - *$it = match header.get(stringify!($it)) { + ($prefix:ident, $it:ident) => { + header.mark_used(&stringify!($prefix.$it).to_string()); + *$it = match header.get(stringify!($prefix.$it)) { Some(HeaderValue(_, Value::Flag(flag, _))) => Some(*flag), Some(HeaderValue(loc, _)) => Err(HeaderError { kind: HeaderErrorKind::ConversionError("LexFlags", "Expected boolean"), @@ -76,19 +76,19 @@ impl TryFrom<&mut Header> for LexFlags { } }; } - cvt_flag!(dot_matches_new_line); - cvt_flag!(multi_line); - cvt_flag!(octal); - cvt_flag!(posix_escapes); - cvt_flag!(allow_wholeline_comments); - cvt_flag!(case_insensitive); - cvt_flag!(swap_greed); - cvt_flag!(ignore_whitespace); - cvt_flag!(unicode); + cvt_flag!(regex, dot_matches_new_line); + cvt_flag!(regex, multi_line); + cvt_flag!(regex, octal); + cvt_flag!(lrlex, posix_escapes); + cvt_flag!(lrlex, allow_wholeline_comments); + cvt_flag!(regex, case_insensitive); + cvt_flag!(regex, swap_greed); + cvt_flag!(regex, ignore_whitespace); + cvt_flag!(regex, unicode); macro_rules! cvt_num { - ($it:ident, $num_ty: ty) => { - header.mark_used(&stringify!($it).to_string()); - *$it = match header.get(stringify!($it)) { + ($prefix:ident, $it:ident, $num_ty: ty) => { + header.mark_used(&stringify!($prefix.$it).to_string()); + *$it = match header.get(stringify!($prefix.$it)) { Some(HeaderValue(_, Value::Setting(Setting::Num(n, _)))) => Some(*n as $num_ty), Some(HeaderValue(loc, _)) => Err(HeaderError { kind: HeaderErrorKind::ConversionError("LexFlags", "Expected numeric"), @@ -98,9 +98,9 @@ impl TryFrom<&mut Header> for LexFlags { } }; } - cvt_num!(size_limit, usize); - cvt_num!(dfa_size_limit, usize); - cvt_num!(nest_limit, u32); + cvt_num!(regex, size_limit, usize); + cvt_num!(regex, dfa_size_limit, usize); + cvt_num!(regex, nest_limit, u32); Ok(lex_flags) } } diff --git a/lrlex/src/main.rs b/lrlex/src/main.rs index 93b798395..30ebbb326 100644 --- a/lrlex/src/main.rs +++ b/lrlex/src/main.rs @@ -95,8 +95,8 @@ fn main() -> Result<(), Box> { process::exit(1); } }; - header.mark_used(&"lexerkind".to_string()); - let lexerkind = if let Some(HeaderValue(_, lk_val)) = header.get("lexerkind") { + header.mark_used(&"lrlex.lexerkind".to_string()); + let lexerkind = if let Some(HeaderValue(_, lk_val)) = header.get("lrlex.lexerkind") { LexerKind::try_from(lk_val)? } else { LexerKind::LRNonStreamingLexer diff --git a/lrpar/cttests/src/grmtools_section.test b/lrpar/cttests/src/grmtools_section.test index 463eef14a..c0cd4962b 100644 --- a/lrpar/cttests/src/grmtools_section.test +++ b/lrpar/cttests/src/grmtools_section.test @@ -1,6 +1,6 @@ grammar: | %grmtools{ - yacckind: Grmtools, + cfgrammar.yacckind: Grmtools, recoverer: RecoveryKind::CPCTPlus, test_files: ["*.input_grmtools_section"] } @@ -19,6 +19,15 @@ grammar: | val_seq -> Result, Vec>> : valbind { let ((key, key_loc), val) = $1; + let key = if !RE_CRATE_DOT.is_match(&key) { + if let Some(crate_name) = CRATE_KEY_MAP.get(key.as_str()) { + format!("{crate_name}.{key}") + } else { + key + } + } else { + key + }; let mut ret = Header::::new(); match ret.entry(key) { Entry::Occupied(orig) => { @@ -38,6 +47,15 @@ grammar: | } | val_seq ',' valbind { let ((key, key_loc), val) = $3; + let key = if !RE_CRATE_DOT.is_match(&key) { + if let Some(crate_name) = CRATE_KEY_MAP.get(key.as_str()) { + format!("{crate_name}.{key}") + } else { + key + } + } else { + key + }; let mut ret = $1?; match ret.entry(key) { Entry::Occupied(orig) => { @@ -144,16 +162,23 @@ grammar: | Namespaced, Header, HeaderValue, + CRATE_KEY_MAP, + RE_CRATE_DOT, }, markmap::Entry, }; + use std::{ + collections::HashMap, + sync::LazyLock + }; + lexer: | %grmtools{case_insensitive} %% %grmtools 'MAGIC' ! '!' - [A-Z][A-Z_]* 'IDENT' + [A-Z][A-Z_\.]* 'IDENT' [0-9]+ 'NUM' , ',' \{ '{' diff --git a/lrpar/src/lib/codegen.rs b/lrpar/src/lib/codegen.rs index d36cc4874..b635f4495 100644 --- a/lrpar/src/lib/codegen.rs +++ b/lrpar/src/lib/codegen.rs @@ -310,12 +310,12 @@ where &mut self, from_ast: Option<&ASTWithValidityInfo>, ) -> Result { - self.header.mark_used(&"yacckind".to_string()); + self.header.mark_used(&"cfgrammar.yacckind".to_string()); if let Some(ast) = from_ast { Ok(ast.clone()) } else if let Some(yk) = self .header - .get("yacckind") + .get("cfgrammar.yacckind") .map(|HeaderValue(_, val)| val) .map(YaccKind::try_from) .transpose()? @@ -329,10 +329,10 @@ where /// Looks up the `recoverer` field in the header, marks the field /// as used, and defaulting to `CPCTPlus` if unfound. fn resolve_recoverer(&mut self) -> Result { - self.header.mark_used(&"recoverer".to_string()); + self.header.mark_used(&"lrpar.recoverer".to_string()); let rk_val = self .header - .get("recoverer") + .get("lrpar.recoverer") .map(|HeaderValue(_, rk_val)| rk_val); if let Some(rk_val) = rk_val { Ok(RecoveryKind::try_from(rk_val)?) @@ -345,10 +345,11 @@ where /// Looks up the `serialisation_format` field in the header, marks the field /// as used, and defaults to `VariableSizedInteger` if unfound. fn resolve_serialisation_format(&mut self) -> Result { - self.header.mark_used(&"serialisation_format".to_string()); + self.header + .mark_used(&"lrpar.serialisation_format".to_string()); if let Some(ec_val) = self .header - .get("serialisation_format") + .get("lrpar.serialisation_format") .map(|HeaderValue(_, ec_val)| ec_val) { Ok(SerialisationFormat::try_from(ec_val)?) diff --git a/lrpar/src/lib/ctbuilder.rs b/lrpar/src/lib/ctbuilder.rs index 771361fcc..6aacc1913 100644 --- a/lrpar/src/lib/ctbuilder.rs +++ b/lrpar/src/lib/ctbuilder.rs @@ -556,7 +556,7 @@ where .expect("output_path must be specified before processing."); let mut header = Header::new(); - match header.entry("yacckind".to_string()) { + match header.entry("cfgrammar.yacckind".to_string()) { Entry::Occupied(_) => unreachable!(), Entry::Vacant(mut v) => match self.yacckind { Some(YaccKind::Eco) => panic!("Eco compile-time grammar generation not supported."), @@ -574,7 +574,7 @@ where }, } if let Some(recoverer) = self.recoverer { - match header.entry("recoverer".to_string()) { + match header.entry("lrpar.recoverer".to_string()) { Entry::Occupied(_) => unreachable!(), Entry::Vacant(v) => { let rk_value: Value = Value::try_from(recoverer)?; @@ -588,7 +588,7 @@ where } if let Some(encoding) = self.serialisation_format { - match header.entry("serialisation_format".to_string()) { + match header.entry("lrpar.serialisation_format".to_string()) { Entry::Occupied(_) => unreachable!(), Entry::Vacant(v) => { let rk_value: Value = Value::try_from(encoding)?; diff --git a/nimbleparse/src/main.rs b/nimbleparse/src/main.rs index 8150d972f..e7feb8958 100644 --- a/nimbleparse/src/main.rs +++ b/nimbleparse/src/main.rs @@ -178,11 +178,11 @@ fn main() { None => (), Some(s) => { header.set_merge_behavior( - &"recoverer".to_string(), + &"lrpar.recoverer".to_string(), cfgrammar::markmap::MergeBehavior::Ours, ); header.insert( - "recoverer".to_string(), + "lrpar.recoverer".to_string(), HeaderValue( Location::CommandLine, Value::try_from(match &*s.to_lowercase() { @@ -195,7 +195,7 @@ fn main() { ); } }; - let entry = match header.entry("yacckind".to_string()) { + let entry = match header.entry("cfgrammar.yacckind".to_string()) { Entry::Occupied(_) => unreachable!("Header should be empty"), Entry::Vacant(v) => v, }; @@ -236,7 +236,7 @@ fn main() { let yacc_y_path = PathBuf::from(&matches.free[1]); let yacc_src = read_file(&yacc_y_path); let yacc_diag = SpannedDiagnosticFormatter::new(&yacc_src, &yacc_y_path); - let yk_val = header.get("yacckind"); + let yk_val = header.get("cfgrammar.yacckind"); if yk_val.is_none() { let parsed_header = GrmtoolsSectionParser::new(&yacc_src, true).parse(); match parsed_header { @@ -257,7 +257,7 @@ fn main() { } } } - let yk_val = header.get("yacckind"); + let yk_val = header.get("cfgrammar.yacckind"); if yk_val.is_none() { eprintln!( "yacckind not specified in the %grmtools section of the grammar or via the '-y' parameter" @@ -267,7 +267,7 @@ fn main() { let HeaderValue(_, yk_val) = yk_val.unwrap(); let yacc_kind = YaccKind::try_from(yk_val).unwrap_or(YaccKind::Grmtools); let ast_validation = ASTWithValidityInfo::new(yacc_kind, &yacc_src); - let recoverykind = if let Some(HeaderValue(_, rk_val)) = header.get("recoverer") { + let recoverykind = if let Some(HeaderValue(_, rk_val)) = header.get("lrpar.recoverer") { match RecoveryKind::try_from(rk_val) { Err(e) => { eprintln!( @@ -551,7 +551,7 @@ where ); } else { // If given no input paths, try to find some with `test_files` in the header. - match self.header.get("test_files") { + match self.header.get("lrpar.test_files") { Some(HeaderValue(_, Value::Setting(Setting::Array(test_globs, _, _)))) => { for setting in test_globs { match setting { @@ -564,7 +564,7 @@ where if glob_paths.peek().is_none() { return Err(NimbleparseError::Other( format!( - "'test_files' glob '{}' matched no paths", + "'lrpar.test_files' glob '{}' matched no paths", s ) .to_string() @@ -578,7 +578,7 @@ where && ext.starts_with("grm") { Err(NimbleparseError::Other( - "test_files extensions beginning with `grm` are reserved." + "lrpar.test_files extensions beginning with `grm` are reserved." .into(), ))? } @@ -607,7 +607,7 @@ where _ => { return Err(NimbleparseError::Other( - "Expected string values in `test_files`".into(), + "Expected string values in `lrpar.test_files`".into(), )); } } @@ -615,7 +615,7 @@ where } Some(_) => { return Err(NimbleparseError::Other( - "Expected Array of string values in `test_files`".into(), + "Expected Array of string values in `lrpar.test_files`".into(), )); } None => { @@ -631,7 +631,7 @@ where )); } let pb = RTParserBuilder::new(&self.grm, &self.stable).recoverer(self.recoverykind); - // Actually parse the given arguments or the `test_files` specified in the grammar. + // Actually parse the given arguments or the `lrpar.test_files` specified in the grammar. for input_path in paths { let input = read_file(&input_path); let lexer = self.lexerdef.lexer(&input);