2023-12-27 18:45:58 -08:00
|
|
|
//! Routines the parser and pretty-printer use to classify AST nodes.
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2023-12-18 02:11:55 +00:00
|
|
|
use crate::{ast, token::Delimiter};
|
2012-04-17 22:02:00 -07:00
|
|
|
|
2023-12-27 18:45:58 -08:00
|
|
|
/// Does this expression require a semicolon to be treated as a statement?
|
|
|
|
|
///
|
|
|
|
|
/// The negation of this: "can this expression be used as a statement without a
|
|
|
|
|
/// semicolon" -- is used as an early bail-out in the parser so that, for
|
|
|
|
|
/// instance,
|
|
|
|
|
///
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// if true {...} else {...}
|
|
|
|
|
/// |x| 5
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// isn't parsed as `(if true {...} else {...} | x) | 5`.
|
|
|
|
|
///
|
|
|
|
|
/// Nearly the same early bail-out also occurs in the right-hand side of match
|
|
|
|
|
/// arms:
|
|
|
|
|
///
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// match i {
|
|
|
|
|
/// 0 => if true {...} else {...}
|
|
|
|
|
/// | x => {}
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Here the `|` is a leading vert in a second match arm. It is not a binary
|
|
|
|
|
/// operator with the If as its left operand. If the first arm were some other
|
|
|
|
|
/// expression for which `expr_requires_semi_to_be_stmt` returns true, then the
|
|
|
|
|
/// `|` on the next line would be a binary operator (leading to a parse error).
|
|
|
|
|
///
|
|
|
|
|
/// The statement case and the match-arm case are "nearly" the same early
|
|
|
|
|
/// bail-out because of 1 edge case. Macro calls with brace delimiter terminate
|
|
|
|
|
/// a statement without a semicolon, but do not terminate a match-arm without
|
|
|
|
|
/// comma.
|
|
|
|
|
///
|
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// m! {} - 1; // two statements: a macro call followed by -1 literal
|
|
|
|
|
///
|
|
|
|
|
/// match () {
|
|
|
|
|
/// _ => m! {} - 1, // binary subtraction operator
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2014-09-13 19:06:01 +03:00
|
|
|
pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
2020-12-24 02:55:21 +01:00
|
|
|
!matches!(
|
|
|
|
|
e.kind,
|
2019-12-22 17:42:04 -05:00
|
|
|
ast::ExprKind::If(..)
|
2020-12-24 02:55:21 +01:00
|
|
|
| ast::ExprKind::Match(..)
|
|
|
|
|
| ast::ExprKind::Block(..)
|
|
|
|
|
| ast::ExprKind::While(..)
|
|
|
|
|
| ast::ExprKind::Loop(..)
|
2023-12-08 14:51:50 -08:00
|
|
|
| ast::ExprKind::ForLoop { .. }
|
2020-12-24 02:55:21 +01:00
|
|
|
| ast::ExprKind::TryBlock(..)
|
2022-12-01 17:54:50 +00:00
|
|
|
| ast::ExprKind::ConstBlock(..)
|
2020-12-24 02:55:21 +01:00
|
|
|
)
|
2012-04-17 22:02:00 -07:00
|
|
|
}
|
2021-07-30 17:12:11 -05:00
|
|
|
|
|
|
|
|
/// If an expression ends with `}`, returns the innermost expression ending in the `}`
|
|
|
|
|
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
|
|
|
|
use ast::ExprKind::*;
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
match &expr.kind {
|
|
|
|
|
AddrOf(_, _, e)
|
|
|
|
|
| Assign(_, e, _)
|
|
|
|
|
| AssignOp(_, _, e)
|
|
|
|
|
| Binary(_, _, e)
|
|
|
|
|
| Break(_, Some(e))
|
2023-09-08 10:14:36 +00:00
|
|
|
| Let(_, e, _, _)
|
2021-07-30 17:12:11 -05:00
|
|
|
| Range(_, Some(e), _)
|
|
|
|
|
| Ret(Some(e))
|
|
|
|
|
| Unary(_, e)
|
2023-12-12 15:20:29 +00:00
|
|
|
| Yield(Some(e))
|
|
|
|
|
| Yeet(Some(e))
|
|
|
|
|
| Become(e) => {
|
2021-07-30 17:12:11 -05:00
|
|
|
expr = e;
|
|
|
|
|
}
|
2022-09-08 10:52:51 +10:00
|
|
|
Closure(closure) => {
|
|
|
|
|
expr = &closure.body;
|
|
|
|
|
}
|
2023-12-08 14:51:50 -08:00
|
|
|
Gen(..)
|
|
|
|
|
| Block(..)
|
|
|
|
|
| ForLoop { .. }
|
|
|
|
|
| If(..)
|
|
|
|
|
| Loop(..)
|
|
|
|
|
| Match(..)
|
|
|
|
|
| Struct(..)
|
|
|
|
|
| TryBlock(..)
|
|
|
|
|
| While(..)
|
|
|
|
|
| ConstBlock(_) => break Some(expr),
|
2023-12-12 15:20:29 +00:00
|
|
|
|
2023-12-18 02:11:55 +00:00
|
|
|
MacCall(mac) => {
|
|
|
|
|
break (mac.args.delim == Delimiter::Brace).then_some(expr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
|
|
|
|
|
// These should have been denied pre-expansion.
|
2023-12-12 15:20:29 +00:00
|
|
|
break None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Break(_, None)
|
|
|
|
|
| Range(_, None, _)
|
|
|
|
|
| Ret(None)
|
|
|
|
|
| Yield(None)
|
|
|
|
|
| Array(_)
|
|
|
|
|
| Call(_, _)
|
|
|
|
|
| MethodCall(_)
|
|
|
|
|
| Tup(_)
|
|
|
|
|
| Lit(_)
|
|
|
|
|
| Cast(_, _)
|
|
|
|
|
| Type(_, _)
|
|
|
|
|
| Await(_, _)
|
|
|
|
|
| Field(_, _)
|
|
|
|
|
| Index(_, _, _)
|
|
|
|
|
| Underscore
|
|
|
|
|
| Path(_, _)
|
|
|
|
|
| Continue(_)
|
|
|
|
|
| Repeat(_, _)
|
|
|
|
|
| Paren(_)
|
|
|
|
|
| Try(_)
|
|
|
|
|
| Yeet(None)
|
2024-02-25 22:22:11 +01:00
|
|
|
| Err(_)
|
2024-02-25 22:22:09 +01:00
|
|
|
| Dummy => break None,
|
2021-07-30 17:12:11 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|