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}