1use std::fmt::Display;
2use wagon_utils::{Spannable, ErrorReport, Span};
3use crate::SpannableNode;
4use std::{collections::HashMap, error::Error};
5use indexmap::IndexSet;
6use wagon_ident::Ident;
7
8pub(crate) type ReqAttributes = IndexSet<SpannableNode<Ident>>;
10
11pub(crate) trait Rewrite<T> {
13 fn rewrite(&mut self, depth: usize, state: &mut FirstPassState) -> FirstPassResult<T>;
14}
15
16#[derive(Debug, Default)]
18pub(crate) struct FirstPassState {
19 parameter_map: HashMap<String, IndexSet<SpannableNode<Ident>>>
20}
21
22pub type FirstPassResult<T> = Result<T, WagCheckError>;
24
25#[derive(PartialEq, Eq, Debug)]
26pub enum WagCheckError {
28 DuplicateParameters(String, SpannableNode<Ident>),
30 DisparateParameters {
32 terminal: String,
34 offender: Vec<SpannableNode<Ident>>,
36 expected: Vec<SpannableNode<Ident>>,
38 span: Span
40 },
41}
42
43impl Error for WagCheckError{}
44
45impl ErrorReport for WagCheckError {
46 fn msg(&self) -> (String, String) {
47 match self {
48 Self::DuplicateParameters(nt, i) => ("Duplicate Parameter!".to_string(), format!("Nonterminal {nt} uses parameter {i} multiple times. This makes no sense.")),
49 Self::DisparateParameters { terminal, offender, expected, ..} => ("Disparate Parameters!".to_string(), format!("Instance of terminal {terminal} uses parameters {offender:?} while it was defined earlier as {expected:?}. This is unsupported")),
50 }
51 }
52
53 fn span(self) -> Span {
54 match self {
55 Self::DuplicateParameters(_, i) => i.span(),
56 Self::DisparateParameters { span, .. } => span,
57 }
58 }
59}
60
61impl Display for WagCheckError {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 let (head, msg) = self.msg();
64 write!(f, "{head}: {msg}")
65 }
66}
67
68impl FirstPassState {
69 pub(crate) fn add_parameter(&mut self, nt: String, param: SpannableNode<Ident>) -> FirstPassResult<()> {
70 if let Some(params) = self.parameter_map.get_mut(&nt) {
71 if params.contains(¶m) {
72 Err(WagCheckError::DuplicateParameters(nt, param))
73 } else {
74 params.insert(param);
75 Ok(())
76 }
77 } else {
78 let mut set = IndexSet::new();
79 set.insert(param);
80 self.parameter_map.insert(nt, set);
81 Ok(())
82 }
83 }
84
85 }
89
90pub(crate) trait GetReqAttributes {
92 fn get_req_attributes(&self) -> ReqAttributes;
93}
94
95pub(crate) trait RewriteToSynth {
97 fn rewrite_to_synth(&mut self) -> ReqAttributes;
98}
99
100#[cfg(test)]
101mod test {
102
103 use crate::parser::Parser;
104 use super::{FirstPassState, Rewrite};
105
106 use pretty_assertions::assert_eq;
107
108 fn test_inputs(input: &str, expected_input: &str) {
109 let mut parser = Parser::new(input);
110 let mut output = parser.parse().unwrap();
111 output.rewrite(0, &mut FirstPassState::default()).unwrap();
112 let mut parser = Parser::new(expected_input);
113 let expected = parser.parse().unwrap();
114 assert_eq!(expected, output);
115 }
116
117 #[test]
118 fn test_simple_rewrite_maybe() {
119 let input = r"
120 A -> X Y?;
121 ";
122 let expected_input = r"
123 A -> X A·0·1;
124 A·0·1 -> Y | ;
125 ";
126 test_inputs(input, expected_input);
127 }
128
129 #[test]
130 fn test_simple_rewrite_many() {
131 let input = r"
132 A -> X Y*;
133 ";
134 let expected_input = r"
135 A -> X A·0·1;
136 A·0·1 -> Y A·0·1 | ;
137 ";
138 test_inputs(input, expected_input);
139 }
140
141 #[test]
142 fn test_simple_rewrite_some() {
143 let input = r"
144 A -> X Y+;
145 ";
146 let expected_input = r"
147 A -> X A·0·1;
148 A·0·1·p -> Y A·0·1·p | ;
149 A·0·1 -> Y A·0·1·p;
150 ";
151 test_inputs(input, expected_input);
152 }
153
154 #[test]
155 fn test_simple_group() {
156 let input = r"
157 A -> (B C?)+;
158 ";
159 let expected_input = r"
160 A -> A·0·0;
161 A·0·0·p -> A·0·0··0 A·0·0·p | ;
162 A·0·0 -> A·0·0··0 A·0·0·p;
163 A·0·0··0 -> B A·0·0··0·0·1;
164 A·0·0··0·0·1 -> C | ;
165 ";
166 test_inputs(input, expected_input);
167 }
168
169 #[test]
170 fn test_complex_rewrite() {
171 let input = r"
172 A -> ((X Y)+ Z?)+;
173 ";
174 let expected_input = r"
175 A -> A·0·0;
176 A·0·0·p -> A·0·0··0 A·0·0·p | ;
177 A·0·0 -> A·0·0··0 A·0·0·p;
178 A·0·0··0 -> A·0·0··0·0·0 A·0·0··0·0·1;
179 A·0·0··0·0·0·p -> A·0·0··0·0·0··1 A·0·0··0·0·0·p | ;
180 A·0·0··0·0·0 -> A·0·0··0·0·0··1 A·0·0··0·0·0·p;
181 A·0·0··0·0·0··1 -> X Y;
182 A·0·0··0·0·1 -> Z | ;
183 ";
184 test_inputs(input, expected_input);
185 }
186
187 #[test]
188 fn test_rewrite_group_no_ebnf() {
189 let input = r"
190 A -> (B C);
191 ";
192 let expected_input = r"
193 A -> A·0·0;
194 A·0·0 -> B C;
195 ";
196 test_inputs(input, expected_input);
197 }
198
199 #[test]
200 fn test_rewrite_conflict() {
201 let input = r"
202 A -> B;
203 A -> C;
204 A -> ;
205 ";
206 let expected_input = r"
207 A -> B | C | ;
208 ";
209 test_inputs(input, expected_input);
210 }
211
212 #[test]
213 fn test_simple_rewrite_with_attrs() {
214 let input = r"
215 A<*a> -> B<*a, $b>+;
216 ";
217 let expected_input = r"
218 A<*a> -> A·0·0<*a, $b>;
219 A·0·0·p<&a, &b> -> B<&a, &b> A·0·0·p<&a, &b> | ;
220 A·0·0<&a, &b> -> B<&a, &b> A·0·0·p<&a, &b>;
221 ";
222 test_inputs(input, expected_input);
223 }
224
225 #[test]
226 fn test_simple_group_with_attrs() {
227 let input = r"
228 A<*x> -> (B<*x> C<$y>?)+;
229 ";
230 let expected_input = r"
231 A<*x> -> A·0·0<*x, $y>;
232 A·0·0·p<&x, &y> -> A·0·0··0<&x, &y> A·0·0·p<&x, &y> | ;
233 A·0·0<&x, &y> -> A·0·0··0<&x, &y> A·0·0·p<&x, &y>;
234 A·0·0··0<&x, &y> -> B<&x> A·0·0··0·0·1<&y>;
235 A·0·0··0·0·1<&y> -> C<&y> | ;
236 ";
237 test_inputs(input, expected_input);
238 }
239
240 #[test]
241 fn test_complex_rewrite_with_attrs() {
242 let input = r"
243 A<*a, *b> -> ((X<*a, *b> Y<*b, $c>)+ Z<$c>?)+;
244 ";
245 let expected_input = r"
246 A<*a, *b> -> A·0·0<*a, *b, $c>;
247 A·0·0·p<&a, &b, &c> -> A·0·0··0<&a, &b, &c> A·0·0·p<&a, &b, &c> | ;
248 A·0·0<&a, &b, &c> -> A·0·0··0<&a, &b, &c> A·0·0·p<&a, &b, &c>;
249 A·0·0··0<&a, &b, &c> -> A·0·0··0·0·0<&a, &b, &c> A·0·0··0·0·1<&c>;
250 A·0·0··0·0·0·p<&a, &b, &c> -> A·0·0··0·0·0··1<&a, &b, &c> A·0·0··0·0·0·p<&a, &b, &c> | ;
251 A·0·0··0·0·0<&a, &b, &c> -> A·0·0··0·0·0··1<&a, &b, &c> A·0·0··0·0·0·p<&a, &b, &c>;
252 A·0·0··0·0·0··1<&a, &b, &c> -> X<&a, &b> Y<&b, &c>;
253 A·0·0··0·0·1<&c> -> Z<&c> | ;
254 ";
255 test_inputs(input, expected_input);
256 }
257
258 #[test]
259 fn test_group_no_ebnf_with_attrs() {
260 let input = r"
261 A<*a> -> (B<*a> C<$b>);
262 ";
263 let expected_input = r"
264 A<*a> -> A·0·0<*a, $b>;
265 A·0·0<&a, &b> -> B<&a> C<&b>;
266 ";
267 test_inputs(input, expected_input);
268 }
269}