1use crate::{PResult, Parser};
2use smallvec::SmallVec;
3use solar_ast::{token::*, *};
4
5use solar_interface::{Ident, Symbol, kw};
6
7impl<'sess, 'ast, 'cb> Parser<'sess, 'ast, 'cb> {
8 #[inline]
10 pub fn parse_expr(&mut self) -> PResult<'sess, Box<'ast, Expr<'ast>>> {
11 self.with_recursion_limit("expression", |this| this.parse_expr_with(None))
12 }
13
14 #[instrument(name = "parse_expr", level = "trace", skip_all)]
15 pub(super) fn parse_expr_with(
16 &mut self,
17 with: Option<Box<'ast, Expr<'ast>>>,
18 ) -> PResult<'sess, Box<'ast, Expr<'ast>>> {
19 let expr = self.parse_binary_expr(4, with)?;
20 if self.eat(TokenKind::Question) {
21 let then = self.parse_expr()?;
22 self.expect(TokenKind::Colon)?;
23 let else_ = self.parse_expr()?;
24 let span = expr.span.to(self.prev_token.span);
25 Ok(self.alloc(Expr { span, kind: ExprKind::Ternary(expr, then, else_) }))
26 } else {
27 let kind = if let Some(binop_eq) = self.token.as_binop_eq() {
28 Some(binop_eq)
29 } else if self.token.kind == TokenKind::Eq {
30 None
31 } else {
32 return Ok(expr);
33 };
34 self.bump(); let rhs = self.parse_expr()?;
36 let span = expr.span.to(self.prev_token.span);
37 Ok(self.alloc(Expr { span, kind: ExprKind::Assign(expr, kind, rhs) }))
38 }
39 }
40
41 fn parse_binary_expr(
43 &mut self,
44 min_precedence: usize,
45 with: Option<Box<'ast, Expr<'ast>>>,
46 ) -> PResult<'sess, Box<'ast, Expr<'ast>>> {
47 let mut expr = self.parse_unary_expr(with)?;
48 let mut precedence = token_precedence(self.token);
49 while precedence >= min_precedence {
50 while token_precedence(self.token) == precedence {
51 let next_precedence = if self.token.kind == TokenKind::StarStar {
53 precedence
54 } else {
55 precedence + 1
56 };
57
58 let token = self.token;
59 self.bump(); let rhs = self.parse_binary_expr(next_precedence, None)?;
62
63 let span = expr.span.to(self.prev_token.span);
64
65 let kind = if let Some(binop) = token.as_binop() {
66 ExprKind::Binary(expr, binop, rhs)
67 } else if let Some(binop_eq) = token.as_binop_eq() {
68 ExprKind::Assign(expr, Some(binop_eq), rhs)
69 } else if token.kind == TokenKind::Eq {
70 ExprKind::Assign(expr, None, rhs)
71 } else {
72 let msg = format!("unknown binop token: {token:?}");
73 self.dcx().bug(msg).span(span).emit();
74 };
75 expr = self.alloc(Expr { span, kind });
76 }
77 precedence -= 1;
78 }
79 Ok(expr)
80 }
81
82 fn parse_unary_expr(
84 &mut self,
85 with: Option<Box<'ast, Expr<'ast>>>,
86 ) -> PResult<'sess, Box<'ast, Expr<'ast>>> {
87 if with.is_none() && self.eat(TokenKind::BinOp(BinOpToken::Plus)) {
88 self.dcx().emit_err(self.prev_token.span, "unary plus is not supported");
89 }
90
91 let lo = with.as_ref().map(|e| e.span).unwrap_or(self.token.span);
92 let parse_lhs = |this: &mut Self, with| {
93 this.parse_lhs_expr(with, lo).map(|expr| {
94 if let Some(unop) = this.token.as_unop(true) {
95 this.bump(); let span = lo.to(this.prev_token.span);
97 this.alloc(Expr { span, kind: ExprKind::Unary(unop, expr) })
98 } else {
99 expr
100 }
101 })
102 };
103 if let Some(with) = with {
104 parse_lhs(self, Some(with))
105 } else if self.eat_keyword(kw::Delete) {
106 self.parse_unary_expr(None).map(|expr| {
107 let span = lo.to(self.prev_token.span);
108 self.alloc(Expr { span, kind: ExprKind::Delete(expr) })
109 })
110 } else if let Some(unop) = self.token.as_unop(false) {
111 self.bump(); self.parse_unary_expr(None).map(|expr| {
113 let span = lo.to(self.prev_token.span);
114 self.alloc(Expr { span, kind: ExprKind::Unary(unop, expr) })
115 })
116 } else {
117 parse_lhs(self, None)
118 }
119 }
120
121 fn parse_lhs_expr(
123 &mut self,
124 with: Option<Box<'ast, Expr<'ast>>>,
125 lo: Span,
126 ) -> PResult<'sess, Box<'ast, Expr<'ast>>> {
127 let mut expr = if let Some(with) = with {
128 Ok(with)
129 } else if self.eat_keyword(kw::New) {
130 self.parse_type().map(|ty| {
131 let span = lo.to(self.prev_token.span);
132 self.alloc(Expr { span, kind: ExprKind::New(ty) })
133 })
134 } else if self.eat_keyword(kw::Payable) {
135 self.parse_call_args().map(|args| {
136 let span = lo.to(self.prev_token.span);
137 self.alloc(Expr { span, kind: ExprKind::Payable(args) })
138 })
139 } else {
140 self.parse_primary_expr()
141 }?;
142 loop {
143 let kind = if self.eat(TokenKind::Dot) {
144 let dot_span = self.prev_token.span;
145 match self.parse_ident_any() {
147 Ok(member) => ExprKind::Member(expr, member),
148 Err(err) => {
149 err.emit();
150 let member = Ident::new(Symbol::DUMMY, dot_span.shrink_to_hi());
151 ExprKind::Member(expr, member)
152 }
153 }
154 } else if self.check(TokenKind::OpenDelim(Delimiter::Parenthesis)) {
155 let args = self.parse_call_args()?;
157 ExprKind::Call(expr, args)
158 } else if self.check(TokenKind::OpenDelim(Delimiter::Bracket)) {
159 let kind = self.parse_expr_index_kind()?;
160 ExprKind::Index(expr, kind)
161 } else if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
162 if !self.look_ahead(1).is_ident() || self.look_ahead(2).kind != TokenKind::Colon {
164 break;
165 }
166
167 let args = self.parse_named_args(false)?;
169 ExprKind::CallOptions(expr, args)
170 } else {
171 break;
172 };
173 let span = lo.to(self.prev_token.span);
174 expr = self.alloc(Expr { span, kind });
175 }
176 Ok(expr)
177 }
178
179 fn parse_primary_expr(&mut self) -> PResult<'sess, Box<'ast, Expr<'ast>>> {
181 let lo = self.token.span;
182 let kind = if self.check_lit() {
183 let (lit, sub) = self.parse_lit(true)?;
184 ExprKind::Lit(self.alloc(lit), sub)
185 } else if self.eat_keyword(kw::Type) {
186 self.expect(TokenKind::OpenDelim(Delimiter::Parenthesis))?;
187 let ty = self.parse_type()?;
188 self.expect(TokenKind::CloseDelim(Delimiter::Parenthesis))?;
189 ExprKind::TypeCall(ty)
190 } else if self.check_elementary_type() {
191 let mut ty = self.parse_type()?;
192 if let TypeKind::Elementary(ElementaryType::Address(payable)) = &mut ty.kind
193 && *payable
194 {
195 let msg = "`address payable` cannot be used in an expression";
196 self.dcx().emit_err(ty.span, msg);
197 *payable = false;
198 }
199 ExprKind::Type(ty)
200 } else if self.check_nr_ident() {
201 let ident = self.parse_ident()?;
202 ExprKind::Ident(ident)
203 } else if self.check(TokenKind::OpenDelim(Delimiter::Parenthesis))
204 || self.check(TokenKind::OpenDelim(Delimiter::Bracket))
205 {
206 let TokenKind::OpenDelim(close_delim) = self.token.kind else { unreachable!() };
208 let is_array = close_delim == Delimiter::Bracket;
209 let list = self.parse_optional_items_seq(close_delim, Self::parse_expr)?;
210 if is_array {
211 let list = list
212 .into_iter()
213 .map(|item| match item.into() {
214 Some(expr) => Ok(Some(expr)),
215 None => {
216 let msg = "array expression components cannot be empty";
217 let span = lo.to(self.prev_token.span);
218 Err(self.dcx().err(msg).span(span))
219 }
220 })
221 .collect::<Result<SmallVec<[Option<_>; 8]>, _>>()?;
222
223 ExprKind::Array(unsafe { option_boxes_unwrap_unchecked(self.alloc_smallvec(list)) })
225 } else {
226 ExprKind::Tuple(self.alloc_smallvec(list))
227 }
228 } else {
229 return self.unexpected();
230 };
231 let span = lo.to(self.prev_token.span);
232 Ok(self.alloc(Expr { span, kind }))
233 }
234
235 #[track_caller]
237 pub(super) fn parse_call_args(&mut self) -> PResult<'sess, CallArgs<'ast>> {
238 self.parse_spanned(Self::parse_call_args_kind).map(|(span, kind)| CallArgs { span, kind })
239 }
240
241 #[track_caller]
242 fn parse_call_args_kind(&mut self) -> PResult<'sess, CallArgsKind<'ast>> {
243 if self.look_ahead(1).kind == TokenKind::OpenDelim(Delimiter::Brace) {
244 self.expect(TokenKind::OpenDelim(Delimiter::Parenthesis))?;
245 let args = self.parse_named_args(true).map(CallArgsKind::Named)?;
246 self.expect(TokenKind::CloseDelim(Delimiter::Parenthesis))?;
247 Ok(args)
248 } else {
249 self.parse_unnamed_args().map(CallArgsKind::Unnamed)
250 }
251 }
252
253 pub(super) fn parse_expr_index_kind(&mut self) -> PResult<'sess, IndexKind<'ast>> {
255 self.expect(TokenKind::OpenDelim(Delimiter::Bracket))?;
256 let kind = if self.check(TokenKind::CloseDelim(Delimiter::Bracket)) {
257 IndexKind::Index(None)
259 } else {
260 let start = if self.check(TokenKind::Colon) { None } else { Some(self.parse_expr()?) };
261 if self.eat_noexpect(TokenKind::Colon) {
262 let end = if self.check(TokenKind::CloseDelim(Delimiter::Bracket)) {
264 None
265 } else {
266 Some(self.parse_expr()?)
267 };
268 IndexKind::Range(start, end)
269 } else {
270 IndexKind::Index(start)
272 }
273 };
274 self.expect(TokenKind::CloseDelim(Delimiter::Bracket))?;
275 Ok(kind)
276 }
277
278 #[track_caller]
280 fn parse_named_args(&mut self, allow_empty: bool) -> PResult<'sess, NamedArgList<'ast>> {
281 self.parse_delim_comma_seq(Delimiter::Brace, allow_empty, Self::parse_named_arg)
282 }
283
284 #[track_caller]
286 fn parse_named_arg(&mut self) -> PResult<'sess, NamedArg<'ast>> {
287 let name = self.parse_ident()?;
288 self.expect(TokenKind::Colon)?;
289 let value = self.parse_expr()?;
290 Ok(NamedArg { name, value })
291 }
292
293 #[allow(clippy::vec_box)]
295 #[track_caller]
296 fn parse_unnamed_args(&mut self) -> PResult<'sess, BoxSlice<'ast, Box<'ast, Expr<'ast>>>> {
297 self.parse_paren_comma_seq(true, Self::parse_expr)
298 }
299}
300
301fn token_precedence(t: Token) -> usize {
302 use BinOpToken::*;
304 use TokenKind::*;
305 match t.kind {
306 Question => 3,
307 Eq => 2,
308 BinOpEq(_) => 2,
309 Comma => 1,
310 OrOr => 4,
311 AndAnd => 5,
312 BinOp(Or) => 8,
313 BinOp(Caret) => 9,
314 BinOp(And) => 10,
315 BinOp(Shl) => 11,
316 BinOp(Sar) => 11,
317 BinOp(Shr) => 11,
318 BinOp(Plus) => 12,
319 BinOp(Minus) => 12,
320 BinOp(Star) => 13,
321 BinOp(Slash) => 13,
322 BinOp(Percent) => 13,
323 StarStar => 14,
324 EqEq => 6,
325 Ne => 6,
326 Lt => 7,
327 Gt => 7,
328 Le => 7,
329 Ge => 7,
330 Walrus => 2,
331 _ => 0,
332 }
333}
334
335#[inline]
344unsafe fn option_boxes_unwrap_unchecked<'a, 'b, T>(
345 list: BoxSlice<'a, Option<Box<'b, T>>>,
346) -> BoxSlice<'a, Box<'b, T>> {
347 debug_assert!(list.iter().all(Option::is_some));
348 unsafe { std::mem::transmute(list) }
350}