1use std::{fmt, rc::Rc};
2
3use crate::{Map, Position, Set};
4
5pub 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}