summaryrefslogtreecommitdiff
path: root/chain/src/default.rs
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2023-02-03 10:52:35 +0800
committerJSDurand <mmemmew@gmail.com>2023-02-03 10:52:35 +0800
commit265ff8f87dc7392fdf701f811eb2bf54d7bc6678 (patch)
tree35538c8ac7524e0d9f2acff8be21b72994728bc4 /chain/src/default.rs
parentf28155105134b90fd86049c65478d307e0d8dbbc (diff)
Finally produced the first correct forest
Finally the prototype parser has produced the first correct forest. It is my first time to generate a correct forest, in fact, ever since the beginning of this project.
Diffstat (limited to 'chain/src/default.rs')
-rw-r--r--chain/src/default.rs82
1 files changed, 28 insertions, 54 deletions
diff --git a/chain/src/default.rs b/chain/src/default.rs
index 77a64ca..5e94623 100644
--- a/chain/src/default.rs
+++ b/chain/src/default.rs
@@ -8,7 +8,8 @@
use super::*;
use crate::atom::{Atom, DefaultAtom};
use crate::item::{
- default::DefaultForest, generate_fragment, Forest, ForestLabel, ForestLabelError,
+ default::DefaultForest, generate_fragment, genins::virtual_generate_fragment, Forest,
+ ForestLabel, ForestLabelError,
};
use core::fmt::Display;
use grammar::{Error as GrammarError, GrammarLabel, GrammarLabelType, TNT};
@@ -35,6 +36,8 @@ pub enum Error {
CannotClone(ForestLabelError),
/// Cannot find a suitable node to plant the new forest fragment.
CannotPlant,
+ /// Trying to insert an empty item.
+ EmptyItem,
/// An invalid situation happens.
Invalid,
}
@@ -52,6 +55,7 @@ impl Display for Error {
Self::CannotReserve(e) => write!(f, "cannot reserve memory: {e}"),
Self::CannotClone(fe) => write!(f, "cannot clone due to {fe}"),
Self::CannotPlant => write!(f, "cannot plant a new forest fragment"),
+ Self::EmptyItem => write!(f, "trying to insert an empty item"),
Self::Invalid => write!(f, "invalid"),
}
}
@@ -393,7 +397,6 @@ impl Chain for DefaultChain {
.is_nullable(0)
.map_err(|_| Error::IndexOutOfBounds(0, atom.non_num()))?;
- // NOTE: Is it really correct to use `Parent::new(0, 0)` here?
builder.add_edge(
first,
root,
@@ -585,15 +588,13 @@ impl Chain for DefaultChain {
)?;
}
Some(Non(non)) => {
- let first_fragment =
- generate_fragment([atom_moved.into(), Non(non).into()], pos)?;
-
- let first_segment_pase = self.forest.insert_item(
- *label,
- first_fragment,
- atom_child_iter.clone(),
- &self.atom,
- )?;
+ if !self
+ .atom
+ .is_first_of(non, t)
+ .map_err(index_out_of_bounds_conversion)?
+ {
+ continue;
+ }
let virtual_node = self
.atom
@@ -601,59 +602,30 @@ impl Chain for DefaultChain {
.map_err(index_out_of_bounds_conversion)?;
if let Some(virtual_node) = virtual_node {
+ let first_fragment =
+ generate_fragment([atom_moved.into(), Non(non).into()], pos)?;
+
+ let first_segment_pase = self.forest.insert_item(
+ *label,
+ first_fragment,
+ atom_child_iter.clone(),
+ &self.atom,
+ )?;
+
let accepting = self
.atom
.is_accepting(virtual_node)
.map_err(index_out_of_bounds_conversion)?;
- let virtual_fragment = {
- // `non` is valid, as checked above
- let non_start = self.atom.nth_accumulator(non).unwrap() * 2;
-
- let mut result = DefaultForest::default();
-
- for (label, child_iter) in self.atom.labels_of(non_start)? {
- if matches!(*label.get_value(),
- Some(Ter(ter)) if ter == t)
- {
- for child in child_iter {
- let mut line: Vec<_> = self
- .atom
- .query_expansion(non_start, child)
- .map_err(index_out_of_bounds_conversion)?
- .iter()
- .copied()
- .flatten()
- .map(|(nt, rule)| [(*rule).into(), Non(*nt).into()])
- .collect();
-
- line.push([label.get_moved().into(), Ter(t).into()]);
-
- let line: Vec<GrammarLabelType> =
- line.into_iter().flatten().collect();
-
- if result.is_empty() {
- result = generate_fragment(line, pos)?;
- } else {
- result.plant(
- 0,
- generate_fragment(line, pos)?,
- false,
- )?;
- }
- }
- }
- }
-
- result
- };
+ let virtual_fragment =
+ virtual_generate_fragment(&self.atom, non, t, pos)?;
// NOTE: We only need the PaSe from the
// first segment, so we pass an empty
// iterator, in which case the passed
// label is only used for the PaSe.
let virtual_pase = self.forest.insert_item(
- Edge::new(0, first_segment_pase, true),
+ Edge::new(0, first_segment_pase, accepting),
virtual_fragment,
std::iter::empty(),
&self.atom,
@@ -810,8 +782,8 @@ mod test_chain {
let atom = DefaultAtom::from_grammar(grammar)?;
let mut chain = DefaultChain::unit(atom)?;
-
chain.chain(3, 00)?;
+ dbg!("hi");
chain.chain(1, 01)?;
chain.chain(2, 02)?;
chain.chain(2, 03)?;
@@ -831,6 +803,8 @@ mod test_chain {
{
chain.graph.print_viz("chain.gv")?;
chain.atom.print_nfa("nfa.gv")?;
+ chain.forest.print_viz("forest.gv")?;
+ item::default::print_labels(&chain.atom, &chain.forest)?;
}
Ok(())