summaryrefslogtreecommitdiff
path: root/chain/src/atom
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2023-08-04 10:08:49 +0800
committerJSDurand <mmemmew@gmail.com>2023-08-04 10:08:49 +0800
commit57134c44207f7129035bbdbca0e4deff398defe3 (patch)
tree124d6f753c75a3e435a5ef665d6b6123d6435ed5 /chain/src/atom
parente64172f7909c71dc609099d3f5c4666d063653eb (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.
Diffstat (limited to 'chain/src/atom')
-rw-r--r--chain/src/atom/default.rs43
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(())
+ }
+}