1use super::{Parse, *};
9
10pub fn expr(p: &mut Parser, power: u8) -> PResult<Expr> {
12 let parsing = Parsing::ExprKind;
13 let start = p.loc();
14 let mut head = Expr {
16 kind: match p.peek_kind(Parsing::Unary)? {
17 literal_like!() => Literal::parse(p)?.into(),
18 path_like!() => exprkind_pathlike(p)?,
19 TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
20 TokenKind::Bar | TokenKind::BarBar => Closure::parse(p)?.into(),
21 TokenKind::Grave => Quote::parse(p)?.into(),
22 TokenKind::LCurly => Block::parse(p)?.into(),
23 TokenKind::LBrack => exprkind_arraylike(p)?,
24 TokenKind::LParen => exprkind_tuplelike(p)?,
25 TokenKind::Let => Let::parse(p)?.into(),
26 TokenKind::Match => Match::parse(p)?.into(),
27 TokenKind::While => ExprKind::While(While::parse(p)?),
28 TokenKind::If => ExprKind::If(If::parse(p)?),
29 TokenKind::For => ExprKind::For(For::parse(p)?),
30 TokenKind::Break => ExprKind::Break(Break::parse(p)?),
31 TokenKind::Return => ExprKind::Return(Return::parse(p)?),
32 TokenKind::Continue => {
33 p.consume_peeked();
34 ExprKind::Continue
35 }
36
37 op => {
38 let (kind, prec) =
39 from_prefix(op).ok_or_else(|| p.error(Unexpected(op), parsing))?;
40 let ((), after) = prec.prefix().expect("should have a precedence");
41 p.consume_peeked();
42 Unary { kind, tail: expr(p, after)?.into() }.into()
43 }
44 },
45 span: Span(start, p.loc()),
46 };
47
48 fn from_postfix(op: TokenKind) -> Option<Precedence> {
49 Some(match op {
50 TokenKind::LBrack => Precedence::Index,
51 TokenKind::LParen => Precedence::Call,
52 TokenKind::LCurly => Precedence::Structor,
53 TokenKind::Dot => Precedence::Member,
54 TokenKind::As => Precedence::Cast,
55 _ => None?,
56 })
57 }
58
59 while let Ok(op) = p.peek_kind(parsing) {
60 if let Some((before, ())) = from_postfix(op).and_then(Precedence::postfix) {
62 if before < power {
63 break;
64 }
65
66 head = Expr {
67 kind: match op {
68 TokenKind::LBrack => {
69 p.consume_peeked();
70 let indices =
71 sep(Expr::parse, TokenKind::Comma, TokenKind::RBrack, parsing)(p)?;
72 p.match_type(TokenKind::RBrack, parsing)?;
73 ExprKind::Index(Index { head: head.into(), indices })
74 }
75 TokenKind::LParen => {
76 p.consume_peeked();
77 let exprs =
78 sep(Expr::parse, TokenKind::Comma, TokenKind::RParen, parsing)(p)?;
79 p.match_type(TokenKind::RParen, parsing)?;
80 Binary {
81 kind: BinaryKind::Call,
82 parts: (
83 head,
84 Expr { kind: Tuple { exprs }.into(), span: Span(start, p.loc()) },
85 )
86 .into(),
87 }
88 .into()
89 }
90 TokenKind::LCurly => match head.kind {
91 ExprKind::Path(path) => ExprKind::Structor(structor_body(p, path)?),
92 _ => break,
93 },
94 TokenKind::Dot => {
95 p.consume_peeked();
96 let kind = MemberKind::parse(p)?;
97 Member { head: Box::new(head), kind }.into()
98 }
99 TokenKind::As => {
100 p.consume_peeked();
101 let ty = Ty::parse(p)?;
102 Cast { head: head.into(), ty }.into()
103 }
104 _ => Err(p.error(Unexpected(op), parsing))?,
105 },
106 span: Span(start, p.loc()),
107 };
108 continue;
109 }
110 if let Some((kind, prec)) = from_infix(op) {
112 let (before, after) = prec.infix().expect("should have a precedence");
113 if before < power {
114 break;
115 }
116 p.consume_peeked();
117
118 let tail = expr(p, after)?;
119 head = Expr {
120 kind: Binary { kind, parts: (head, tail).into() }.into(),
121 span: Span(start, p.loc()),
122 };
123 continue;
124 }
125
126 if let Some((kind, prec)) = from_modify(op) {
127 let (before, after) = prec.infix().expect("should have a precedence");
128 if before < power {
129 break;
130 }
131 p.consume_peeked();
132
133 let tail = expr(p, after)?;
134 head = Expr {
135 kind: Modify { kind, parts: (head, tail).into() }.into(),
136 span: Span(start, p.loc()),
137 };
138 continue;
139 }
140
141 if let TokenKind::Eq = op {
142 let (before, after) = Precedence::Assign
143 .infix()
144 .expect("should have a precedence");
145 if before < power {
146 break;
147 }
148 p.consume_peeked();
149
150 let tail = expr(p, after)?;
151 head = Expr {
152 kind: Assign { parts: (head, tail).into() }.into(),
153 span: Span(start, p.loc()),
154 };
155
156 continue;
157 }
158
159 if let TokenKind::As = op {
160 let before = Precedence::Cast.level();
161 if before < power {
162 break;
163 }
164 p.consume_peeked();
165
166 let ty = Ty::parse(p)?;
167 head = Expr { kind: Cast { head: head.into(), ty }.into(), span: Span(start, p.loc()) };
168
169 continue;
170 }
171
172 break;
173 }
174
175 Ok(head)
176}
177
178fn exprkind_arraylike(p: &mut Parser) -> PResult<ExprKind> {
183 const P: Parsing = Parsing::Array;
184 const START: TokenKind = TokenKind::LBrack;
185 const END: TokenKind = TokenKind::RBrack;
186
187 p.match_type(START, P)?;
188 let out = match p.peek_kind(P)? {
189 END => Array { values: vec![] }.into(),
190 _ => exprkind_array_rep(p)?,
191 };
192 p.match_type(END, P)?;
193 Ok(out)
194}
195
196fn exprkind_array_rep(p: &mut Parser) -> PResult<ExprKind> {
198 const P: Parsing = Parsing::Array;
199 const END: TokenKind = TokenKind::RBrack;
200
201 let first = Expr::parse(p)?;
202 Ok(match p.peek_kind(P)? {
203 TokenKind::Semi => ArrayRep {
204 value: first.into(),
205 repeat: {
206 p.consume_peeked();
207 p.parse()?
208 },
209 }
210 .into(),
211 TokenKind::RBrack => Array { values: vec![first] }.into(),
212 TokenKind::Comma => Array {
213 values: {
214 p.consume_peeked();
215 let mut out = vec![first];
216 out.extend(sep(Expr::parse, TokenKind::Comma, END, P)(p)?);
217 out
218 },
219 }
220 .into(),
221 ty => Err(p.error(Unexpected(ty), P))?,
222 })
223}
224
225fn exprkind_tuplelike(p: &mut Parser) -> PResult<ExprKind> {
229 p.match_type(TokenKind::LParen, Parsing::Group)?;
230 let out = match p.peek_kind(Parsing::Group)? {
231 TokenKind::RParen => Ok(ExprKind::Empty),
232 _ => exprkind_group(p),
233 };
234 p.match_type(TokenKind::RParen, Parsing::Group)?;
235 out
236}
237
238fn exprkind_group(p: &mut Parser) -> PResult<ExprKind> {
240 let first = Expr::parse(p)?;
241 match p.peek_kind(Parsing::Group)? {
242 TokenKind::Comma => {
243 let mut exprs = vec![first];
244 p.consume_peeked();
245 while TokenKind::RParen != p.peek_kind(Parsing::Tuple)? {
246 exprs.push(Expr::parse(p)?);
247 match p.peek_kind(Parsing::Tuple)? {
248 TokenKind::Comma => p.consume_peeked(),
249 _ => break,
250 };
251 }
252 Ok(Tuple { exprs }.into())
253 }
254 _ => Ok(Group { expr: first.into() }.into()),
255 }
256}
257
258fn exprkind_pathlike(p: &mut Parser) -> PResult<ExprKind> {
260 Path::parse(p).map(Into::into)
261}
262
263fn structor_body(p: &mut Parser, to: Path) -> PResult<Structor> {
265 let init = delim(
266 sep(
267 Fielder::parse,
268 TokenKind::Comma,
269 CURLIES.1,
270 Parsing::Structor,
271 ),
272 CURLIES,
273 Parsing::Structor,
274 )(p)?;
275
276 Ok(Structor { to, init })
277}
278
279#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
281pub enum Precedence {
282 Assign,
283 Structor, Condition, Logic,
286 Compare,
287 Range,
288 Bitwise,
289 Shift,
290 Factor,
291 Term,
292 Unary,
293 Index,
294 Cast,
295 Member, Call,
297 Deref,
298}
299
300impl Precedence {
301 #[inline]
302 pub const fn level(self) -> u8 {
303 (self as u8) << 1
304 }
305
306 pub fn prefix(self) -> Option<((), u8)> {
307 match self {
308 Self::Assign => Some(((), self.level())),
309 Self::Unary => Some(((), self.level())),
310 Self::Deref => Some(((), self.level())),
311 _ => None,
312 }
313 }
314
315 pub fn infix(self) -> Option<(u8, u8)> {
316 let level = self.level();
317 match self {
318 Self::Unary => None,
319 Self::Assign => Some((level + 1, level)),
320 _ => Some((level, level + 1)),
321 }
322 }
323
324 pub fn postfix(self) -> Option<(u8, ())> {
325 match self {
326 Self::Structor | Self::Index | Self::Call | Self::Member | Self::Cast => {
327 Some((self.level(), ()))
328 }
329 _ => None,
330 }
331 }
332}
333
334impl From<ModifyKind> for Precedence {
335 fn from(_value: ModifyKind) -> Self {
336 Precedence::Assign
337 }
338}
339
340impl From<BinaryKind> for Precedence {
341 fn from(value: BinaryKind) -> Self {
342 use BinaryKind as Op;
343 match value {
344 Op::Call => Precedence::Call,
345 Op::Mul | Op::Div | Op::Rem => Precedence::Term,
346 Op::Add | Op::Sub => Precedence::Factor,
347 Op::Shl | Op::Shr => Precedence::Shift,
348 Op::BitAnd | Op::BitOr | Op::BitXor => Precedence::Bitwise,
349 Op::LogAnd | Op::LogOr | Op::LogXor => Precedence::Logic,
350 Op::RangeExc | Op::RangeInc => Precedence::Range,
351 Op::Lt | Op::LtEq | Op::Equal | Op::NotEq | Op::GtEq | Op::Gt => Precedence::Compare,
352 }
353 }
354}
355
356impl From<UnaryKind> for Precedence {
357 fn from(value: UnaryKind) -> Self {
358 use UnaryKind as Op;
359 match value {
360 Op::Loop => Precedence::Assign,
361 Op::Deref => Precedence::Deref,
362 _ => Precedence::Unary,
363 }
364 }
365}
366
367macro operator($($name:ident ($takes:ident => $returns:ident) {$($t:ident => $p:ident),*$(,)?};)*) {$(
369 pub fn $name (value: $takes) -> Option<($returns, Precedence)> {
370 match value {
371 $($takes::$t => Some(($returns::$p, Precedence::from($returns::$p))),)*
372 _ => None?,
373 }
374 })*
375}
376
377operator! {
378 from_prefix (TokenKind => UnaryKind) {
379 Loop => Loop,
380 Star => Deref,
381 Minus => Neg,
382 Bang => Not,
383 DotDot => RangeExc,
384 DotDotEq => RangeInc,
385 At => At,
386 Tilde => Tilde,
387 };
388
389 from_modify(TokenKind => ModifyKind) {
390 AmpEq => And,
391 BarEq => Or,
392 XorEq => Xor,
393 LtLtEq => Shl,
394 GtGtEq => Shr,
395 PlusEq => Add,
396 MinusEq => Sub,
397 StarEq => Mul,
398 SlashEq => Div,
399 RemEq => Rem,
400 };
401
402 from_infix (TokenKind => BinaryKind) {
403 Lt => Lt,
404 LtEq => LtEq,
405 EqEq => Equal,
406 BangEq => NotEq,
407 GtEq => GtEq,
408 Gt => Gt,
409 DotDot => RangeExc,
410 DotDotEq => RangeInc,
411 AmpAmp => LogAnd,
412 BarBar => LogOr,
413 XorXor => LogXor,
414 Amp => BitAnd,
415 Bar => BitOr,
416 Xor => BitXor,
417 LtLt => Shl,
418 GtGt => Shr,
419 Plus => Add,
420 Minus => Sub,
421 Star => Mul,
422 Slash => Div,
423 Rem => Rem,
424 };
425}