1use crate::ast::{
2 ArrayExpression, BinaryExpression, CallExpression, ClassExpression, CommaExpression,
3 DelegateExpression, ExpectExpression, Expression, FunctionExpression, IndexExpression,
4 LiteralExpression, ParensExpression, PostfixExpression, Precedence, PrefixExpression,
5 PropertyExpression, RootVarExpression, TableExpression, TernaryExpression, VarExpression,
6 VectorExpression,
7};
8use crate::parser::array::array_value;
9use crate::parser::class::class_definition;
10use crate::parser::function::function_definition;
11use crate::parser::identifier::{identifier, method_identifier};
12use crate::parser::operator::{binary_operator, postfix_operator, prefix_operator};
13use crate::parser::parse_result_ext::ParseResultExt;
14use crate::parser::table::table_slot;
15use crate::parser::token_list::TokenList;
16use crate::parser::token_list_ext::TokenListExt;
17use crate::parser::type_::type_;
18use crate::parser::ParseResult;
19use crate::token::{TerminalToken, TokenType};
20use crate::{ContextType, ParseErrorType};
21
22pub fn expression(tokens: TokenList, precedence: Precedence) -> ParseResult<Box<Expression>> {
23 let (mut next_tokens, mut value) = value(tokens)?;
24
25 loop {
26 let mut value_container = Some(value);
27 match operator(next_tokens, precedence, ExpressionRef(&mut value_container))
28 .with_context_from(ContextType::Expression, tokens)
29 .maybe(next_tokens)?
30 {
31 (new_tokens, Some(new_value)) => {
32 next_tokens = new_tokens;
33 value = new_value;
34 }
35 (new_tokens, None) => return Ok((new_tokens, value_container.unwrap())),
36 }
37 }
38}
39
40fn value(tokens: TokenList) -> ParseResult<Box<Expression>> {
41 function(tokens)
42 .map_val(Expression::Function)
43 .or_try(|| parens(tokens).map_val(Expression::Parens))
44 .or_try(|| literal(tokens).map_val(Expression::Literal))
45 .or_try(|| var(tokens).map_val(Expression::Var))
46 .or_try(|| root_var(tokens).map_val(Expression::RootVar))
47 .or_try(|| table(tokens).map_val(Expression::Table))
48 .or_try(|| class(tokens).map_val(Expression::Class))
49 .or_try(|| array(tokens).map_val(Expression::Array))
50 .or_try(|| vector(tokens).map_val(Expression::Vector))
51 .or_try(|| prefix(tokens).map_val(Expression::Prefix))
52 .or_try(|| delegate(tokens).map_val(Expression::Delegate))
53 .or_try(|| expect(tokens).map_val(Expression::Expect))
54 .or_error(|| tokens.error(ParseErrorType::ExpectedValue))
55 .map_val(Box::new)
56}
57
58pub fn function(tokens: TokenList) -> ParseResult<FunctionExpression> {
59 type_(tokens)
60 .not_line_ending()
61 .maybe(tokens)
62 .and_then(|(tokens, return_type)| {
63 tokens
64 .terminal(TerminalToken::Function)
65 .map_val(|function| (return_type, function))
66 })
67 .determines(|tokens, (return_type, function)| {
68 function_definition(tokens).map_val(|definition| FunctionExpression {
69 return_type,
70 function,
71 definition,
72 })
73 })
74 .with_context_from(ContextType::FunctionLiteral, tokens)
75}
76
77pub fn parens(tokens: TokenList) -> ParseResult<ParensExpression> {
78 tokens
79 .terminal(TerminalToken::OpenBracket)
80 .determines_and_opens(
81 ContextType::Expression,
82 |tokens| tokens.terminal(TerminalToken::CloseBracket),
83 |tokens, open, close| {
84 expression(tokens, Precedence::None).map_val(|value| ParensExpression {
85 open,
86 value,
87 close,
88 })
89 },
90 )
91}
92
93pub fn literal(tokens: TokenList) -> ParseResult<LiteralExpression> {
94 if let Some((tokens, item)) = tokens.split_first() {
95 if let TokenType::Literal(literal) = item.token.ty {
96 return Ok((
97 tokens,
98 LiteralExpression {
99 literal,
100 token: &item.token,
101 },
102 ));
103 }
104 }
105
106 Err(tokens.error(ParseErrorType::ExpectedLiteral))
107}
108
109pub fn var(tokens: TokenList) -> ParseResult<VarExpression> {
110 identifier(tokens).map_val(|name| VarExpression { name })
111}
112
113pub fn root_var(tokens: TokenList) -> ParseResult<RootVarExpression> {
114 tokens
115 .terminal(TerminalToken::Namespace)
116 .determines(|tokens, root| {
117 identifier(tokens).map_val(|name| RootVarExpression { root, name })
118 })
119}
120
121pub fn table(tokens: TokenList) -> ParseResult<TableExpression> {
122 table_delimited(tokens, TerminalToken::OpenBrace, TerminalToken::CloseBrace)
123}
124
125pub fn table_delimited(
126 tokens: TokenList,
127 open_terminal: TerminalToken,
128 close_terminal: TerminalToken,
129) -> ParseResult<TableExpression> {
130 tokens.terminal(open_terminal).determines_and_opens(
131 ContextType::TableLiteral,
132 |tokens| tokens.terminal(close_terminal),
133 |tokens, open, close| {
134 let (tokens, slots) = tokens.many_until(
135 |tokens| tokens.is_ended() || tokens.terminal(TerminalToken::Ellipsis).is_ok(),
136 table_slot,
137 )?;
138 let (tokens, spread) = tokens.terminal(TerminalToken::Ellipsis).maybe(tokens)?;
139 Ok((
140 tokens,
141 TableExpression {
142 open,
143 slots,
144 spread,
145 close,
146 },
147 ))
148 },
149 )
150}
151
152pub fn class(tokens: TokenList) -> ParseResult<ClassExpression> {
153 tokens
154 .terminal(TerminalToken::Class)
155 .determines(|tokens, class| {
156 class_definition(tokens).map_val(|definition| ClassExpression { class, definition })
157 })
158 .with_context_from(ContextType::ClassLiteral, tokens)
159}
160
161pub fn array(tokens: TokenList) -> ParseResult<ArrayExpression> {
162 tokens
163 .terminal(TerminalToken::OpenSquare)
164 .determines_and_opens(
165 ContextType::ArrayLiteral,
166 |tokens| tokens.terminal(TerminalToken::CloseSquare),
167 |tokens, open, close| {
168 let (tokens, values) = tokens.many_until(
169 |tokens| tokens.is_ended() || tokens.terminal(TerminalToken::Ellipsis).is_ok(),
170 array_value,
171 )?;
172 let (tokens, spread) = tokens.terminal(TerminalToken::Ellipsis).maybe(tokens)?;
173 Ok((
174 tokens,
175 ArrayExpression {
176 open,
177 values,
178 spread,
179 close,
180 },
181 ))
182 },
183 )
184}
185
186pub fn vector(tokens: TokenList) -> ParseResult<VectorExpression> {
187 tokens
188 .terminal(TerminalToken::Less)
189 .determines(|tokens, open| {
190 let (tokens, x) = expression(tokens, Precedence::Comma)?;
191 let (tokens, comma_1) = tokens.terminal(TerminalToken::Comma)?;
192 let (tokens, y) = expression(tokens, Precedence::Comma)?;
193 let (tokens, comma_2) = tokens.terminal(TerminalToken::Comma)?;
194 let (tokens, z) = expression(tokens, Precedence::Bitshift)?;
195 let (tokens, close) = tokens.terminal(TerminalToken::Greater)?;
196 Ok((
197 tokens,
198 VectorExpression {
199 open,
200 x,
201 comma_1,
202 y,
203 comma_2,
204 z,
205 close,
206 },
207 ))
208 })
209 .with_context_from(ContextType::VectorLiteral, tokens)
210}
211
212pub fn prefix(tokens: TokenList) -> ParseResult<PrefixExpression> {
213 prefix_operator(tokens).determines(|tokens, operator| {
214 expression(tokens, Precedence::Prefix).map_val(|value| PrefixExpression { operator, value })
215 })
216}
217
218pub fn delegate(tokens: TokenList) -> ParseResult<DelegateExpression> {
219 tokens
220 .terminal(TerminalToken::Delegate)
221 .determines(|tokens, delegate| {
222 let (tokens, parent) = expression(tokens, Precedence::None)?;
223 let (tokens, colon) = tokens.terminal(TerminalToken::Colon)?;
224 let (tokens, value) = expression(tokens, Precedence::Comma)?;
225 Ok((
226 tokens,
227 DelegateExpression {
228 delegate,
229 parent,
230 colon,
231 value,
232 },
233 ))
234 })
235}
236
237pub fn expect(tokens: TokenList) -> ParseResult<ExpectExpression> {
238 tokens
239 .terminal(TerminalToken::Expect)
240 .determines(|tokens, expect| {
241 let (tokens, ty) = type_(tokens)?;
242 tokens.terminal(TerminalToken::OpenBracket).opens(
243 ContextType::Expression,
244 |tokens| tokens.terminal(TerminalToken::CloseBracket),
245 |tokens, open, close| {
246 let (tokens, value) = expression(tokens, Precedence::None)?;
247 Ok((
248 tokens,
249 ExpectExpression {
250 expect,
251 ty,
252 open,
253 value,
254 close,
255 },
256 ))
257 },
258 )
259 })
260}
261
262struct ExpressionRef<'a, 's>(&'a mut Option<Box<Expression<'s>>>);
263impl<'a, 's> ExpressionRef<'a, 's> {
264 fn take(self) -> Box<Expression<'s>> {
265 self.0.take().unwrap()
266 }
267}
268
269fn operator<'s>(
270 tokens: TokenList<'s>,
271 precedence: Precedence,
272 left: ExpressionRef<'_, 's>,
273) -> ParseResult<'s, Box<Expression<'s>>> {
274 let left_ref = left.0;
275
276 property(tokens, precedence, ExpressionRef(left_ref))
277 .map_val(Expression::Property)
278 .or_try(|| {
279 ternary(tokens, precedence, ExpressionRef(left_ref)).map_val(Expression::Ternary)
280 })
281 .or_try(|| binary(tokens, precedence, ExpressionRef(left_ref)).map_val(Expression::Binary))
282 .or_try(|| index(tokens, precedence, ExpressionRef(left_ref)).map_val(Expression::Index))
283 .or_try(|| {
284 postfix(tokens, precedence, ExpressionRef(left_ref)).map_val(Expression::Postfix)
285 })
286 .or_try(|| call(tokens, precedence, ExpressionRef(left_ref)).map_val(Expression::Call))
287 .or_try(|| comma(tokens, precedence, ExpressionRef(left_ref)).map_val(Expression::Comma))
288 .or_error(|| tokens.error(ParseErrorType::ExpectedOperator))
289 .map_val(Box::new)
290}
291
292fn property<'s>(
293 tokens: TokenList<'s>,
294 precedence: Precedence,
295 left: ExpressionRef<'_, 's>,
296) -> ParseResult<'s, PropertyExpression<'s>> {
297 if precedence >= Precedence::Property {
299 return Err(tokens.error(ParseErrorType::Precedence));
300 }
301
302 tokens
303 .terminal(TerminalToken::Dot)
304 .determines(|tokens, dot| {
305 method_identifier(tokens).map_val(|property| PropertyExpression {
306 base: left.take(),
307 dot,
308 property,
309 })
310 })
311}
312
313fn ternary<'s>(
314 tokens: TokenList<'s>,
315 precedence: Precedence,
316 left: ExpressionRef<'_, 's>,
317) -> ParseResult<'s, TernaryExpression<'s>> {
318 if precedence > Precedence::Ternary {
320 return Err(tokens.error(ParseErrorType::Precedence));
321 }
322
323 tokens
324 .terminal(TerminalToken::Question)
325 .determines(|tokens, question| {
326 let (tokens, true_value) = expression(tokens, Precedence::None)?;
327 let (tokens, separator) = tokens.terminal(TerminalToken::Colon)?;
328 let (tokens, false_value) = expression(tokens, Precedence::Ternary)?;
329
330 Ok((
331 tokens,
332 TernaryExpression {
333 condition: left.take(),
334 question,
335 true_value,
336 separator,
337 false_value,
338 },
339 ))
340 })
341}
342
343fn binary<'s>(
344 tokens: TokenList<'s>,
345 precedence: Precedence,
346 left: ExpressionRef<'_, 's>,
347) -> ParseResult<'s, BinaryExpression<'s>> {
348 binary_operator(tokens)
349 .and_then(|(tokens, operator)| {
350 if precedence >= operator.precedence() {
352 Err(tokens.error(ParseErrorType::Precedence))
353 } else {
354 Ok((tokens, operator))
355 }
356 })
357 .determines(|tokens, operator| {
358 expression(tokens, operator.precedence()).map_val(|right| BinaryExpression {
359 left: left.take(),
360 operator,
361 right,
362 })
363 })
364}
365
366fn index<'s>(
367 tokens: TokenList<'s>,
368 precedence: Precedence,
369 left: ExpressionRef<'_, 's>,
370) -> ParseResult<'s, IndexExpression<'s>> {
371 if precedence >= Precedence::Postfix {
373 return Err(tokens.error(ParseErrorType::Precedence));
374 }
375
376 tokens
377 .terminal(TerminalToken::OpenSquare)
378 .determines_and_opens(
379 ContextType::Expression,
380 |tokens| tokens.terminal(TerminalToken::CloseSquare),
381 |tokens, open, close| {
382 expression(tokens, Precedence::None).map_val(|index| IndexExpression {
383 base: left.take(),
384 open,
385 index,
386 close,
387 })
388 },
389 )
390}
391
392fn postfix<'s>(
393 tokens: TokenList<'s>,
394 precedence: Precedence,
395 left: ExpressionRef<'_, 's>,
396) -> ParseResult<'s, PostfixExpression<'s>> {
397 if precedence >= Precedence::Postfix {
399 return Err(tokens.error(ParseErrorType::Precedence));
400 }
401
402 if tokens.is_newline() {
412 return Err(tokens.error(ParseErrorType::IllegalLineBreak));
413 }
414
415 postfix_operator(tokens)
416 .not_definite()
417 .map_val(|operator| PostfixExpression {
418 value: left.take(),
419 operator,
420 })
421}
422
423fn call<'s>(
424 tokens: TokenList<'s>,
425 precedence: Precedence,
426 left: ExpressionRef<'_, 's>,
427) -> ParseResult<'s, CallExpression<'s>> {
428 if precedence >= Precedence::Postfix {
430 return Err(tokens.error(ParseErrorType::Precedence));
431 }
432
433 tokens
434 .terminal(TerminalToken::OpenBracket)
435 .determines_and_opens(
436 ContextType::CallArgumentList,
437 |tokens| tokens.terminal(TerminalToken::CloseBracket),
438 |tokens, open, close| {
439 tokens
440 .separated_list_trailing0(
441 |tokens| {
442 let res = expression(tokens, Precedence::Comma).map_val(|expr| *expr);
443 if tokens.is_ended() {
444 res
445 } else {
446 res.definite()
447 }
448 },
449 |tokens| tokens.terminal(TerminalToken::Comma),
450 )
451 .map_val(|args| (open, args, close))
452 },
453 )
454 .and_then(|(tokens, (open, arguments, close))| {
455 let (tokens, post_initializer) = if tokens.is_newline() {
457 (tokens, None)
458 } else {
459 table(tokens).maybe(tokens)?
460 };
461
462 Ok((
463 tokens,
464 CallExpression {
465 function: left.take(),
466 open,
467 arguments,
468 close,
469 post_initializer,
470 },
471 ))
472 })
473}
474
475fn comma<'s>(
476 tokens: TokenList<'s>,
477 precedence: Precedence,
478 left: ExpressionRef<'_, 's>,
479) -> ParseResult<'s, CommaExpression<'s>> {
480 if precedence >= Precedence::Comma {
482 return Err(tokens.error(ParseErrorType::Precedence));
483 }
484
485 tokens
486 .terminal(TerminalToken::Comma)
487 .determines(|tokens, first_comma| {
488 let (tokens, mut values) = tokens.separated_list1(
489 |tokens| expression(tokens, Precedence::Comma).map_val(|expr| *expr),
490 |tokens| tokens.terminal(TerminalToken::Comma),
491 )?;
492 values.items.insert(0, (*left.take(), first_comma));
493 Ok((tokens, CommaExpression { values }))
494 })
495}