lexigram_lib/grammar/origin.rs
1// Copyright (c) 2025 Redglyph (@gmail.com). All Rights Reserved.
2
3#![allow(unused)]
4
5use std::collections::HashMap;
6use std::hash::Hash;
7use std::marker::PhantomData;
8use crate::VarId;
9use crate::grammar::GrTree;
10
11#[derive(Clone, Debug)]
12/// Origin from a RuleTreeSet perspective: [`Origin<(VarId, usize), FromRTS>`](Origin), where
13/// `(VarId, usize)` identifies a node in the processed [`RuleTreeSet`]:
14/// * [`VarId`] is the variable
15/// * `usize` is the node index in the [`GrTree`] of that variable
16///
17/// and associates it with a node [`VarId`, usize] of the original [`RuleTreeSet`] rules
18/// after normalization (but keeping the * and + ops).
19pub struct FromRTS;
20
21#[derive(Clone, Debug)]
22/// Origin from a ProdRuleSet perspective: [`Origin<VarId, FromPRS>`](Origin), where
23/// `VarId` identifies a children nonterminal in the processed [`ProdRuleSet`]:
24/// * [`VarId`] is the variable
25///
26/// and associates it with a node [`VarId`, usize] of the original [`RuleTreeSet`] rules
27/// after normalization (but keeping the * and + ops).
28///
29/// The alternatives of the ProdRuleSet store their own [`VarId`, usize] links to the original
30/// nodes because it's easier than to track the data when they're moved around.
31pub struct FromPRS;
32
33#[derive(Clone, Debug)]
34pub struct Origin<F, T> {
35 pub trees: Vec<GrTree>,
36 pub map: HashMap<F, (VarId, usize)>,
37 _phantom: PhantomData<T>,
38}
39
40impl<F, T> Origin<F, T> {
41 /// Creates a blank [`Origin`] object.
42 pub fn new() -> Self {
43 Origin {
44 trees: Vec::new(),
45 map: HashMap::new(),
46 _phantom: PhantomData,
47 }
48 }
49
50 /// Creates a blank [`Origin`] object with a tree capacity of `size`. Use this method when
51 /// you can't give the data in a form that suits the other constructors but when you know
52 /// the number of variables.
53 pub fn with_capacity(size: usize) -> Self {
54 Origin {
55 trees: Vec::with_capacity(size),
56 map: HashMap::new(),
57 _phantom: PhantomData,
58 }
59 }
60
61 /// Creates an [`Origin`] object with the given trees and mapping.
62 pub fn from_data(trees: Vec<GrTree>, map: HashMap<F, (VarId, usize)>) -> Self {
63 Origin { trees, map, _phantom: PhantomData }
64 }
65
66 /// Creates an [`Origin`] object with the given trees as mutable reference. It will
67 /// take the content from `trees` to create the object. After that, `trees` is empty.
68 ///
69 /// Use this method to create an [`Origin`] object from another generic form of the
70 /// same type; typically when creating an `Origin<(VarId, AltId), FromPRS>` from an
71 /// `Origin<(VarId, usize), FromRTS>` if you can't move the original.
72 pub fn from_trees_mut(trees: &mut Vec<GrTree>) -> Self {
73 let trees = std::mem::take(trees);
74 Self::from_data(trees, HashMap::new())
75 }
76
77 /// Sets the original [`tree`](GrTree) of nonterminal `var`.
78 pub fn set_tree(&mut self, var: VarId, tree: GrTree) {
79 let var = var as usize;
80 if self.trees.len() <= var {
81 self.trees.resize(var + 1, GrTree::new());
82 }
83 self.trees[var] = tree;
84 }
85
86 /// Gets the original [`GrTree`] of nonterminal `var`, if it exists.
87 pub fn get_tree(&self, var: VarId) -> Option<&GrTree> {
88 self.trees.get(var as usize)
89 }
90}
91
92impl<F: Eq + Hash, T> Origin<F, T> {
93 /// Adds a connection between a `new` node and its `origin` in the original [`GrTree`].
94 ///
95 /// `new` is made up of a nonterminal index and its tree index.
96 pub fn add(&mut self, new: F, origin: (VarId, usize)) {
97 self.map.insert(new, origin);
98 }
99
100 /// Gets the original [`GrTree`] and node index, if they exist, from a `new` node.
101 ///
102 /// `new` is made up of a nonterminal index and its tree index.
103 pub fn get(&self, new: F) -> Option<(&GrTree, usize)> {
104 self.map.get(&new).cloned()
105 .map(|(v, node)| (&self.trees[v as usize], node))
106 }
107}