diff options
author | JSDurand <mmemmew@gmail.com> | 2023-08-04 10:08:49 +0800 |
---|---|---|
committer | JSDurand <mmemmew@gmail.com> | 2023-08-04 10:08:49 +0800 |
commit | 57134c44207f7129035bbdbca0e4deff398defe3 (patch) | |
tree | 124d6f753c75a3e435a5ef665d6b6123d6435ed5 | |
parent | e64172f7909c71dc609099d3f5c4666d063653eb (diff) |
chain/atom/default: Fix nullibility of virtual nodes.
* chain/src/atom/default.rs: Previously the nullibility of virtual
nodes is determined by the nullibility of all its out-going edges.
This is now determined only by the nullibility of out-going edges
that are not "left-linearly expanded". This is the correct
approach.
-rw-r--r-- | chain/src/atom/default.rs | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/chain/src/atom/default.rs b/chain/src/atom/default.rs index 6ae924f..fa0cc3b 100644 --- a/chain/src/atom/default.rs +++ b/chain/src/atom/default.rs @@ -537,11 +537,15 @@ impl DefaultAtom { .or_insert_with(Default::default) .insert(rule, frag); - accepting = - accepting + // Those left-linearly expanded arrows should + // not affect the nullability of the virtual + // nodes. + if !label.is_left_p() { + accepting = accepting || *accepting_vec.get(child).ok_or( GrammarError::IndexOutOfBounds(child, accepting_vec.len()), )?; + } if let Some((_, old_accepting)) = terminals_map.get_mut(&t) { *old_accepting = *old_accepting || accepting; @@ -736,3 +740,38 @@ impl Atom for DefaultAtom { self.accepting_vec.len() } } + +#[cfg(test)] +mod test_default_atom { + use super::*; + + #[test] + fn test_from_grammar() -> Result<(), Box<dyn std::error::Error>> { + use grammar::Grammar; + + let grammar_str = std::fs::read_to_string( + "/Users/durand/Desktop/Centre/A propos de programmes/Rust/rep/grammar/abnf grammars/test.abnf", + ) + .unwrap(); + + let grammar: Grammar = grammar_str.parse()?; + + println!("grammar"); + println!("{grammar}"); + + let atom = DefaultAtom::from_grammar(grammar)?; + + atom.print_nullables(); + + atom.print_virtual(); + + for virtual_node in 166..=173 { + assert_eq!( + atom.is_accepting(virtual_node)?, + [169, 170, 172].contains(&virtual_node) + ); + } + + Ok(()) + } +} |