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