general_parser/
expression.rs

1use crate::{Allocator, Configuration, Lexer, Literal};
2
3#[cfg(not(feature = "stable"))]
4use std::alloc::Allocator as AllocatorTrait;
5
6#[cfg(feature = "stable")]
7use allocator_api2::vec::Vec;
8
9#[derive(Debug)]
10pub struct Expression<'a, T> {
11	pub on: T,
12	pub arguments: Vec<Expression<'a, T>, &'a Allocator>,
13}
14
15impl<'a, T> Expression<'a, T>
16where
17	T: Literal<'a>,
18{
19	pub fn from_string(
20		source: &'a str,
21		configuration: &'a Configuration,
22		allocator: &'a Allocator,
23	) -> Self {
24		let mut reader = Lexer::new(source);
25		let this = Self::from_reader(&mut reader, configuration, allocator);
26		reader.skip();
27		if !reader.finished() {
28			panic!("not finished {:?}", reader.current());
29		}
30		this
31	}
32
33	pub fn from_reader(
34		reader: &mut Lexer<'a>,
35		configuration: &'a Configuration,
36		allocator: &'a Allocator,
37	) -> Self {
38		Self::from_reader_with_precedence(reader, configuration, allocator, 0, None)
39	}
40
41	pub(crate) fn from_reader_with_precedence(
42		reader: &mut Lexer<'a>,
43		configuration: &'a Configuration,
44		allocator: &'a Allocator,
45		precedence: u8,
46		break_before: Option<&'a str>,
47	) -> Self {
48		if reader.starts_with("(") {
49			reader.advance(1);
50			let value = Expression::from_reader(reader, configuration, allocator);
51			if reader.starts_with(")") {
52				reader.advance(1);
53				value
54			} else {
55				panic!("no close paren {current:?}", current = reader.current());
56			}
57		} else {
58			let top = if let Some(prefix) = configuration
59				.prefix_ternary_operators
60				.iter()
61				.find(|operator| reader.starts_with(operator.parts.0))
62			{
63				// hmm
64				// if precedence.order > operator.precedence {
65				//     return top;
66				// }
67
68				reader.advance(prefix.parts.0.len());
69
70				let next = Self::from_reader_with_precedence(
71					reader,
72					configuration,
73					allocator,
74					prefix.precedence,
75					Some(prefix.parts.1),
76				);
77				if reader.starts_with(prefix.parts.1) {
78					reader.advance(prefix.parts.1.len());
79				} else {
80					// TODO check prefix operators
81					panic!("{:?}", (reader.current(), prefix.parts.1));
82				}
83
84				let lhs = Self::from_reader_with_precedence(
85					reader,
86					configuration,
87					allocator,
88					prefix.precedence,
89					Some(prefix.parts.2),
90				);
91				if reader.starts_with(prefix.parts.2) {
92					reader.advance(prefix.parts.2.len());
93				} else {
94					panic!()
95				}
96				let rhs = Self::from_reader_with_precedence(
97					reader,
98					configuration,
99					allocator,
100					prefix.precedence,
101					break_before,
102				);
103
104				let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
105				arguments.push(next);
106				arguments.push(lhs);
107				arguments.push(rhs);
108
109				let on = T::from_str(prefix.name);
110				Expression { on, arguments }
111			} else if let Some(operator) = configuration
112				.prefix_unary_operators
113				.iter()
114				.find(|operator| reader.starts_with(operator.representation))
115			{
116				// hmm
117				// if precedence > operator.precedence {
118				//     return top;
119				// }
120
121				reader.advance(operator.representation.len());
122				let operand = Self::from_reader_with_precedence(
123					reader,
124					configuration,
125					allocator,
126					operator.precedence,
127					break_before,
128				);
129
130				let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
131				arguments.push(operand);
132				Expression { on: T::from_str(operator.representation), arguments }
133			} else {
134				let identifier = reader.parse_identifier();
135
136				if let Some(ref adjacency) = configuration.adjacency
137					&& !adjacency.functions.contains(&identifier)
138				{
139					// TODO slice iterator
140					let mut chars = identifier.char_indices();
141
142					let first: Self = {
143						let (idx, chr) = chars.next().unwrap();
144						let identifier = &identifier[idx..(idx + chr.len_utf8())];
145						Expression {
146							on: T::from_str(identifier),
147							arguments: Vec::new_in(allocator),
148						}
149					};
150
151					let mut top = first;
152
153					for (idx, chr) in chars {
154						let identifier = &identifier[idx..(idx + chr.len_utf8())];
155						let rhs = Expression {
156							on: T::from_str(identifier),
157							arguments: Vec::new_in(allocator),
158						};
159
160						let mut arguments = Vec::new_in(allocator);
161						arguments.push(top);
162						arguments.push(rhs);
163						top = Expression {
164							on: T::from_str(adjacency.operator.representation),
165							arguments,
166						};
167					}
168
169					top
170				} else {
171					let on = T::from_str(identifier);
172
173					let mut arguments = Vec::new_in(allocator);
174
175					// TODO WIP check
176					while reader.starts_with_value() {
177						let Configuration {
178							binary_operators,
179							postfix_ternary_operators,
180							postfix_unary_operators,
181							..
182						} = &configuration;
183
184						let should_break = binary_operators
185							.iter()
186							.any(|operator| reader.starts_with(operator.representation))
187							|| postfix_ternary_operators
188								.iter()
189								.any(|operator| reader.starts_with(operator.parts.0))
190							|| postfix_unary_operators
191								.iter()
192								.any(|operator| reader.starts_with(operator.representation))
193							|| break_before
194								.is_some_and(|break_before| reader.starts_with(break_before));
195
196						if should_break {
197							break;
198						}
199
200						let expression = Self::from_reader_with_precedence(
201							reader,
202							configuration,
203							allocator,
204							1,
205							break_before,
206						);
207						arguments.push(expression);
208					}
209
210					Expression { on, arguments }
211				}
212			};
213
214			Self::append_operators(reader, configuration, allocator, precedence, break_before, top)
215		}
216	}
217
218	fn append_operators(
219		reader: &mut Lexer<'a>,
220		configuration: &'a Configuration,
221		allocator: &'a Allocator,
222		return_precedence: u8,
223		break_before: Option<&'a str>,
224		mut top: Self,
225	) -> Self {
226		while !reader.finished() {
227			if break_before.is_some_and(|break_before| reader.starts_with(break_before)) {
228				break;
229			}
230
231			top = if let Some(postfix) = configuration
232				.postfix_ternary_operators
233				.iter()
234				.find(|operator| reader.starts_with(operator.parts.0))
235			{
236				if return_precedence > postfix.precedence {
237					return top;
238				}
239
240				reader.advance(postfix.parts.0.len());
241				let lhs = Self::from_reader_with_precedence(
242					reader,
243					configuration,
244					allocator,
245					postfix.precedence,
246					Some(postfix.parts.1),
247				);
248
249				if reader.starts_with(postfix.parts.1) {
250					reader.advance(postfix.parts.1.len());
251					let rhs = Self::from_reader_with_precedence(
252						reader,
253						configuration,
254						allocator,
255						postfix.precedence,
256						Some(postfix.parts.2),
257					);
258
259					if reader.starts_with(postfix.parts.2) {
260						reader.advance(postfix.parts.2.len());
261					} else {
262						panic!()
263					}
264
265					let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
266					arguments.push(top);
267					arguments.push(lhs);
268					arguments.push(rhs);
269
270					let on = T::from_str(postfix.name);
271					Expression { on, arguments }
272				} else {
273					let substitute_binary_operator = configuration
274						.binary_operators
275						.iter()
276						.find(|operator| operator.representation == postfix.parts.0);
277
278					if let Some(operator) = substitute_binary_operator {
279						debug_assert!(
280							return_precedence <= operator.precedence,
281							"binary operator {bop_prec} not equal to ternary {tern_prec} ({return_precedence})",
282							bop_prec = operator.precedence,
283							tern_prec = postfix.precedence
284						);
285
286						let mut arguments = Vec::new_in(allocator);
287						arguments.push(top);
288						arguments.push(lhs);
289
290						let on = T::from_str(operator.representation);
291						Expression { on, arguments }
292					} else {
293						panic!(
294							"Expected {part} found {found}",
295							part = postfix.parts.1,
296							found = reader.current()
297						);
298					}
299				}
300			} else if let Some(operator) = configuration
301				.binary_operators
302				.iter()
303				.find(|operator| reader.starts_with(operator.representation))
304			{
305				if return_precedence > operator.precedence {
306					return top;
307				}
308
309				reader.advance(operator.representation.len());
310				let lhs = top;
311				let rhs = Self::from_reader_with_precedence(
312					reader,
313					configuration,
314					allocator,
315					operator.precedence,
316					break_before,
317				);
318
319				let mut arguments = Vec::new_in(allocator);
320				arguments.push(lhs);
321				arguments.push(rhs);
322
323				let on = T::from_str(operator.representation);
324				Expression { on, arguments }
325			} else if let Some(operator) = configuration
326				.postfix_unary_operators
327				.iter()
328				.find(|operator| reader.starts_with(operator.representation))
329			{
330				if return_precedence > operator.precedence {
331					return top;
332				}
333				reader.advance(operator.representation.len());
334				let mut arguments = Vec::new_in(allocator);
335				arguments.push(top);
336
337				let on = T::from_str(operator.representation);
338				Expression { on, arguments }
339			} else if reader.current().starts_with('(')
340				&& let Some(adjacency) = &configuration.adjacency
341			{
342				let operator = adjacency.operator;
343				if return_precedence > operator.precedence {
344					return top;
345				}
346
347				let rhs = Self::from_reader_with_precedence(
348					reader,
349					configuration,
350					allocator,
351					operator.precedence,
352					break_before,
353				);
354				let mut arguments = Vec::new_in(allocator);
355				arguments.push(top);
356				arguments.push(rhs);
357				Expression { on: T::from_str(operator.representation), arguments }
358			} else {
359				break;
360			};
361		}
362		top
363	}
364}
365
366pub struct ExpressionRepresentation<'a, T>(pub &'a Expression<'a, T>);
367
368impl<'a, T> std::fmt::Display for ExpressionRepresentation<'a, T>
369where
370	T: std::fmt::Display,
371{
372	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
373		if self.0.arguments.is_empty() {
374			write!(f, "{on}", on = self.0.on)
375		} else {
376			write!(f, "({on}", on = self.0.on)?;
377			for arg in &self.0.arguments {
378				write!(f, " {on}", on = ExpressionRepresentation(arg))?;
379			}
380			write!(f, ")")
381		}
382	}
383}