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 mut value = Expression::from_reader(reader, configuration, allocator);
51			if reader.starts_with(")") {
52				reader.advance(1);
53
54				if let Some(ref adjacency) = configuration.adjacency
55					&& reader.starts_with_value()
56				{
57					let identifier = reader.parse_identifier();
58					let rhs = Expression {
59						on: T::from_str(identifier),
60						arguments: Vec::new_in(allocator),
61					};
62
63					let mut arguments = Vec::new_in(allocator);
64					arguments.push(value);
65					arguments.push(rhs);
66					value = Expression {
67						on: T::from_str(adjacency.operator.representation),
68						arguments,
69					};
70				}
71
72				value
73			} else {
74				panic!("no close paren {current:?}", current = reader.current());
75			}
76		} else {
77			let top = if let Some(prefix) = configuration
78				.prefix_ternary_operators
79				.iter()
80				.find(|operator| reader.starts_with(operator.parts.0))
81			{
82				// hmm
83				// if precedence.order > operator.precedence {
84				//     return top;
85				// }
86
87				reader.advance(prefix.parts.0.len());
88
89				let next = Self::from_reader_with_precedence(
90					reader,
91					configuration,
92					allocator,
93					prefix.precedence,
94					Some(prefix.parts.1),
95				);
96				if reader.starts_with(prefix.parts.1) {
97					reader.advance(prefix.parts.1.len());
98				} else {
99					// TODO check prefix operators
100					panic!("{:?}", (reader.current(), prefix.parts.1));
101				}
102
103				let lhs = Self::from_reader_with_precedence(
104					reader,
105					configuration,
106					allocator,
107					prefix.precedence,
108					Some(prefix.parts.2),
109				);
110				if reader.starts_with(prefix.parts.2) {
111					reader.advance(prefix.parts.2.len());
112				} else {
113					panic!()
114				}
115				let rhs = Self::from_reader_with_precedence(
116					reader,
117					configuration,
118					allocator,
119					prefix.precedence,
120					break_before,
121				);
122
123				let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
124				arguments.push(next);
125				arguments.push(lhs);
126				arguments.push(rhs);
127
128				let on = T::from_str(prefix.name);
129				Expression { on, arguments }
130			} else if let Some(operator) = configuration
131				.prefix_unary_operators
132				.iter()
133				.find(|operator| reader.starts_with(operator.representation))
134			{
135				// hmm
136				// if precedence > operator.precedence {
137				//     return top;
138				// }
139
140				reader.advance(operator.representation.len());
141				let operand = Self::from_reader_with_precedence(
142					reader,
143					configuration,
144					allocator,
145					operator.precedence,
146					break_before,
147				);
148
149				let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
150				arguments.push(operand);
151				Expression { on: T::from_str(operator.representation), arguments }
152			} else {
153				let identifier = reader.parse_identifier();
154
155				if let Some(ref adjacency) = configuration.adjacency {
156					let parts = identifier
157						.find(|chr| !matches!(chr, '0'..='9' | '.'))
158						.map(|idx| identifier.split_at(idx));
159
160					if let Some((numeric, item)) = parts {
161						let top = if adjacency.functions.contains(&item) {
162							let on = T::from_str(item);
163							Expression::parse_function_call(
164								reader,
165								configuration,
166								allocator,
167								break_before,
168								on,
169							)
170						} else {
171							let (prefix, after) = item.split_at(1);
172							let mut top = Expression {
173								on: T::from_str(prefix),
174								arguments: Vec::new_in(allocator),
175							};
176							for slice in chars_slices(after) {
177								let item = Expression {
178									on: T::from_str(slice),
179									arguments: Vec::new_in(allocator),
180								};
181
182								let mut arguments = Vec::new_in(allocator);
183								arguments.push(item);
184								arguments.push(top);
185								top = Expression {
186									on: T::from_str(adjacency.operator.representation),
187									arguments,
188								};
189							}
190							top
191						};
192						if numeric.is_empty() {
193							top
194						} else {
195							let item = Expression {
196								on: T::from_str(numeric),
197								arguments: Vec::new_in(allocator),
198							};
199
200							let mut arguments = Vec::new_in(allocator);
201							arguments.push(item);
202							arguments.push(top);
203							Expression {
204								on: T::from_str(adjacency.operator.representation),
205								arguments,
206							}
207						}
208					} else {
209						Expression {
210							on: T::from_str(identifier),
211							arguments: Vec::new_in(allocator),
212						}
213					}
214				} else {
215					let on = T::from_str(identifier);
216					Expression::parse_function_call(
217						reader,
218						configuration,
219						allocator,
220						break_before,
221						on,
222					)
223				}
224			};
225
226			Self::append_operators(reader, configuration, allocator, precedence, break_before, top)
227		}
228	}
229
230	fn append_operators(
231		reader: &mut Lexer<'a>,
232		configuration: &'a Configuration,
233		allocator: &'a Allocator,
234		return_precedence: u8,
235		break_before: Option<&'a str>,
236		mut top: Self,
237	) -> Self {
238		while !reader.finished() {
239			if break_before.is_some_and(|break_before| reader.starts_with(break_before)) {
240				break;
241			}
242
243			top = if let Some(postfix) = configuration
244				.postfix_ternary_operators
245				.iter()
246				.find(|operator| reader.starts_with(operator.parts.0))
247			{
248				if return_precedence > postfix.precedence {
249					return top;
250				}
251
252				reader.advance(postfix.parts.0.len());
253				let lhs = Self::from_reader_with_precedence(
254					reader,
255					configuration,
256					allocator,
257					postfix.precedence,
258					Some(postfix.parts.1),
259				);
260
261				if reader.starts_with(postfix.parts.1) {
262					reader.advance(postfix.parts.1.len());
263					let rhs = Self::from_reader_with_precedence(
264						reader,
265						configuration,
266						allocator,
267						postfix.precedence,
268						Some(postfix.parts.2),
269					);
270
271					if reader.starts_with(postfix.parts.2) {
272						reader.advance(postfix.parts.2.len());
273					} else {
274						panic!()
275					}
276
277					let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
278					arguments.push(top);
279					arguments.push(lhs);
280					arguments.push(rhs);
281
282					let on = T::from_str(postfix.name);
283					Expression { on, arguments }
284				} else {
285					let substitute_binary_operator = configuration
286						.binary_operators
287						.iter()
288						.find(|operator| operator.representation == postfix.parts.0);
289
290					if let Some(operator) = substitute_binary_operator {
291						debug_assert!(
292							return_precedence <= operator.precedence,
293							"binary operator {bop_prec} not equal to ternary {tern_prec} ({return_precedence})",
294							bop_prec = operator.precedence,
295							tern_prec = postfix.precedence
296						);
297
298						let mut arguments = Vec::new_in(allocator);
299						arguments.push(top);
300						arguments.push(lhs);
301
302						let on = T::from_str(operator.representation);
303						Expression { on, arguments }
304					} else {
305						panic!(
306							"Expected {part} found {found}",
307							part = postfix.parts.1,
308							found = reader.current()
309						);
310					}
311				}
312			} else if let Some(operator) = configuration
313				.binary_operators
314				.iter()
315				.find(|operator| reader.starts_with(operator.representation))
316			{
317				if return_precedence > operator.precedence {
318					return top;
319				}
320
321				reader.advance(operator.representation.len());
322				let lhs = top;
323				let rhs = Self::from_reader_with_precedence(
324					reader,
325					configuration,
326					allocator,
327					operator.precedence,
328					break_before,
329				);
330
331				let mut arguments = Vec::new_in(allocator);
332				arguments.push(lhs);
333				arguments.push(rhs);
334
335				let on = T::from_str(operator.representation);
336				Expression { on, arguments }
337			} else if let Some(operator) = configuration
338				.postfix_unary_operators
339				.iter()
340				.find(|operator| reader.starts_with(operator.representation))
341			{
342				if return_precedence > operator.precedence {
343					return top;
344				}
345				reader.advance(operator.representation.len());
346				let mut arguments = Vec::new_in(allocator);
347				arguments.push(top);
348
349				let on = T::from_str(operator.representation);
350				Expression { on, arguments }
351			} else if reader.current().starts_with('(')
352				&& let Some(adjacency) = &configuration.adjacency
353			{
354				let operator = adjacency.operator;
355				if return_precedence > operator.precedence {
356					return top;
357				}
358
359				let rhs = Self::from_reader_with_precedence(
360					reader,
361					configuration,
362					allocator,
363					operator.precedence,
364					break_before,
365				);
366				let mut arguments = Vec::new_in(allocator);
367				arguments.push(top);
368				arguments.push(rhs);
369				Expression { on: T::from_str(operator.representation), arguments }
370			} else {
371				break;
372			};
373		}
374		top
375	}
376
377	fn parse_function_call(
378		reader: &mut Lexer<'a>,
379		configuration: &'a Configuration,
380		allocator: &'a Allocator,
381		break_before: Option<&'a str>,
382		on: T,
383	) -> Self {
384		let mut arguments = Vec::new_in(allocator);
385
386		while reader.starts_with_value() {
387			let Configuration {
388				binary_operators,
389				postfix_ternary_operators,
390				postfix_unary_operators,
391				..
392			} = &configuration;
393
394			let should_break =
395				binary_operators.iter().any(|operator| reader.starts_with(operator.representation))
396					|| postfix_ternary_operators
397						.iter()
398						.any(|operator| reader.starts_with(operator.parts.0))
399					|| postfix_unary_operators
400						.iter()
401						.any(|operator| reader.starts_with(operator.representation))
402					|| break_before.is_some_and(|break_before| reader.starts_with(break_before));
403
404			if should_break {
405				break;
406			}
407
408			let expression = Self::from_reader_with_precedence(
409				reader,
410				configuration,
411				allocator,
412				1,
413				break_before,
414			);
415			arguments.push(expression);
416		}
417
418		Expression { on, arguments }
419	}
420}
421
422fn chars_slices(slice: &str) -> impl Iterator<Item = &str> {
423	slice.char_indices().map(|(idx, chr)| &slice[idx..][..chr.len_utf8()])
424}
425
426pub struct ExpressionRepresentation<'a, T>(pub &'a Expression<'a, T>);
427
428impl<'a, T> std::fmt::Display for ExpressionRepresentation<'a, T>
429where
430	T: std::fmt::Display,
431{
432	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
433		if self.0.arguments.is_empty() {
434			write!(f, "{on}", on = self.0.on)
435		} else {
436			write!(f, "({on}", on = self.0.on)?;
437			for arg in &self.0.arguments {
438				write!(f, " {on}", on = ExpressionRepresentation(arg))?;
439			}
440			write!(f, ")")
441		}
442	}
443}