1use crate::core::cache::Allocs;
2use crate::core::pos::Pos;
3use crate::grammar::{AnnotatedRuleExpr, Block, GrammarFile, Rule};
4use crate::parser::var_map::{VarMap, VarMapValue};
5use serde::{Deserialize, Serialize};
6use std::fmt::{Display, Formatter};
7use std::iter;
8
9#[derive(Copy, Clone)]
10pub struct GrammarState<'arn, 'grm> {
11 rules: &'arn [&'arn RuleState<'arn, 'grm>],
12 last_mut_pos: Option<Pos>,
13}
14
15#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Hash)]
16pub struct RuleId(usize);
17
18impl Display for RuleId {
19 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
20 write!(f, "{}", self.0)
21 }
22}
23
24impl<'arn, 'grm> Default for GrammarState<'arn, 'grm> {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30#[derive(Debug)]
31pub enum AdaptError<'grm> {
32 InvalidRuleMutation(&'grm str),
33 SamePos(Pos),
34}
35
36impl<'arn, 'grm: 'arn> GrammarState<'arn, 'grm> {
37 pub fn new() -> Self {
38 Self {
39 rules: &[],
40 last_mut_pos: None,
41 }
42 }
43
44 pub fn adapt_with(
47 &self,
48 grammar: &'arn GrammarFile<'arn, 'grm>,
49 ctx: VarMap<'arn, 'grm>,
50 pos: Option<Pos>,
51 alloc: Allocs<'arn>,
52 ) -> Result<(Self, VarMap<'arn, 'grm>), AdaptError<'grm>> {
53 if let Some(pos) = pos {
55 if let Some(last_mut_pos) = self.last_mut_pos {
56 if pos == last_mut_pos {
57 return Err(AdaptError::SamePos(pos));
58 }
59 }
60 }
61
62 let mut new_rules = self.rules.to_vec();
64 let mut new_ctx = ctx;
65 let tmp: Vec<_> = grammar
66 .rules
67 .iter()
68 .map(|new_rule| {
69 let rule = if new_rule.adapt {
70 ctx.get(new_rule.name)
71 .and_then(VarMapValue::as_rule_id)
72 .expect("Name refers to a rule id")
73 } else {
74 new_rules.push(alloc.alloc(RuleState::new_empty(new_rule.name, new_rule.args)));
75 RuleId(new_rules.len() - 1)
76 };
77 new_ctx = new_ctx.extend(
78 iter::once((new_rule.name, VarMapValue::new_rule(rule, alloc))),
79 alloc,
80 );
81 (new_rule.name, rule)
82 })
83 .collect();
84
85 for (&(_, id), rule) in tmp.iter().zip(grammar.rules.iter()) {
87 new_rules[id.0] = alloc.alloc(
88 new_rules[id.0]
89 .update(rule, new_ctx, alloc)
90 .map_err(|_| AdaptError::InvalidRuleMutation(rule.name))?,
91 );
92 }
93
94 Ok((
95 Self {
96 last_mut_pos: pos,
97 rules: alloc.alloc_extend(new_rules),
98 },
99 new_ctx,
100 ))
101 }
102
103 pub fn new_with(
104 grammar: &'arn GrammarFile<'arn, 'grm>,
105 alloc: Allocs<'arn>,
106 ) -> (Self, VarMap<'arn, 'grm>) {
107 GrammarState::new()
109 .adapt_with(grammar, VarMap::default(), None, alloc)
110 .unwrap()
111 }
112
113 pub fn get(&self, rule: RuleId) -> Option<&RuleState<'arn, 'grm>> {
114 self.rules.get(rule.0).map(|v| &**v)
115 }
116
117 pub fn unique_id(&self) -> GrammarStateId {
118 GrammarStateId(self.rules.as_ptr() as usize)
119 }
120}
121
122#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
124pub struct GrammarStateId(usize);
125
126#[derive(Copy, Clone)]
127pub struct RuleState<'arn, 'grm> {
128 pub name: &'grm str,
129 pub args: &'arn [&'grm str],
130 pub blocks: &'arn [BlockState<'arn, 'grm>],
131}
132
133pub enum UpdateError {
134 ToposortCycle,
135}
136
137impl<'arn, 'grm> RuleState<'arn, 'grm> {
138 pub fn new_empty(name: &'grm str, args: &'arn [&'grm str]) -> Self {
139 Self {
140 name,
141 blocks: &[],
142 args,
143 }
144 }
145
146 pub fn update(
147 &self,
148 r: &'arn Rule<'arn, 'grm>,
149 ctx: VarMap<'arn, 'grm>,
150 allocs: Allocs<'arn>,
151 ) -> Result<Self, UpdateError> {
152 assert_eq!(self.name, r.name);
153 assert_eq!(self.args, r.args);
154
155 let mut result = Vec::with_capacity(self.blocks.len() + r.blocks.len());
157 let mut old_iter = self.blocks.iter();
158
159 for new_block in r.blocks {
160 if !new_block.adapt {
162 result.push(BlockState::new(new_block, ctx, allocs));
163 continue;
164 }
165 loop {
167 let Some(old_block) = old_iter.next() else {
169 return Err(UpdateError::ToposortCycle);
170 };
171 if old_block.name != new_block.name {
173 result.push(*old_block);
174 continue;
175 }
176 result.push(old_block.update(new_block, ctx, allocs));
177 break;
178 }
179 }
180 for old_block in old_iter {
181 result.push(*old_block);
182 }
183
184 Ok(Self {
185 name: self.name,
186 args: self.args,
187 blocks: allocs.alloc_extend(result),
188 })
189 }
190}
191
192#[derive(Copy, Clone)]
193pub struct BlockState<'arn, 'grm> {
194 pub name: &'grm str,
195 pub constructors: &'arn [Constructor<'arn, 'grm>],
196}
197
198pub type Constructor<'arn, 'grm> = (&'arn AnnotatedRuleExpr<'arn, 'grm>, VarMap<'arn, 'grm>);
199
200impl<'arn, 'grm> BlockState<'arn, 'grm> {
201 pub fn new(
202 block: &'arn Block<'arn, 'grm>,
203 ctx: VarMap<'arn, 'grm>,
204 allocs: Allocs<'arn>,
205 ) -> Self {
206 Self {
207 name: block.name,
208 constructors: allocs.alloc_extend(block.constructors.iter().map(|r| (r, ctx))),
209 }
210 }
211
212 #[must_use]
213 pub fn update(
214 &self,
215 b: &'arn Block<'arn, 'grm>,
216 ctx: VarMap<'arn, 'grm>,
217 allocs: Allocs<'arn>,
218 ) -> Self {
219 assert_eq!(self.name, b.name);
220 Self {
221 name: self.name,
222 constructors: allocs.alloc_extend_len(
223 self.constructors.len() + b.constructors.len(),
224 self.constructors
225 .iter()
226 .cloned()
227 .chain(b.constructors.iter().map(|r| (r, ctx))),
228 ),
229 }
230 }
231}