summaryrefslogtreecommitdiff
path: root/chain/src/item
diff options
context:
space:
mode:
Diffstat (limited to 'chain/src/item')
-rw-r--r--chain/src/item/default/splone.rs100
-rw-r--r--chain/src/item/genins.rs184
2 files changed, 126 insertions, 158 deletions
diff --git a/chain/src/item/default/splone.rs b/chain/src/item/default/splone.rs
index 4f4835b..851968c 100644
--- a/chain/src/item/default/splone.rs
+++ b/chain/src/item/default/splone.rs
@@ -19,6 +19,12 @@ fn get_rule_label(label: GrammarLabel) -> Option<usize> {
}
}
+/// Existing or non-existing label.
+enum Eon {
+ Ex(usize),
+ Nex(ForestLabel<GrammarLabel>),
+}
+
impl DefaultForest<ForestLabel<GrammarLabel>> {
/// Either "open split" or "closed split".
///
@@ -56,6 +62,11 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
/// [`split_node`][DefaultForest::<ForestLabel<GrammarLabel>>::split_node]
/// for details.
///
+ /// # Return
+ ///
+ /// The function returns the new, splitted or cloned node, or the
+ /// old node, if nothing is performed.
+ ///
/// # Name
///
/// The name is a mixture of *split* and *clone*.
@@ -74,12 +85,19 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
/// descriptions of procedures below, we actually refer to the
/// parents of the rule parents, which should again be checked to
/// be labelled by non-terminals.
- fn splone(&mut self, node: usize, end: Option<usize>, edge_index: usize) -> Result<(), Error> {
+ pub(crate) fn splone(
+ &mut self,
+ node: usize,
+ end: Option<usize>,
+ edge_index: usize,
+ ) -> Result<usize, Error> {
let node_label = self.vertex_label(node)?.ok_or(Error::NodeNoLabel(node))?;
assert!(get_nt_label(node_label.label()).is_some());
if node_label.is_packed() {
+ self.print_viz("dbg forest.gv").unwrap();
+ dbg!(self.vertex_label(node)?, end);
return Err(Error::SplitPack(node));
}
@@ -89,26 +107,26 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
// We can check the end to know whether the new label is equal
// to the old label.
if node_end == end {
- if node_degree == edge_index + 1 {
- return Ok(());
+ if node_degree <= edge_index + 1 {
+ return Ok(node);
}
- dbg!();
- self.clone_node(node, edge_index + 1, false)?;
+ let cloned = self.clone_node(node, edge_index + 1, false)?;
- return Ok(());
+ return Ok(cloned);
}
let new_label = self.create_new_label(node, end, edge_index)?;
- let new_label = if let Some(label) = new_label {
- label
- } else {
- return Ok(());
+ let new_label = match new_label {
+ Eon::Nex(label) => label,
+ Eon::Ex(existing) => {
+ return Ok(existing);
+ }
};
if node_end.is_some()
- || edge_index + 1 != node_degree
+ || edge_index + 1 < node_degree
|| node_label.clone_index().is_some()
|| new_label.clone_index().is_some()
{
@@ -168,7 +186,7 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
// builder.add_edge(packed, node, new_label)?;
// }
- Ok(())
+ Ok(node)
}
/// Procedure to split the node:
@@ -180,12 +198,16 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
/// 3. For each parent, clone the parent. Replace the original
/// child of the parent, which pointed to the old node, by this
/// new node. Other children are inherited from the old parent.
+ ///
+ /// # Return
+ ///
+ /// The function returns the new node index.
fn split_node(
&mut self,
new_label: ForestLabel<GrammarLabel>,
mut node: usize,
edge_index: usize,
- ) -> Result<(), Error> {
+ ) -> Result<usize, Error> {
let end = new_label.label().end();
let mut builder = PLGBuilderMut::from_graph_mut(&mut self.graph);
@@ -269,7 +291,7 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
};
for (parent, new_child) in parents {
- if self.has_same_children_but_one(
+ if self.has_same_children_until(
parent.node(),
parent.node(),
parent.edge(),
@@ -284,18 +306,9 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
let mut builder = PLGBuilderMut::from_graph_mut(&mut self.graph);
builder.add_edge(cloned, new_child, new_label)?;
-
- let children_to_add: Vec<_> = builder
- .children_of(parent.node())?
- .skip(parent.edge() + 1)
- .collect();
-
- for child in children_to_add {
- builder.add_edge(cloned, child, new_label)?;
- }
}
- Ok(())
+ Ok(new_node)
}
/// Procedure for the new label:
@@ -320,7 +333,7 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
node: usize,
end: Option<usize>,
edge_index: usize,
- ) -> Result<Option<ForestLabel<GrammarLabel>>, Error> {
+ ) -> Result<Eon, Error> {
let mut copied_label = self
.vertex_label(node)?
.ok_or(Error::NodeNoLabel(node))?
@@ -337,7 +350,7 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
if let Some(packed) = self.query_label(label) {
for child in self.children_of(packed)? {
if self.has_same_children(child, node, self.degree(child)?, edge_index + 1)? {
- return Ok(None);
+ return Ok(Eon::Ex(child));
}
}
@@ -347,7 +360,7 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
let clone_index = self.clone_node(first_child, 0, true)?;
- Ok(Some(ForestLabel::new(
+ Ok(Eon::Nex(ForestLabel::new(
copied_label,
ForestLabelType::Cloned(clone_index),
)))
@@ -356,17 +369,17 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
if let Some(existing) = self.query_label(plain_label) {
if self.has_same_children(existing, node, self.degree(existing)?, edge_index + 1)? {
- return Ok(None);
+ return Ok(Eon::Ex(existing));
}
let clone_index = self.clone_node(existing, 0, true)?;
- Ok(Some(ForestLabel::new(
+ Ok(Eon::Nex(ForestLabel::new(
copied_label,
ForestLabelType::Cloned(clone_index),
)))
} else {
- Ok(Some(plain_label))
+ Ok(Eon::Nex(plain_label))
}
}
}
@@ -396,9 +409,14 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
}
/// Detect if a node has a branch that has the same children as
- /// another node, except at a given index, where it points to
- /// another given node.
- fn has_same_children_but_one(
+ /// another node, until a given index, where it points to another
+ /// given node.
+ ///
+ /// # Clones
+ ///
+ /// If `nodea` is a clone, it checks every clone to see if the
+ /// condition is satisfied for some clone.
+ fn has_same_children_until(
&self,
nodea: usize,
nodeb: usize,
@@ -408,14 +426,20 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
let labela = self.vertex_label(nodea)?.ok_or(Error::NodeNoLabel(nodea))?;
let children_b = self.children_of(nodeb)?;
+ if children_b.len() < edge_index + 1 {
+ return Err(Error::IndexOutOfBounds(edge_index, children_b.len() - 1));
+ }
+
if labela.is_plain() {
let children_a = self.children_of(nodea)?;
- if children_a.len() != children_b.len() {
+ if children_a.len() < edge_index + 1 {
return Ok(false);
}
- for (index, (childa, childb)) in children_a.zip(children_b).enumerate() {
+ for (index, (childa, childb)) in
+ children_a.zip(children_b).take(edge_index + 1).enumerate()
+ {
if index != edge_index {
if childa != childb {
return Ok(false);
@@ -437,11 +461,13 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
let children_a = self.children_of(branch)?;
let children_b = children_b.clone();
- if children_a.len() != children_b.len() {
+ if children_a.len() < edge_index + 1 {
continue 'branch_loop;
}
- for (index, (childa, childb)) in children_a.zip(children_b).enumerate() {
+ for (index, (childa, childb)) in
+ children_a.zip(children_b).take(edge_index + 1).enumerate()
+ {
if index != edge_index {
if childa != childb {
continue 'branch_loop;
diff --git a/chain/src/item/genins.rs b/chain/src/item/genins.rs
index 43807f8..4c51d9a 100644
--- a/chain/src/item/genins.rs
+++ b/chain/src/item/genins.rs
@@ -25,6 +25,12 @@ fn index_out_of_bounds_conversion(ge: GrammarError) -> Error {
_ => Error::Invalid,
}
}
+
+/// Determine if a label is labelled by a terminal.
+fn is_labelled_by_terminal(label: GrammarLabelType) -> bool {
+ matches!(label.tnt(), Some(t) if matches!(t, TNT::Ter(_)))
+}
+
/// A helper function to generate a fragment of forest.
///
/// It simply constructs a root node and then appends
@@ -38,30 +44,43 @@ pub fn generate_fragment(
labels: impl AsRef<[GrammarLabelType]>,
pos: usize,
) -> Result<DefaultForest<ForestLabel<GrammarLabel>>, crate::default::Error> {
- let mut labels_iter = labels.as_ref().iter();
- let mut result: DefaultForest<ForestLabel<GrammarLabel>>;
-
- if let Some(first_label) = labels_iter.next() {
- result = DefaultForest::new_leaf(GrammarLabel::new(*first_label, pos));
-
- let mut index = 0;
-
- for label in labels_iter {
- result.plant(
- index,
- DefaultForest::new_leaf(GrammarLabel::new(*label, pos)),
- false,
- )?;
-
- // To prevent duplication of labels causing
- // panics, we query the index of the new node.
- index = result
- .query_label(GrammarLabel::new(*label, pos).into())
- // REVIEW: Perhaps a LabelNoNode error?
- .ok_or(Error::Invalid)?;
- }
+ let labels_slice = labels.as_ref();
+
+ let labels_len = labels_slice.len();
+
+ let last_label = if labels_len > 0 {
+ labels_slice.get(labels_len - 1).copied().unwrap()
} else {
- result = Default::default();
+ return Ok(Default::default());
+ };
+
+ let labels_iter = labels_slice.iter();
+
+ let labels_iter_zipped = labels_iter
+ .clone()
+ .zip(labels_iter.skip(1).chain(std::iter::once(&last_label)));
+
+ let mut mapped_iter = labels_iter_zipped.map(|(label, next_label)| {
+ if is_labelled_by_terminal(*next_label) {
+ GrammarLabel::new_closed(*label, pos, pos + 1)
+ } else {
+ GrammarLabel::new(*label, pos)
+ }
+ });
+
+ let first_label = mapped_iter.next().unwrap();
+
+ let mut result = DefaultForest::new_leaf(first_label);
+
+ let mut index = 0;
+
+ for label in mapped_iter {
+ result.plant(index, DefaultForest::new_leaf(label), false)?;
+
+ index = result
+ .query_label(label.into())
+ // REVIEW: Perhaps a LabelNoNode error?
+ .ok_or(Error::Invalid)?;
}
Ok(result)
@@ -123,7 +142,7 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
&mut self,
label: Edge,
fragment: impl Borrow<DefaultForest<ForestLabel<GrammarLabel>>>,
- atom_child_iter: impl Iterator<Item = usize>,
+ atom_child_iter: impl Iterator<Item = usize> + ExactSizeIterator,
atom: &DefaultAtom,
) -> Result<PaSe, Error> {
let fragment = fragment.borrow();
@@ -243,8 +262,6 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
// locate the nodes
for reduction_nt in reduction_info.iter().copied().flatten().rev() {
while let Some(mut node) = stack.pop() {
- // REVIEW: A lot of labels appear here.
- // Perhaps I need to refactor something?
let mut node_label = self
.vertex_label(node.node())?
.ok_or_else(|| Error::NodeNoLabel(node.node()))?;
@@ -255,53 +272,32 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
.label(),
GrammarLabelType::TNT(TNT::Non(nt)) if nt == *reduction_nt
) {
- // TODO: Try to update the end index of the
- // node; if the node already has an ending
- // index, clone the node, and update the
- // ending index of the cloned node; otherwise,
- // just set the ending index.
-
- if node_label.label().end().is_some() {
- let cloned_node =
- self.clone_node(node.node(), node.edge() + 1, false)?;
-
- self.transform_label(cloned_node, |mut label| {
- label.set_end(pos + 1);
- label
- })?;
-
- node_label = self
- .vertex_label(node.node())?
- .ok_or_else(|| Error::NodeNoLabel(node.node()))?;
- } else {
- self.transform_label(node.node(), |mut label| {
- label.set_end(pos + 1);
- label
- })?;
- }
+ let sploned_node = self.splone(node.node(), Some(pos), node.edge())?;
+
+ node_label = self
+ .vertex_label(sploned_node)?
+ .ok_or(Error::NodeNoLabel(sploned_node))?;
if node_label.clone_index().is_some() {
- let mut parent_iter = self.parents_of(node.node())?;
+ let mut parent_iter = self.parents_of(sploned_node)?;
#[cfg(debug_assertions)]
- assert_eq!(parent_iter.len(), 1);
+ {
+ assert_eq!(parent_iter.len(), 1);
- node = parent_iter.next().unwrap();
+ assert!(self
+ .vertex_label(sploned_node)?
+ .ok_or(Error::NodeNoLabel(sploned_node))?
+ .is_packed());
+ }
- #[cfg(debug_assertions)]
- assert!(self
- .vertex_label(node.node())?
- .ok_or_else(|| Error::NodeNoLabel(node.node()))?
- .is_packed());
+ node = parent_iter.next().unwrap();
+ } else {
+ node = Parent::new(sploned_node, node.edge());
}
let parents_iter = self.parents_of(node.node())?;
- let to_update = parents_iter
- .clone()
- .map(|parent| parent.node())
- .collect::<Vec<_>>();
-
for parent in parents_iter {
let parent_label = self
.vertex_label(parent.node())?
@@ -312,14 +308,11 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
crate::item::default::print_labels(atom, self.borrow()).unwrap();
self.print_viz("dbg forest.gv").unwrap();
- dbg!(parent, parent_label, label, node);
+ dbg!(parent, parent_label, label, node, sploned_node);
panic!("assumption fails");
}
- // debug_assert!(parent_label.label().rule().is_some());
- // debug_assert!(parent_label.end().is_none());
-
second_stack.extend(self.parents_of(parent.node())?.filter(|n| {
matches!(self.vertex_label(n.node()),
Ok(Some(label))
@@ -328,13 +321,6 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
Some(TNT::Non(_))))
}));
}
-
- for node in to_update {
- self.transform_label(node, |mut label| {
- label.set_end(pos + 1);
- label
- })?;
- }
}
}
@@ -357,59 +343,15 @@ impl DefaultForest<ForestLabel<GrammarLabel>> {
self.print_viz("dbg forest.gv").unwrap();
#[cfg(test)]
- genins_test::print_labels(atom, self).unwrap();
+ genins_test::print_labels(atom, self.borrow()).unwrap();
return Err(Error::CannotPlant);
}
for parent in stack.into_iter() {
- let was_last_child = parent.edge() + 1 >= self.degree(parent.node())?;
-
- let overlap = {
- if let Ok(child) = self.nth_child(parent.node(), parent.edge()) {
- let edge_th_child = child;
- let child_label = self
- .vertex_label(edge_th_child)?
- .ok_or(Error::NodeNoLabel(edge_th_child))?;
- let child_start = child_label.label().start();
- let child_end = child_label.label().end();
-
- child_start >= pos || matches!(child_end, Some(end) if end > pos)
- } else {
- // the root case
- false
- }
- };
+ let sploned_node = self.splone(parent.node(), None, parent.edge())?;
- if overlap {
- let cloned_node = self.clone_node(parent.node(), parent.edge() + 1, false)?;
-
- self.plant(cloned_node, fragment, non_empty)?;
- } else if was_last_child {
- // dbg!(&fragment);
- self.plant(parent.node(), fragment, non_empty)?;
- } else {
- let nth_child = self.nth_child(parent.node(), parent.edge() + 1)?;
-
- if self.is_prefix(nth_child, fragment)? {
- // do nothing
- continue;
- }
-
- // dbg!(
- // label,
- // atom_child,
- // &parents,
- // reduction_info,
- // atom.query_reduction(label.label(), atom_child).unwrap()
- // );
-
- // self.print_viz("dbg forest.gv").unwrap();
-
- let cloned_node = self.clone_node(parent.node(), parent.edge() + 1, false)?;
-
- self.plant(cloned_node, fragment, non_empty)?;
- }
+ self.plant(sploned_node, fragment, non_empty)?;
non_empty = true;
}