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		config: &'a Configuration,
22		allocator: &'a Allocator,
23	) -> Self {
24		let mut reader = Lexer::new(source);
25		let this = Self::from_reader(&mut reader, config, 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		config: &'a Configuration,
36		allocator: &'a Allocator,
37	) -> Self {
38		Self::from_reader_with_precedence(reader, config, allocator, 0)
39	}
40
41	pub(crate) fn from_reader_with_precedence(
42		reader: &mut Lexer<'a>,
43		config: &'a Configuration,
44		allocator: &'a Allocator,
45		precedence: u8,
46	) -> Self {
47		let operator = config
48			.prefix_unary_operators
49			.iter()
50			.find(|operator| reader.starts_with(operator.representation));
51
52		let top = if let Some(operator) = operator {
53			// hmm
54			// if precedence > operator.precedence {
55			//     return top;
56			// }
57			reader.advance(operator.representation.len());
58			let operand =
59				Self::from_reader_with_precedence(reader, config, allocator, operator.precedence);
60			let mut arguments: Vec<Expression<_>, &Allocator> = Vec::new_in(allocator);
61			arguments.push(operand);
62			Expression { on: T::from_str(operator.representation), arguments }
63		} else if reader.starts_with("(") {
64			reader.advance(1);
65			let value = Expression::from_reader(reader, config, allocator);
66			if reader.starts_with(")") {
67				reader.advance(1);
68			} else {
69				panic!("no close paren {current:?}", current = reader.current());
70			};
71
72			value
73		} else {
74			let identifier = reader.parse_identifier();
75
76			if let Some(ref adjacency) = config.adjacency
77				&& !adjacency.functions.contains(&identifier)
78			{
79				let mut chars = identifier.char_indices();
80
81				let first: Self = {
82					let (idx, chr) = chars.next().unwrap();
83					let identifier = &identifier[idx..(idx + chr.len_utf8())];
84					Expression { on: T::from_str(identifier), arguments: Vec::new_in(allocator) }
85				};
86
87				let mut top = first;
88
89				for (idx, chr) in chars {
90					let identifier = &identifier[idx..(idx + chr.len_utf8())];
91					let rhs = Expression {
92						on: T::from_str(identifier),
93						arguments: Vec::new_in(allocator),
94					};
95
96					let mut arguments = Vec::new_in(allocator);
97					arguments.push(top);
98					arguments.push(rhs);
99					top = Expression {
100						on: T::from_str(adjacency.operator.representation),
101						arguments,
102					};
103				}
104
105				top
106			} else {
107				let on = T::from_str(identifier);
108
109				let mut arguments = Vec::new_in(allocator);
110				// TODO WIP
111				if precedence == 0 {
112					while reader.starts_with_value() {
113						let expression =
114							Self::from_reader_with_precedence(reader, config, allocator, 1);
115						arguments.push(expression);
116					}
117				}
118
119				Expression { on, arguments }
120			}
121		};
122		Self::append_operators(reader, config, allocator, precedence, top)
123	}
124
125	fn append_operators(
126		reader: &mut Lexer<'a>,
127		config: &'a Configuration,
128		allocator: &'a Allocator,
129		return_precedence: u8,
130		mut top: Self,
131	) -> Self {
132		while !reader.finished() {
133			let binary_operator = config
134				.binary_operators
135				.iter()
136				.find(|operator| reader.starts_with(operator.representation));
137
138			if let Some(operator) = binary_operator {
139				if return_precedence > operator.precedence {
140					return top;
141				}
142
143				reader.advance(operator.representation.len());
144				let lhs = top;
145				let rhs = Self::from_reader_with_precedence(
146					reader,
147					config,
148					allocator,
149					operator.precedence,
150				);
151
152				let mut arguments = Vec::new_in(allocator);
153				arguments.push(lhs);
154				arguments.push(rhs);
155
156				top = Expression { on: T::from_str(operator.representation), arguments };
157			} else {
158				let unary_operator = config
159					.postfix_unary_operators
160					.iter()
161					.find(|operator| reader.starts_with(operator.representation));
162
163				if let Some(operator) = unary_operator {
164					if return_precedence > operator.precedence {
165						return top;
166					}
167					reader.advance(operator.representation.len());
168					let mut arguments = Vec::new_in(allocator);
169					arguments.push(top);
170
171					top = Expression { on: T::from_str(operator.representation), arguments };
172				} else if reader.current().starts_with('(')
173					&& let Some(adjacency) = &config.adjacency
174				{
175					let operator = adjacency.operator;
176					if return_precedence > operator.precedence {
177						return top;
178					}
179
180					let rhs = Self::from_reader_with_precedence(
181						reader,
182						config,
183						allocator,
184						operator.precedence,
185					);
186					let mut arguments = Vec::new_in(allocator);
187					arguments.push(top);
188					arguments.push(rhs);
189					top = Expression { on: T::from_str(operator.representation), arguments };
190				} else {
191					break;
192				}
193			}
194		}
195		top
196	}
197}
198
199pub struct ExpressionRepresentation<'a, T>(pub &'a Expression<'a, T>);
200
201impl<'a, T> std::fmt::Display for ExpressionRepresentation<'a, T>
202where
203	T: std::fmt::Display,
204{
205	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
206		if self.0.arguments.is_empty() {
207			write!(f, "{on}", on = self.0.on)
208		} else {
209			write!(f, "({on}", on = self.0.on)?;
210			for arg in &self.0.arguments {
211				write!(f, " {on}", on = ExpressionRepresentation(arg))?;
212			}
213			write!(f, ")")
214		}
215	}
216}