1use core::mem::take;
2use core::ops;
3
4use crate::ast::prelude::*;
5
6#[test]
7#[cfg(not(miri))]
8fn ast_parse() {
9 rt::<ast::Expr>("()");
10 rt::<ast::Expr>("foo[\"foo\"]");
11 rt::<ast::Expr>("foo[\"bar\"]");
12 rt::<ast::Expr>("foo.bar()");
13 rt::<ast::Expr>("var()");
14 rt::<ast::Expr>("var");
15 rt::<ast::Expr>("42");
16 rt::<ast::Expr>("1 + 2 / 3 - 4 * 1");
17 rt::<ast::Expr>("let var = 42");
18 rt::<ast::Expr>("let var = \"foo bar\"");
19 rt::<ast::Expr>("var[\"foo\"] = \"bar\"");
20 rt::<ast::Expr>("let var = objects[\"foo\"] + 1");
21 rt::<ast::Expr>("var = 42");
22
23 let expr = rt::<ast::Expr>(
24 r#"
25 if 1 { } else { if 2 { } else { } }
26 "#,
27 );
28 assert!(matches!(expr, ast::Expr::If(..)));
29
30 rt::<ast::Expr>("foo.bar.baz()");
32 rt::<ast::Expr>("foo[0][1][2]");
33 rt::<ast::Expr>("foo.bar()[0].baz()[1]");
34
35 rt::<ast::Expr>("42 is i64::i64");
36 rt::<ast::Expr>("{ let x = 1; x }");
37
38 let expr = rt::<ast::Expr>("#[cfg(debug_assertions)] { assert_eq(x, 32); }");
39 assert!(
40 matches!(expr, ast::Expr::Block(b) if b.attributes.len() == 1 && b.block.statements.len() == 1)
41 );
42
43 rt::<ast::Expr>("#{\"foo\": b\"bar\"}");
44 rt::<ast::Expr>("Disco {\"never_died\": true }");
45 rt::<ast::Expr>("(false, 1, 'n')");
46 rt::<ast::Expr>("[false, 1, 'b']");
47
48 let expr = rt::<ast::Expr>(r#"if true {} else {}"#);
49 assert!(matches!(expr, ast::Expr::If(..)));
50
51 let expr = rt::<ast::Expr>("if 1 { } else { if 2 { } else { } }");
52 assert!(matches!(expr, ast::Expr::If(..)));
53
54 let expr = rt::<ast::Expr>(r#"while true {}"#);
55 assert!(matches!(expr, ast::Expr::While(..)));
56
57 rt::<ast::Expr>("format!(\"{}\", a).bar()");
58}
59
60#[derive(Debug, Clone, Copy)]
62pub(crate) struct EagerBrace(bool);
63
64pub(crate) const EAGER_BRACE: EagerBrace = EagerBrace(true);
66
67pub(crate) const NOT_EAGER_BRACE: EagerBrace = EagerBrace(false);
70
71impl ops::Deref for EagerBrace {
72 type Target = bool;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79#[derive(Debug, Clone, Copy)]
81pub(crate) struct EagerBinary(bool);
82
83pub(crate) const EAGER_BINARY: EagerBinary = EagerBinary(true);
85
86pub(crate) const NOT_EAGER_BINARY: EagerBinary = EagerBinary(false);
88
89impl ops::Deref for EagerBinary {
90 type Target = bool;
91
92 fn deref(&self) -> &Self::Target {
93 &self.0
94 }
95}
96
97#[derive(Debug, Clone, Copy)]
101pub(crate) struct Callable(bool);
102
103pub(crate) const CALLABLE: Callable = Callable(true);
106
107pub(crate) const NOT_CALLABLE: Callable = Callable(false);
112
113impl ops::Deref for Callable {
114 type Target = bool;
115
116 fn deref(&self) -> &Self::Target {
117 &self.0
118 }
119}
120
121#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
123#[non_exhaustive]
124pub enum Expr {
125 Path(ast::Path),
127 Assign(ast::ExprAssign),
129 While(ast::ExprWhile),
131 Loop(ast::ExprLoop),
133 For(ast::ExprFor),
135 Let(ast::ExprLet),
137 If(ast::ExprIf),
139 Match(ast::ExprMatch),
141 Call(ast::ExprCall),
143 FieldAccess(ast::ExprFieldAccess),
145 Binary(ast::ExprBinary),
147 Unary(ast::ExprUnary),
149 Index(ast::ExprIndex),
151 Break(ast::ExprBreak),
153 Continue(ast::ExprContinue),
155 Yield(ast::ExprYield),
157 Block(ast::ExprBlock),
159 Return(ast::ExprReturn),
161 Await(ast::ExprAwait),
163 Try(ast::ExprTry),
165 Select(ast::ExprSelect),
167 Closure(ast::ExprClosure),
169 Lit(ast::ExprLit),
171 Object(ast::ExprObject),
173 Tuple(ast::ExprTuple),
175 Vec(ast::ExprVec),
177 Range(ast::ExprRange),
179 Empty(ast::ExprEmpty),
181 Group(ast::ExprGroup),
183 MacroCall(ast::MacroCall),
185}
186
187impl Expr {
188 pub(crate) fn is_callable(&self, callable: bool) -> bool {
191 match self {
192 Self::While(_) => false,
193 Self::Loop(_) => callable,
194 Self::For(_) => false,
195 Self::If(_) => callable,
196 Self::Match(_) => callable,
197 Self::Select(_) => callable,
198 Self::Block(_) => callable,
199 _ => true,
200 }
201 }
202
203 pub(crate) fn take_attributes(&mut self) -> Vec<ast::Attribute> {
205 match self {
206 Self::Path(_) => Vec::new(),
207 Self::Break(expr) => take(&mut expr.attributes),
208 Self::Continue(expr) => take(&mut expr.attributes),
209 Self::Yield(expr) => take(&mut expr.attributes),
210 Self::Block(expr) => take(&mut expr.attributes),
211 Self::Return(expr) => take(&mut expr.attributes),
212 Self::Closure(expr) => take(&mut expr.attributes),
213 Self::Match(expr) => take(&mut expr.attributes),
214 Self::While(expr) => take(&mut expr.attributes),
215 Self::Loop(expr) => take(&mut expr.attributes),
216 Self::For(expr) => take(&mut expr.attributes),
217 Self::Let(expr) => take(&mut expr.attributes),
218 Self::If(expr) => take(&mut expr.attributes),
219 Self::Select(expr) => take(&mut expr.attributes),
220 Self::Lit(expr) => take(&mut expr.attributes),
221 Self::Assign(expr) => take(&mut expr.attributes),
222 Self::Binary(expr) => take(&mut expr.attributes),
223 Self::Call(expr) => take(&mut expr.attributes),
224 Self::FieldAccess(expr) => take(&mut expr.attributes),
225 Self::Group(expr) => take(&mut expr.attributes),
226 Self::Empty(expr) => take(&mut expr.attributes),
227 Self::Unary(expr) => take(&mut expr.attributes),
228 Self::Index(expr) => take(&mut expr.attributes),
229 Self::Await(expr) => take(&mut expr.attributes),
230 Self::Try(expr) => take(&mut expr.attributes),
231 Self::Object(expr) => take(&mut expr.attributes),
232 Self::Range(expr) => take(&mut expr.attributes),
233 Self::Vec(expr) => take(&mut expr.attributes),
234 Self::Tuple(expr) => take(&mut expr.attributes),
235 Self::MacroCall(expr) => take(&mut expr.attributes),
236 }
237 }
238
239 pub(crate) fn is_lit(&self) -> bool {
245 match self {
246 Self::Lit(..) => return true,
247 Self::Unary(ast::ExprUnary {
248 op: ast::UnOp::Neg(..),
249 expr,
250 ..
251 }) => {
252 return matches!(
253 &**expr,
254 Self::Lit(ast::ExprLit {
255 lit: ast::Lit::Number(..),
256 ..
257 })
258 );
259 }
260 _ => (),
261 }
262
263 false
264 }
265
266 pub(crate) fn from_lit(lit: ast::Lit) -> Self {
268 Self::Lit(ast::ExprLit {
269 attributes: Vec::new(),
270 lit,
271 })
272 }
273
274 pub(crate) fn parse_without_eager_brace(p: &mut Parser<'_>) -> Result<Self> {
280 Self::parse_with(p, NOT_EAGER_BRACE, EAGER_BINARY, CALLABLE)
281 }
282
283 pub(crate) fn parse_with_meta(
289 p: &mut Parser<'_>,
290 attributes: &mut Vec<ast::Attribute>,
291 callable: Callable,
292 ) -> Result<Self> {
293 p.nested(|p| {
294 let lhs = primary(p, attributes, EAGER_BRACE, callable)?;
295 let lookahead = ast::BinOp::from_peeker(p.peeker());
296 binary(p, lhs, lookahead, 0, EAGER_BRACE)
297 })
298 }
299
300 pub(crate) fn parse_with(
302 p: &mut Parser<'_>,
303 eager_brace: EagerBrace,
304 eager_binary: EagerBinary,
305 callable: Callable,
306 ) -> Result<Self> {
307 p.nested(|p| {
308 let mut attributes = p.parse()?;
309
310 let expr = primary(p, &mut attributes, eager_brace, callable)?;
311
312 let expr = if *eager_binary {
313 let lookeahead = ast::BinOp::from_peeker(p.peeker());
314 binary(p, expr, lookeahead, 0, eager_brace)?
315 } else {
316 expr
317 };
318
319 if let Some(span) = attributes.option_span() {
320 return Err(compile::Error::unsupported(span, "attributes"));
321 }
322
323 Ok(expr)
324 })
325 }
326
327 pub(crate) fn parse_with_meta_path(
329 p: &mut Parser<'_>,
330 attributes: &mut Vec<ast::Attribute>,
331 path: ast::Path,
332 eager_brace: EagerBrace,
333 ) -> Result<Self> {
334 if *eager_brace && p.peek::<T!['{']>()? {
335 let ident = ast::ObjectIdent::Named(path);
336
337 return Ok(Self::Object(ast::ExprObject::parse_with_meta(
338 p,
339 take(attributes),
340 ident,
341 )?));
342 }
343
344 if p.peek::<T![!]>()? {
345 return Ok(Self::MacroCall(ast::MacroCall::parse_with_meta_path(
346 p,
347 take(attributes),
348 path,
349 )?));
350 }
351
352 Ok(Self::Path(path))
353 }
354
355 pub(crate) fn peek_with_brace(p: &mut Peeker<'_>, eager_brace: EagerBrace) -> bool {
356 match p.nth(0) {
357 K![async] => true,
358 K![self] => true,
359 K![select] => true,
360 K![#] => true,
361 K![-] => true,
362 K![!] => true,
363 K![&] => true,
364 K![*] => true,
365 K![while] => true,
366 K![loop] => true,
367 K![for] => true,
368 K![let] => true,
369 K![if] => true,
370 K![break] => true,
371 K![continue] => true,
372 K![return] => true,
373 K![true] => true,
374 K![false] => true,
375 K![ident] => true,
376 K![::] => true,
377 K![number] => true,
378 K![char] => true,
379 K![byte] => true,
380 K![str] => true,
381 K![bytestr] => true,
382 K!['label] => matches!(p.nth(1), K![:]),
383 K![..] => true,
384 K!['('] => true,
385 K!['['] => true,
386 K!['{'] if *eager_brace => true,
387 _ => false,
388 }
389 }
390}
391
392impl Parse for Expr {
393 fn parse(p: &mut Parser<'_>) -> Result<Self> {
394 Self::parse_with(p, EAGER_BRACE, EAGER_BINARY, CALLABLE)
395 }
396}
397
398impl Peek for Expr {
399 fn peek(p: &mut Peeker<'_>) -> bool {
400 Self::peek_with_brace(p, EAGER_BRACE)
401 }
402}
403
404fn primary(
406 p: &mut Parser<'_>,
407 attributes: &mut Vec<ast::Attribute>,
408 eager_brace: EagerBrace,
409 callable: Callable,
410) -> Result<Expr> {
411 let expr = base(p, attributes, eager_brace)?;
412 chain(p, expr, callable)
413}
414
415fn base(
417 p: &mut Parser<'_>,
418 attributes: &mut Vec<ast::Attribute>,
419 eager_brace: EagerBrace,
420) -> Result<Expr> {
421 if let Some(path) = p.parse::<Option<ast::Path>>()? {
422 return Expr::parse_with_meta_path(p, attributes, path, eager_brace);
423 }
424
425 if ast::Lit::peek_in_expr(p.peeker()) {
426 return Ok(Expr::Lit(ast::ExprLit::parse_with_meta(
427 p,
428 take(attributes),
429 )?));
430 }
431
432 let mut label = p.parse::<Option<(ast::Label, T![:])>>()?;
433 let mut async_token = p.parse::<Option<T![async]>>()?;
434 let mut const_token = p.parse::<Option<T![const]>>()?;
435 let mut move_token = p.parse::<Option<T![move]>>()?;
436
437 let expr = match p.nth(0)? {
438 K![..] => {
439 let limits = ast::ExprRangeLimits::HalfOpen(p.parse()?);
440 range(p, take(attributes), None, limits, eager_brace)?
441 }
442 K![..=] => {
443 let limits = ast::ExprRangeLimits::Closed(p.parse()?);
444 range(p, take(attributes), None, limits, eager_brace)?
445 }
446 K![#] => {
447 let ident = ast::ObjectIdent::Anonymous(p.parse()?);
448
449 Expr::Object(ast::ExprObject::parse_with_meta(
450 p,
451 take(attributes),
452 ident,
453 )?)
454 }
455 K![||] | K![|] => Expr::Closure(ast::ExprClosure::parse_with_meta(
456 p,
457 take(attributes),
458 take(&mut async_token),
459 take(&mut move_token),
460 )?),
461 K![select] => Expr::Select(ast::ExprSelect::parse_with_attributes(p, take(attributes))?),
462 K![!] | K![-] | K![&] | K![*] => Expr::Unary(ast::ExprUnary::parse_with_meta(
463 p,
464 take(attributes),
465 eager_brace,
466 )?),
467 K![while] => Expr::While(ast::ExprWhile::parse_with_meta(
468 p,
469 take(attributes),
470 take(&mut label),
471 )?),
472 K![loop] => Expr::Loop(ast::ExprLoop::parse_with_meta(
473 p,
474 take(attributes),
475 take(&mut label),
476 )?),
477 K![for] => Expr::For(ast::ExprFor::parse_with_meta(
478 p,
479 take(attributes),
480 take(&mut label),
481 )?),
482 K![let] => Expr::Let(ast::ExprLet::parse_with_meta(p, take(attributes))?),
483 K![if] => Expr::If(ast::ExprIf::parse_with_meta(p, take(attributes))?),
484 K![match] => Expr::Match(ast::ExprMatch::parse_with_attributes(p, take(attributes))?),
485 K!['['] => Expr::Vec(ast::ExprVec::parse_with_meta(p, take(attributes))?),
486 ast::Kind::Open(ast::Delimiter::Empty) => empty_group(p, take(attributes))?,
487 K!['('] => paren_group(p, take(attributes))?,
488 K!['{'] => Expr::Block(ast::ExprBlock {
489 attributes: take(attributes),
490 async_token: take(&mut async_token),
491 const_token: take(&mut const_token),
492 move_token: take(&mut move_token),
493 label: take(&mut label),
494 block: p.parse()?,
495 }),
496 K![break] => Expr::Break(ast::ExprBreak::parse_with_meta(p, take(attributes))?),
497 K![continue] => Expr::Continue(ast::ExprContinue::parse_with_meta(p, take(attributes))?),
498 K![yield] => Expr::Yield(ast::ExprYield::parse_with_meta(p, take(attributes))?),
499 K![return] => Expr::Return(ast::ExprReturn::parse_with_meta(p, take(attributes))?),
500 _ => {
501 return Err(compile::Error::expected(
502 p.tok_at(0)?,
503 Expectation::Expression,
504 ));
505 }
506 };
507
508 if let Some(span) = label.option_span() {
509 return Err(compile::Error::unsupported(span, "label"));
510 }
511
512 if let Some(span) = async_token.option_span() {
513 return Err(compile::Error::unsupported(span, "async modifier"));
514 }
515
516 if let Some(span) = const_token.option_span() {
517 return Err(compile::Error::unsupported(span, "const modifier"));
518 }
519
520 if let Some(span) = move_token.option_span() {
521 return Err(compile::Error::unsupported(span, "move modifier"));
522 }
523
524 Ok(expr)
525}
526
527fn chain(p: &mut Parser<'_>, mut expr: Expr, callable: Callable) -> Result<Expr> {
533 while !p.is_eof()? {
534 let is_callable = expr.is_callable(*callable);
535
536 match p.nth(0)? {
537 K!['['] if is_callable => {
538 p.link()?;
539
540 expr = Expr::Index(ast::ExprIndex {
541 attributes: expr.take_attributes(),
542 target: Box::try_new(expr)?,
543 open: p.parse()?,
544 index: p.parse()?,
545 close: p.parse()?,
546 });
547 }
548 K!['('] if is_callable => {
550 p.link()?;
551
552 expr = Expr::Call(ast::ExprCall::parse_with_meta(
553 p,
554 expr.take_attributes(),
555 Box::try_new(expr)?,
556 )?);
557 }
558 K![?] => {
559 p.link()?;
560
561 expr = Expr::Try(ast::ExprTry {
562 attributes: expr.take_attributes(),
563 expr: Box::try_new(expr)?,
564 try_token: p.parse()?,
565 });
566 }
567 K![=] => {
568 p.link()?;
569
570 let eq = p.parse()?;
571 let rhs = Expr::parse_with(p, EAGER_BRACE, EAGER_BINARY, CALLABLE)?;
572
573 expr = Expr::Assign(ast::ExprAssign {
574 attributes: expr.take_attributes(),
575 lhs: Box::try_new(expr)?,
576 eq,
577 rhs: Box::try_new(rhs)?,
578 });
579 }
580 K![.] => {
581 p.link()?;
582
583 match p.nth(1)? {
584 K![await] => {
586 expr = Expr::Await(ast::ExprAwait {
587 attributes: expr.take_attributes(),
588 expr: Box::try_new(expr)?,
589 dot: p.parse()?,
590 await_token: p.parse()?,
591 });
592 }
593 K![ident] => {
595 expr = Expr::FieldAccess(ast::ExprFieldAccess {
596 attributes: expr.take_attributes(),
597 expr: Box::try_new(expr)?,
598 dot: p.parse()?,
599 expr_field: ast::ExprField::Path(p.parse()?),
600 });
601 }
602 K![number] => {
604 expr = Expr::FieldAccess(ast::ExprFieldAccess {
605 attributes: expr.take_attributes(),
606 expr: Box::try_new(expr)?,
607 dot: p.parse()?,
608 expr_field: ast::ExprField::LitNumber(p.parse()?),
609 });
610 }
611 _ => {
612 return Err(compile::Error::new(p.span(0..1), ErrorKind::BadFieldAccess));
613 }
614 }
615 }
616 _ => break,
617 }
618 }
619
620 Ok(expr)
621}
622
623fn binary(
625 p: &mut Parser<'_>,
626 mut lhs: Expr,
627 mut lookahead: Option<ast::BinOp>,
628 min_precedence: usize,
629 eager_brace: EagerBrace,
630) -> Result<Expr> {
631 while let Some(op) = lookahead {
632 let precedence = op.precedence();
633
634 if precedence < min_precedence {
635 break;
636 }
637
638 p.link()?;
641
642 op.advance(p)?;
643
644 match op {
645 ast::BinOp::DotDot(token) => {
646 lhs = range(
647 p,
648 lhs.take_attributes(),
649 Some(Box::try_new(lhs)?),
650 ast::ExprRangeLimits::HalfOpen(token),
651 eager_brace,
652 )?;
653 lookahead = ast::BinOp::from_peeker(p.peeker());
654 continue;
655 }
656 ast::BinOp::DotDotEq(token) => {
657 lhs = range(
658 p,
659 lhs.take_attributes(),
660 Some(Box::try_new(lhs)?),
661 ast::ExprRangeLimits::Closed(token),
662 eager_brace,
663 )?;
664 lookahead = ast::BinOp::from_peeker(p.peeker());
665 continue;
666 }
667 _ => (),
668 }
669
670 let mut rhs = primary(p, &mut Vec::new(), eager_brace, CALLABLE)?;
671 lookahead = ast::BinOp::from_peeker(p.peeker());
672
673 while let Some(next) = lookahead {
674 match (precedence, next.precedence()) {
675 (lh, rh) if lh < rh => {
676 rhs = binary(p, rhs, Some(next), lh + 1, eager_brace)?;
678 lookahead = ast::BinOp::from_peeker(p.peeker());
679 continue;
680 }
681 (lh, rh) if lh == rh && !next.is_assoc() => {
682 return Err(compile::Error::new(
683 lhs.span().join(rhs.span()),
684 ErrorKind::PrecedenceGroupRequired,
685 ));
686 }
687 _ => {}
688 };
689
690 break;
691 }
692
693 lhs = Expr::Binary(ast::ExprBinary {
694 attributes: lhs.take_attributes(),
695 lhs: Box::try_new(lhs)?,
696 op,
697 rhs: Box::try_new(rhs)?,
698 });
699 }
700
701 Ok(lhs)
702}
703
704fn range(
706 p: &mut Parser<'_>,
707 attributes: Vec<ast::Attribute>,
708 from: Option<Box<Expr>>,
709 limits: ast::ExprRangeLimits,
710 eager_brace: EagerBrace,
711) -> Result<Expr> {
712 let to = if Expr::peek_with_brace(p.peeker(), eager_brace) {
713 Some(Box::try_new(Expr::parse_with(
714 p,
715 eager_brace,
716 EAGER_BINARY,
717 CALLABLE,
718 )?)?)
719 } else {
720 None
721 };
722
723 Ok(Expr::Range(ast::ExprRange {
724 attributes,
725 start: from,
726 limits,
727 end: to,
728 }))
729}
730
731fn empty_group(p: &mut Parser<'_>, attributes: Vec<ast::Attribute>) -> Result<Expr> {
733 let open = p.parse::<ast::OpenEmpty>()?;
734 let expr = p.parse::<Expr>()?;
735 let close = p.parse::<ast::CloseEmpty>()?;
736
737 Ok(Expr::Empty(ast::ExprEmpty {
738 attributes,
739 open,
740 expr: Box::try_new(expr)?,
741 close,
742 }))
743}
744
745fn paren_group(p: &mut Parser<'_>, attributes: Vec<ast::Attribute>) -> Result<Expr> {
747 if let (K!['('], K![')']) = (p.nth(0)?, p.nth(1)?) {
749 return Ok(Expr::Tuple(ast::ExprTuple::parse_with_meta(p, attributes)?));
750 }
751
752 let open = p.parse::<T!['(']>()?;
753 let expr = p.parse::<Expr>()?;
754
755 if p.peek::<T![')']>()? {
757 return Ok(Expr::Group(ast::ExprGroup {
758 attributes,
759 open,
760 expr: Box::try_new(expr)?,
761 close: p.parse()?,
762 }));
763 }
764
765 Ok(Expr::Tuple(ast::ExprTuple::parse_from_first_expr(
768 p, attributes, open, expr,
769 )?))
770}