diff options
| author | JSDurand <mmemmew@gmail.com> | 2026-10-16 14:01:01 +0800 |
|---|---|---|
| committer | JSDurand <mmemmew@gmail.com> | 2026-10-16 14:02:10 +0800 |
| commit | fba9a90cfc6aca2a26cce72f55fb261789139781 (patch) | |
| tree | b4b121791ad639e745df689c0d5a8ed7a9e5dcc4 /grammar | |
| parent | 3ae0cf9898485a2ec35df7d23cd274e7dea5796d (diff) | |
Now I tested and discussed with claude, and had a working version of
this project. The rest is to port the claude version to my own
writings. So this serves as the starting point before that attempt.
In the new attempt the design is better, and a number of bugs were
found and supposedly fixed, so let us see how this goes at the end.
Diffstat (limited to 'grammar')
| -rw-r--r-- | grammar/src/abnf/mod.rs | 8 | ||||
| -rw-r--r-- | grammar/src/lib.rs | 44 | ||||
| -rw-r--r-- | grammar/src/test_grammar_helper.rs | 2 |
3 files changed, 49 insertions, 5 deletions
diff --git a/grammar/src/abnf/mod.rs b/grammar/src/abnf/mod.rs index b53dcc1..2e2d0f2 100644 --- a/grammar/src/abnf/mod.rs +++ b/grammar/src/abnf/mod.rs @@ -2439,9 +2439,9 @@ impl std::str::FromStr for Grammar { break; } - if appending_p && nonterminals_map.get(&rule_name).is_none() { + if appending_p && !nonterminals_map.contains_key(&rule_name) { return Err(Error::AppendToNothing(current_skipped_index)); - } else if !appending_p && nonterminals_map.get(&rule_name).is_some() { + } else if !appending_p && nonterminals_map.contains_key(&rule_name) { return Err(Error::CreateAgain(current_skipped_index)); } @@ -2473,13 +2473,13 @@ impl std::str::FromStr for Grammar { for data in rule_data { match data { IntermediateConstruct::Terminal(name) => { - if terminals_map.get(&name).is_none() { + if !terminals_map.contains_key(&name) { terminals_map.insert(name.clone(), terminals_vec.len()); terminals_vec.push(name); } } IntermediateConstruct::Nonterminal(name) => { - if nonterminals_map.get(&name).is_none() { + if !nonterminals_map.contains_key(&name) { return Err(Error::UnknownNonterminal(name)); } } diff --git a/grammar/src/lib.rs b/grammar/src/lib.rs index 64f4cdb..79c19e0 100644 --- a/grammar/src/lib.rs +++ b/grammar/src/lib.rs @@ -68,6 +68,13 @@ impl Nonterminal { pub fn name(&self) -> &str { &self.0 } + + /// A public constructor for the purposes of easy grammar + /// constructions. + #[inline] + pub fn new(name: String) -> Self { + Self(name) + } } /// The type of a terminal or a non-terminal. @@ -82,6 +89,16 @@ pub enum TNT { Non(usize), } +impl TNT { + /// Retrieve the index of this enum. + pub fn value(&self) -> usize { + match self { + Self::Ter(index) => *index, + Self::Non(index) => *index, + } + } +} + impl Display for TNT { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -881,6 +898,33 @@ impl Grammar { ) .unwrap()) } + + /// Print the names of terminals and non-terminals into a given + /// file. + pub fn print_tnt(&self, file_name: &str) -> Result<(), String> { + let mut fs = std::fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(file_name) + .map_err(|e| format!("{e}"))?; + + use std::io::Write; + + for (n, ter) in (0..(self.ter_num())).map(TNT::Ter).enumerate() { + let name = self.name_of_tnt(ter).unwrap(); + + writeln!(&mut fs, "{n}-th terminal: {name}").map_err(|e| format!("{e}"))?; + } + + for (n, non) in (0..(self.non_num())).map(TNT::Non).enumerate() { + let name = self.name_of_tnt(non).unwrap(); + + writeln!(&mut fs, "{n}-th non-terminal: {name}").map_err(|e| format!("{e}"))?; + } + + Ok(()) + } } pub mod first_set; diff --git a/grammar/src/test_grammar_helper.rs b/grammar/src/test_grammar_helper.rs index 9d86865..8c9c2ed 100644 --- a/grammar/src/test_grammar_helper.rs +++ b/grammar/src/test_grammar_helper.rs @@ -18,7 +18,7 @@ pub fn new_closure_regex( } /// A function to scan the inputs. -fn scan_tnt( +pub fn scan_tnt( parser: &DefaultRegParser<TNT>, input: &str, ) -> Result<Option<(usize, RegexType<TNT>, ParseDirection)>, ParseError> { |
