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 let value = p.match_type(TokenKind::Literal, Parsing::ArrayRep)?;
208 match value.data() {
209 TokenData::Integer(size) => *size as usize,
210 _ => {
211 Err(p.error(ErrorKind::Unexpected(TokenKind::Literal), Parsing::ArrayRep))?
212 }
213 }
214 },
215 }
216 .into(),
217 TokenKind::RBrack => Array { values: vec![first] }.into(),
218 TokenKind::Comma => Array {
219 values: {
220 p.consume_peeked();
221 let mut out = vec![first];
222 out.extend(sep(Expr::parse, TokenKind::Comma, END, P)(p)?);
223 out
224 },
225 }
226 .into(),
227 ty => Err(p.error(Unexpected(ty), P))?,
228 })
229}
230
231fn exprkind_tuplelike(p: &mut Parser) -> PResult<ExprKind> {
235 p.match_type(TokenKind::LParen, Parsing::Group)?;
236 let out = match p.peek_kind(Parsing::Group)? {
237 TokenKind::RParen => Ok(ExprKind::Empty),
238 _ => exprkind_group(p),
239 };
240 p.match_type(TokenKind::RParen, Parsing::Group)?;
241 out
242}
243
244fn exprkind_group(p: &mut Parser) -> PResult<ExprKind> {
246 let first = Expr::parse(p)?;
247 match p.peek_kind(Parsing::Group)? {
248 TokenKind::Comma => {
249 let mut exprs = vec![first];
250 p.consume_peeked();
251 while TokenKind::RParen != p.peek_kind(Parsing::Tuple)? {
252 exprs.push(Expr::parse(p)?);
253 match p.peek_kind(Parsing::Tuple)? {
254 TokenKind::Comma => p.consume_peeked(),
255 _ => break,
256 };
257 }
258 Ok(Tuple { exprs }.into())
259 }
260 _ => Ok(Group { expr: first.into() }.into()),
261 }
262}
263
264fn exprkind_pathlike(p: &mut Parser) -> PResult<ExprKind> {
266 Path::parse(p).map(Into::into)
267}
268
269fn structor_body(p: &mut Parser, to: Path) -> PResult<Structor> {
271 let init = delim(
272 sep(
273 Fielder::parse,
274 TokenKind::Comma,
275 CURLIES.1,
276 Parsing::Structor,
277 ),
278 CURLIES,
279 Parsing::Structor,
280 )(p)?;
281
282 Ok(Structor { to, init })
283}
284
285#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
287pub enum Precedence {
288 Assign,
289 Structor, Condition, Logic,
292 Compare,
293 Range,
294 Bitwise,
295 Shift,
296 Factor,
297 Term,
298 Unary,
299 Index,
300 Cast,
301 Member, Call,
303 Deref,
304}
305
306impl Precedence {
307 #[inline]
308 pub const fn level(self) -> u8 {
309 (self as u8) << 1
310 }
311
312 pub fn prefix(self) -> Option<((), u8)> {
313 match self {
314 Self::Assign => Some(((), self.level())),
315 Self::Unary => Some(((), self.level())),
316 Self::Deref => Some(((), self.level())),
317 _ => None,
318 }
319 }
320
321 pub fn infix(self) -> Option<(u8, u8)> {
322 let level = self.level();
323 match self {
324 Self::Unary => None,
325 Self::Assign => Some((level + 1, level)),
326 _ => Some((level, level + 1)),
327 }
328 }
329
330 pub fn postfix(self) -> Option<(u8, ())> {
331 match self {
332 Self::Structor | Self::Index | Self::Call | Self::Member | Self::Cast => {
333 Some((self.level(), ()))
334 }
335 _ => None,
336 }
337 }
338}
339
340impl From<ModifyKind> for Precedence {
341 fn from(_value: ModifyKind) -> Self {
342 Precedence::Assign
343 }
344}
345
346impl From<BinaryKind> for Precedence {
347 fn from(value: BinaryKind) -> Self {
348 use BinaryKind as Op;
349 match value {
350 Op::Call => Precedence::Call,
351 Op::Mul | Op::Div | Op::Rem => Precedence::Term,
352 Op::Add | Op::Sub => Precedence::Factor,
353 Op::Shl | Op::Shr => Precedence::Shift,
354 Op::BitAnd | Op::BitOr | Op::BitXor => Precedence::Bitwise,
355 Op::LogAnd | Op::LogOr | Op::LogXor => Precedence::Logic,
356 Op::RangeExc | Op::RangeInc => Precedence::Range,
357 Op::Lt | Op::LtEq | Op::Equal | Op::NotEq | Op::GtEq | Op::Gt => Precedence::Compare,
358 }
359 }
360}
361
362impl From<UnaryKind> for Precedence {
363 fn from(value: UnaryKind) -> Self {
364 use UnaryKind as Op;
365 match value {
366 Op::Loop => Precedence::Assign,
367 Op::Deref => Precedence::Deref,
368 _ => Precedence::Unary,
369 }
370 }
371}
372
373macro operator($($name:ident ($takes:ident => $returns:ident) {$($t:ident => $p:ident),*$(,)?};)*) {$(
375 pub fn $name (value: $takes) -> Option<($returns, Precedence)> {
376 match value {
377 $($takes::$t => Some(($returns::$p, Precedence::from($returns::$p))),)*
378 _ => None?,
379 }
380 })*
381}
382
383operator! {
384 from_prefix (TokenKind => UnaryKind) {
385 Loop => Loop,
386 Star => Deref,
387 Minus => Neg,
388 Bang => Not,
389 DotDot => RangeExc,
390 DotDotEq => RangeInc,
391 At => At,
392 Tilde => Tilde,
393 };
394
395 from_modify(TokenKind => ModifyKind) {
396 AmpEq => And,
397 BarEq => Or,
398 XorEq => Xor,
399 LtLtEq => Shl,
400 GtGtEq => Shr,
401 PlusEq => Add,
402 MinusEq => Sub,
403 StarEq => Mul,
404 SlashEq => Div,
405 RemEq => Rem,
406 };
407
408 from_infix (TokenKind => BinaryKind) {
409 Lt => Lt,
410 LtEq => LtEq,
411 EqEq => Equal,
412 BangEq => NotEq,
413 GtEq => GtEq,
414 Gt => Gt,
415 DotDot => RangeExc,
416 DotDotEq => RangeInc,
417 AmpAmp => LogAnd,
418 BarBar => LogOr,
419 XorXor => LogXor,
420 Amp => BitAnd,
421 Bar => BitOr,
422 Xor => BitXor,
423 LtLt => Shl,
424 GtGt => Shr,
425 Plus => Add,
426 Minus => Sub,
427 Star => Mul,
428 Slash => Div,
429 Rem => Rem,
430 };
431}