1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! What follows a primary: calls, trailing lambdas, indexing, members,
//! type arguments, `!`.
use super::expr::POSTFIXES;
use super::{PResult, Parser};
use crate::ast::{Arg, Expr, ExprKind};
use crate::source::token::{Punct, Tok};
impl Parser<'_, '_, '_> {
pub(crate) fn postfix(&mut self, mut expr: Expr) -> PResult<Expr> {
loop {
expr = match self.tok() {
Tok::Punct(Punct::LParen) => self.call(expr)?,
Tok::Punct(Punct::LBrace) if !self.no_brace => self.trailing_lambda(expr)?,
Tok::Punct(Punct::LBracket) => self.index(expr, false)?,
// `a?[i]`: `?` then `[` (not a conditional's `?`).
Tok::Punct(Punct::Question) if self.nth_is(1, Punct::LBracket) => {
self.bump();
self.index(expr, true)?
}
Tok::Punct(Punct::Bang) => {
let span = expr.span.to(self.bump().span);
Expr {
kind: ExprKind::NotNull(Box::new(expr)),
span,
}
}
Tok::Punct(p @ (Punct::Dot | Punct::SafeDot)) => {
let safe = *p == Punct::SafeDot;
self.bump();
let name = self.any_name("a member")?;
let span = expr.span.to(name.span);
Expr {
kind: ExprKind::Member {
expr: Box::new(expr),
name,
safe,
},
span,
}
}
Tok::Punct(Punct::Lt) if self.type_args_ahead().is_some() => {
let args = self.type_args()?;
let span = expr.span.to(self.prev());
Expr {
kind: ExprKind::TypeArgs {
expr: Box::new(expr),
args,
},
span,
}
}
Tok::Punct(p) if let Some(&(_, op)) = POSTFIXES.iter().find(|(s, _)| s == p) => {
let span = expr.span.to(self.bump().span);
Expr {
kind: ExprKind::Unary {
op,
expr: Box::new(expr),
},
span,
}
}
_ => return Ok(expr),
};
}
}
fn call(&mut self, callee: Expr) -> PResult<Expr> {
let args = self.args()?;
let span = callee.span.to(self.prev());
Ok(Expr {
kind: ExprKind::Call {
callee: Box::new(callee),
args,
},
span,
})
}
/// `f { … }` / `f(a) { … }`: the lambda is the last argument.
fn trailing_lambda(&mut self, callee: Expr) -> PResult<Expr> {
let lambda = self.block_lambda()?;
let span = callee.span.to(lambda.span);
let arg = Arg {
name: None,
pass: None,
value: lambda,
};
let kind = match callee.kind {
ExprKind::Call { callee, mut args } => {
args.push(arg);
ExprKind::Call { callee, args }
}
other => {
let callee = Expr {
kind: other,
span: callee.span,
};
ExprKind::Call {
callee: Box::new(callee),
args: vec![arg],
}
}
};
Ok(Expr { kind, span })
}
/// `a[i]`, `grid[x, y]`.
fn index(&mut self, expr: Expr, safe: bool) -> PResult<Expr> {
self.bump();
let args = self.braces(|p| p.list(Punct::RBracket, Self::expr))?;
let span = expr.span.to(self.prev());
Ok(Expr {
kind: ExprKind::Index {
expr: Box::new(expr),
args,
safe,
},
span,
})
}
}