lrp/
grammar.rs

1use std::{fmt, rc::Rc};
2
3use crate::{Map, Position, Set};
4
5/// Production Rule + Index In Declaration
6pub type Production<T> = (Vec<T>, usize);
7pub type RuleMap<T> = Map<T, Rule<T>>;
8
9#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
10pub struct Rule<T>
11where
12    T: Clone + PartialEq + PartialOrd + Ord + fmt::Debug,
13{
14    pub name: T,
15    pub prods: Vec<Rc<Production<T>>>,
16}
17
18impl<T> Rule<T>
19where
20    T: Clone + PartialEq + PartialOrd + Ord + fmt::Debug,
21{
22    #[must_use]
23    pub fn new<I>(name: T, prods: I) -> Self
24    where
25        I: IntoIterator<Item = Vec<T>>,
26    {
27        Self {
28            name,
29            prods: prods
30                .into_iter()
31                .enumerate()
32                .map(|(i, p)| Rc::new((p, i)))
33                .collect(),
34        }
35    }
36
37    #[must_use]
38    pub fn single(name: T, prod: Vec<T>) -> Self {
39        Self::new(name, std::iter::once(prod))
40    }
41
42    pub fn prods(&self) -> impl Iterator<Item = Rc<Production<T>>> + '_ {
43        self.prods.iter().cloned()
44    }
45}
46
47#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
48pub struct Grammar<T>
49where
50    T: Clone + PartialEq + PartialOrd + Ord + fmt::Debug,
51{
52    pub rules: RuleMap<T>,
53    pub terminals: Set<T>,
54    pub symbols: Set<T>,
55    pub basis: Position<T>,
56}
57
58impl<T> Grammar<T>
59where
60    T: Clone + PartialEq + PartialOrd + Ord + fmt::Debug,
61{
62    #[must_use]
63    pub fn new(start: T, rules: RuleMap<T>, eof: T) -> Self {
64        let mut terminals = Set::new();
65        for rule in rules.values() {
66            for rc in rule.prods() {
67                for term in &rc.0 {
68                    if !rules.contains_key(term) {
69                        terminals.insert(term.clone());
70                    }
71                }
72            }
73        }
74        terminals.insert(eof.clone());
75        let symbols = rules.keys().chain(terminals.iter()).cloned().collect();
76
77        let prods = &rules[&start].prods;
78        debug_assert_eq!(prods.len(), 1, "there's more than one possible entry");
79        let basis = Position::new(start, prods[0].clone(), 0, Set::from([eof]));
80        Self {
81            rules,
82            terminals,
83            symbols,
84            basis,
85        }
86    }
87
88    #[must_use]
89    pub fn basis(&self) -> Position<T> {
90        self.basis.clone()
91    }
92
93    #[must_use]
94    pub fn is_terminal(&self, term: &T) -> bool {
95        !self.rules.contains_key(term)
96    }
97
98    pub fn rules(&self) -> impl Iterator<Item = &Rule<T>> {
99        self.rules.values()
100    }
101
102    pub fn symbols(&self) -> impl Iterator<Item = T> + '_ {
103        self.symbols.iter().cloned()
104    }
105}