wagon_parser/
firstpass.rs

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
8/// Set of all attributes that are required to be in scope for something.
9pub(crate) type ReqAttributes = IndexSet<SpannableNode<Ident>>;
10
11/// Any node that can be rewritten in a different way for any reason should implement this trait.
12pub(crate) trait Rewrite<T> {
13	fn rewrite(&mut self, depth: usize, state: &mut FirstPassState) -> FirstPassResult<T>;
14}
15
16/// A state object to keep track of things during rewriting.
17#[derive(Debug, Default)]
18pub(crate) struct FirstPassState {
19	parameter_map: HashMap<String, IndexSet<SpannableNode<Ident>>>
20}
21
22/// After rewriting/typechecking, we either return something or we have a [`WagCheckError`].
23pub type FirstPassResult<T> = Result<T, WagCheckError>;
24
25#[derive(PartialEq, Eq, Debug)]
26/// Any error that can occur during the rewriting/checking process.
27pub enum WagCheckError {
28	/// A rule wants multiple parameters, but they are the exact same.
29	DuplicateParameters(String, SpannableNode<Ident>),
30	/// Two alternative instances of a rule want different parameters.
31	DisparateParameters {
32		/// The non-terminal which has the issue.
33		terminal: String,
34		/// The specific [`Ident`] which caused the issue.
35		offender: Vec<SpannableNode<Ident>>,
36		/// The [`Ident`] we expected to see.
37		expected: Vec<SpannableNode<Ident>>,
38		/// The span information of this node.
39		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(&param) {
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	// pub(crate) fn get_parameters(&self, s: &str) -> Option<&IndexSet<SpannableNode<Ident>>> {
86	// 	self.parameter_map.get(s)
87	// }
88}
89
90/// Trait to determine which attributes are required to be in scope for this part of the tree.
91pub(crate) trait GetReqAttributes {
92	fn get_req_attributes(&self) -> ReqAttributes;
93}
94
95/// Trait to convert all attributes to synth and return a list of all of them.
96pub(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}