Skip to main content

cl_parser/parser/
expr.rs

1//! Conlang's [Expression](Expr) parser.
2
3use super::{PResult, PResultExt, Parse, ParseError, Parser, no_eof, pat::Prec as PPrec};
4use cl_ast::{types::Literal, *};
5use cl_token::{TKind, Token};
6
7/// Organizes the precedence hierarchy for syntactic elements
8#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
9pub enum Prec {
10    Min,
11    /// The Semicolon Operator gets its own precedence level
12    Do,
13    /// The body of a function, conditional, etc.
14    Body,
15    /// An assignment
16    Assign,
17    /// Constructor for a struct
18    Make,
19    /// Constructor for a tuple
20    Tuple,
21    /// The conditional of an `if` or `while` (which is really an `if`)
22    Logical,
23    /// The short-circuiting "boolean or" operator
24    LogOr,
25    /// The short-circuiting "boolean and" operator
26    LogAnd,
27    /// Value comparison operators
28    Compare,
29    /// Constructor for a Range
30    Range,
31    /// Binary/bitwise operators
32    Binary,
33    /// Bit-shifting operators
34    Shift,
35    /// Addition and Subtraction operators
36    Factor,
37    /// Multiplication, Division, and Remainder operators
38    Term,
39    /// Negation, Reference, Try
40    Unary,
41    /// Place-projection operators (`*x`, `x[1]`, `x.a`, `x.1`)
42    Project,
43    /// Call subscripting
44    Extend,
45    Max,
46}
47
48impl Prec {
49    pub const MIN: usize = Prec::Min.value();
50
51    pub const fn value(self) -> usize {
52        self as usize * 2
53    }
54
55    pub const fn prev(self) -> usize {
56        match self {
57            Self::Assign => self.value() + 1,
58            _ => self.value(),
59        }
60    }
61
62    pub const fn next(self) -> usize {
63        match self {
64            Self::Assign => self.value(),
65            _ => self.value() + 1,
66        }
67    }
68}
69
70/// `PseudoOperator`: fake operators used to give certain tokens special behavior.
71#[derive(Clone, Copy, Debug, PartialEq, Eq)]
72pub enum Ps {
73    Id,         // Identifier
74    Mid,        // MetaIdentifier
75    Lit,        // Literal
76    Use,        // use Use
77    Def,        // any definition (let, struct, enum, fn, ...)
78    DocInner,   // Documentation Comment `//!`
79    DocOuter,   // Documentation Comment `///`
80    For,        // for Pat in Expr Expr else Expr
81    Lambda0,    // || Expr
82    Lambda,     // | Pat,* | Expr
83    DoubleRef,  // && Expr
84    Make,       // Expr{ Expr,* }
85    Match,      // match Expr { (Pat => Expr),* }
86    TryCatch,   // try Expr (catch Pat Expr?)* (else Expr)?
87    ImplicitDo, // An implicit semicolon
88    Ellipsis,   // An ellipsis (...)
89    End,        // Produces an empty value.
90    Op(Op),     // A normal [ast::Op]
91}
92
93/// Tries to map the incoming [Token] to a prefix [expression operator](Op)
94/// and its [precedence level](Prec)
95fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
96    Ok(match token.kind {
97        TKind::InDoc => (Ps::DocInner, Prec::Min),
98        TKind::OutDoc => (Ps::DocOuter, Prec::Max),
99        TKind::Do => (Ps::Op(Op::Do), Prec::Do),
100        TKind::Semi => (Ps::End, Prec::Body),
101
102        TKind::Identifier | TKind::ColonColon => (Ps::Id, Prec::Max),
103        TKind::Dollar => (Ps::Mid, Prec::Max),
104        TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => {
105            (Ps::Lit, Prec::Max)
106        }
107        TKind::Use => (Ps::Use, Prec::Max),
108
109        TKind::Pub => (Ps::Op(Op::Pub), Prec::Max),
110        TKind::Const => (Ps::Op(Op::Const), Prec::Max),
111        TKind::Static => (Ps::Op(Op::Static), Prec::Max),
112        TKind::For => (Ps::For, Prec::Max),
113        TKind::Match => (Ps::Match, Prec::Max),
114        TKind::Try => (Ps::TryCatch, Prec::Max),
115        TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
116
117        TKind::Fn
118        | TKind::Mod
119        | TKind::Impl
120        | TKind::Let
121        | TKind::Type
122        | TKind::Struct
123        | TKind::Enum => (Ps::Def, Prec::Max),
124
125        TKind::Loop => (Ps::Op(Op::Loop), Prec::Body),
126        TKind::If => (Ps::Op(Op::If), Prec::Body),
127        TKind::While => (Ps::Op(Op::While), Prec::Body),
128        TKind::Defer => (Ps::Op(Op::Defer), Prec::Body),
129        TKind::Break => (Ps::Op(Op::Break), Prec::Body),
130        TKind::Return => (Ps::Op(Op::Return), Prec::Body),
131        TKind::Continue => (Ps::Op(Op::Continue), Prec::Max),
132
133        TKind::LCurly => (Ps::Op(Op::Block), Prec::Min),
134        TKind::RCurly => (Ps::End, Prec::Do),
135        TKind::LBrack => (Ps::Op(Op::Array), Prec::Tuple),
136        TKind::RBrack => (Ps::End, Prec::Tuple),
137        TKind::LParen => (Ps::Op(Op::Group), Prec::Min),
138        TKind::RParen => (Ps::End, Prec::Tuple),
139        TKind::Amp => (Ps::Op(Op::Refer), Prec::Unary),
140        TKind::AmpAmp => (Ps::DoubleRef, Prec::Unary),
141        TKind::Bang => (Ps::Op(Op::Not), Prec::Unary),
142        TKind::BangBang => (Ps::Op(Op::Identity), Prec::Unary),
143        TKind::Bar => (Ps::Lambda, Prec::Body),
144        TKind::BarBar => (Ps::Lambda0, Prec::Body),
145        TKind::DotDot => (Ps::Op(Op::RangeEx), Prec::Range),
146        TKind::DotDotDot => (Ps::Ellipsis, Prec::Max),
147        TKind::DotDotEq => (Ps::Op(Op::RangeIn), Prec::Range),
148        TKind::Minus => (Ps::Op(Op::Neg), Prec::Unary),
149        TKind::Plus => (Ps::Op(Op::Identity), Prec::Unary),
150        TKind::Star => (Ps::Op(Op::Deref), Prec::Unary),
151        TKind::Hash => (Ps::Op(Op::MetaOuter), Prec::Max),
152        TKind::HashBang => (Ps::Op(Op::MetaInner), Prec::Max),
153
154        kind => Err(ParseError::NotPrefix(kind, token.span))?,
155    })
156}
157
158/// Tries to map the incoming [Token] to an infix [expression operator](Op)
159/// and its [precedence level](Prec)
160const fn from_infix(token: &Token) -> PResult<(Ps, Prec)> {
161    Ok(match token.kind {
162        TKind::Semi => (Ps::Op(Op::Do), Prec::Do), // the inspiration
163        TKind::In => (Ps::Op(Op::Do), Prec::Do),
164
165        TKind::Eq => (Ps::Op(Op::Set), Prec::Assign),
166        TKind::StarEq => (Ps::Op(Op::MulSet), Prec::Assign),
167        TKind::SlashEq => (Ps::Op(Op::DivSet), Prec::Assign),
168        TKind::RemEq => (Ps::Op(Op::RemSet), Prec::Assign),
169        TKind::PlusEq => (Ps::Op(Op::AddSet), Prec::Assign),
170        TKind::MinusEq => (Ps::Op(Op::SubSet), Prec::Assign),
171        TKind::LtLtEq => (Ps::Op(Op::ShlSet), Prec::Assign),
172        TKind::GtGtEq => (Ps::Op(Op::ShrSet), Prec::Assign),
173        TKind::AmpEq => (Ps::Op(Op::AndSet), Prec::Assign),
174        TKind::XorEq => (Ps::Op(Op::XorSet), Prec::Assign),
175        TKind::BarEq => (Ps::Op(Op::OrSet), Prec::Assign),
176        TKind::Comma => (Ps::Op(Op::Tuple), Prec::Tuple),
177        TKind::LCurly => (Ps::Make, Prec::Make),
178        TKind::XorXor => (Ps::Op(Op::LogXor), Prec::Logical),
179        TKind::BarBar => (Ps::Op(Op::LogOr), Prec::LogOr),
180        TKind::AmpAmp => (Ps::Op(Op::LogAnd), Prec::LogAnd),
181        TKind::Lt => (Ps::Op(Op::Lt), Prec::Compare),
182        TKind::LtEq => (Ps::Op(Op::Leq), Prec::Compare),
183        TKind::EqEq => (Ps::Op(Op::Eq), Prec::Compare),
184        TKind::BangEq => (Ps::Op(Op::Neq), Prec::Compare),
185        TKind::GtEq => (Ps::Op(Op::Geq), Prec::Compare),
186        TKind::Gt => (Ps::Op(Op::Gt), Prec::Compare),
187        TKind::DotDot => (Ps::Op(Op::RangeEx), Prec::Range),
188        TKind::DotDotEq => (Ps::Op(Op::RangeIn), Prec::Range),
189        TKind::Amp => (Ps::Op(Op::And), Prec::Binary),
190        TKind::Xor => (Ps::Op(Op::Xor), Prec::Binary),
191        TKind::Bar => (Ps::Op(Op::Or), Prec::Binary),
192        TKind::LtLt => (Ps::Op(Op::Shl), Prec::Shift),
193        TKind::GtGt => (Ps::Op(Op::Shr), Prec::Shift),
194        TKind::Plus => (Ps::Op(Op::Add), Prec::Factor),
195        TKind::Minus => (Ps::Op(Op::Sub), Prec::Factor),
196        TKind::Star => (Ps::Op(Op::Mul), Prec::Term),
197        TKind::Slash => (Ps::Op(Op::Div), Prec::Term),
198        TKind::Rem => (Ps::Op(Op::Rem), Prec::Term),
199
200        TKind::Question => (Ps::Op(Op::Try), Prec::Unary),
201        TKind::Dot => (Ps::Op(Op::Dot), Prec::Project),
202        TKind::LBrack => (Ps::Op(Op::Index), Prec::Project),
203        TKind::LParen => (Ps::Op(Op::Call), Prec::Extend),
204
205        TKind::RParen | TKind::RBrack | TKind::RCurly => (Ps::End, Prec::Max),
206        TKind::As => (Ps::Op(Op::As), Prec::Unary),
207        _ => (Ps::ImplicitDo, Prec::Do),
208    })
209}
210
211impl<'t> Parse<'t> for Expr {
212    type Prec = usize;
213
214    /// Parses an [Expr]ession.
215    ///
216    /// The `level` parameter indicates the operator binding level of the expression.
217    fn parse(p: &mut Parser<'t>, level: usize) -> PResult<Self> {
218        const MIN: usize = Prec::MIN;
219
220        // Prefix
221        let tok @ &Token { kind, span, .. } = p.peek()?;
222        let (op, prec) = from_prefix(tok)?;
223        no_eof(move || {
224            let mut head = match op {
225                // "End" is produced when an "empty" expression is syntactically required.
226                // This happens when a semi or closing delimiter begins an expression.
227                // The token which emitted "End" cannot be consumed, as it is expected
228                // elsewhere.
229                Ps::End if level <= prec.next() => Expr::Omitted,
230                Ps::End => Err(ParseError::NotPrefix(kind, span))?,
231
232                Ps::Id => Expr::Id(p.parse(())?),
233                Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string().as_str().into()),
234                Ps::Lit => Expr::Lit(p.parse(())?),
235                Ps::Use => Expr::Use(p.consume().parse(())?),
236                Ps::Def => Expr::Bind(p.parse(())?),
237                Ps::For => parse_for(p, ())?,
238                Ps::Match => Expr::Match(p.parse(())?),
239                Ps::TryCatch => Expr::Match(Box::new(parse_try_catch(p, ())?)),
240                Ps::Lambda | Ps::Lambda0 => {
241                    p.split()?; // is either `||`, which can be split, or `|`, which can't
242
243                    let args = p
244                        .opt(PPrec::Tuple, TKind::Bar)?
245                        .map(|At(pat, span): At<Pat>| pat.to_tuple(span).at(span))
246                        .unwrap_or(At(Pat::Op(PatOp::Tuple, vec![]), span.merge(p.span())));
247
248                    let rety = p
249                        .opt_if(PPrec::Fn, TKind::Arrow)?
250                        .unwrap_or(Pat::Ignore.at(p.span()));
251
252                    Expr::Bind(Box::new(Bind(
253                        BindOp::Fn,
254                        vec![],
255                        Pat::Op(PatOp::Fn, vec![args, rety]).at(span.merge(p.span())),
256                        vec![p.parse(prec.next())?],
257                    )))
258                }
259                Ps::DocOuter | Ps::DocInner => {
260                    let comment = Literal::Str(p.take_lexeme()?.string().unwrap());
261                    let comment = Expr::Lit(comment).at(span);
262                    // TODO: collapse consecutive doc comments into one
263                    let next = match p.peek().allow_eof()? {
264                        Some(_) => p.parse(prec.next())?,
265                        None => Expr::Omitted.at(span),
266                    };
267                    Expr::Op(
268                        match op {
269                            Ps::DocOuter => Op::MetaOuter,
270                            _ => Op::MetaInner,
271                        },
272                        vec![comment, next],
273                    )
274                }
275                Ps::Ellipsis => p.consume().then(Expr::Omitted),
276                Ps::Op(op @ (Op::MetaOuter | Op::MetaInner)) => {
277                    // Ignores leading #/#! outside of attribute, for doc comments.
278                    if p.consume().expect(TKind::LBrack).is_err() {
279                        return p.parse(level);
280                    }
281                    let meta = p
282                        .opt(MIN, TKind::RBrack)?
283                        .unwrap_or_else(|| Expr::Omitted.at(span));
284                    Expr::Op(op, vec![meta, p.parse(prec.next())?])
285                }
286                Ps::Op(Op::Block) => Expr::Op(
287                    Op::Block,
288                    p.consume().opt(MIN, kind.flip())?.into_iter().collect(),
289                ),
290                Ps::Op(Op::Array) => parse_array(p)?,
291                Ps::Op(Op::Group) => match p.consume().opt(MIN, kind.flip())? {
292                    Some(value) => Expr::Op(Op::Group, vec![value]),
293                    None => Expr::Op(Op::Tuple, vec![]),
294                },
295                Ps::Op(Op::Continue) => p.consume().then(Expr::Op(Op::Continue, vec![])),
296                Ps::Op(op @ (Op::If | Op::While)) => {
297                    p.consume();
298                    let exprs = vec![
299                        // conditional restricted to Logical operators or above
300                        p.parse(Prec::Logical.value())?,
301                        p.parse(prec.next())?,
302                        match p.next_if(TKind::Else).allow_eof()? {
303                            Some(Ok(_)) => p.parse(prec.next())?,
304                            _ => Expr::Omitted.at(span.merge(p.span())),
305                        },
306                    ];
307                    Expr::Op(op, exprs)
308                }
309                Ps::DoubleRef => {
310                    p.split()?;
311                    Expr::Op(Op::Refer, vec![p.parse(prec.next())?])
312                }
313
314                Ps::Op(op) => Expr::Op(op, vec![p.consume().parse(prec.next())?]),
315                _ => unimplemented!("prefix {op:?}"),
316            };
317
318            // Infix and Postfix
319            while let Ok(Some(tok @ &Token { kind, .. })) = p.peek().allow_eof()
320                && let Ok((op, prec)) = from_infix(tok)
321                && level <= prec.prev()
322                && op != Ps::End
323            {
324                let span = span.merge(p.span());
325
326                head = match op {
327                    // Make (structor expressions) are context-sensitive
328                    Ps::Make if let Expr::Id(_) | Expr::MetId(_) = head => {
329                        Expr::Make(Box::new(Make(
330                            head.at(span),
331                            p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
332                        )))
333                    }
334                    Ps::Make => break,
335                    // As is ImplicitDo (semicolon elision)
336                    Ps::ImplicitDo if p.elide_do => head.and_do(span, p.parse(prec.next())?),
337                    Ps::ImplicitDo => break,
338                    // Allow `;` at end of file
339                    Ps::Op(Op::Do) => head.and_do(
340                        span,
341                        match p.consume().peek().allow_eof()? {
342                            Some(_) => p.parse(prec.next())?,
343                            None => At(Expr::Omitted, p.span()),
344                        },
345                    ),
346                    Ps::Op(Op::Index) => Expr::Op(
347                        Op::Index,
348                        p.consume()
349                            .list(vec![head.at(span)], 0, TKind::Comma, TKind::RBrack)?,
350                    ),
351                    Ps::Op(Op::Call) => {
352                        let head = head.at(span);
353                        let args = match p.consume().opt::<At<Expr>>(0, TKind::RParen)? {
354                            None => Expr::Op(Op::Tuple, vec![]).at(span),
355                            Some(At(expr, span)) => expr.to_tuple(span).at(span),
356                        };
357                        Expr::Op(Op::Call, vec![head, args])
358                    }
359                    Ps::Op(op @ Op::Tuple) => Expr::Op(
360                        op,
361                        p.consume()
362                            .list_bare(vec![head.at(span)], prec.next(), kind)?,
363                    ) // then remove `...`s
364                    .deomit(),
365                    Ps::Op(op @ Op::Try) => {
366                        p.consume();
367                        Expr::Op(op, vec![head.at(span)])
368                    }
369                    Ps::Op(op) => {
370                        Expr::Op(op, vec![head.at(span), p.consume().parse(prec.next())?])
371                    }
372                    _ => Err(ParseError::NotInfix(kind, span))?,
373                }
374            }
375
376            Ok(head)
377        })
378    }
379}
380
381/// Parses an array with 0 or more elements, or an array-repetition
382fn parse_array(p: &mut Parser<'_>) -> PResult<Expr> {
383    if p.consume().peek()?.kind == TKind::RBrack {
384        p.consume();
385        return Ok(Expr::Op(Op::Array, vec![]));
386    }
387
388    let prec = Prec::Tuple;
389    let item = p.parse(prec.value())?;
390    let repeat = p.opt_if(prec.next(), TKind::Semi)?;
391    p.expect(TKind::RBrack)?;
392
393    Ok(match (repeat, item) {
394        (Some(repeat), item) => Expr::Op(Op::ArRep, vec![item, repeat]),
395        (None, At(Expr::Op(Op::Tuple, items), _)) => Expr::Op(Op::Array, items),
396        (None, item) => Expr::Op(Op::Array, vec![item]),
397    })
398}
399
400/// Parses a `match` expression
401///
402/// ```ignore
403/// match scrutinee {
404///     (Pat => Expr);*
405/// }
406/// ```
407impl<'t> Parse<'t> for Match {
408    type Prec = ();
409
410    fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self>
411    where Self: Sized {
412        Ok(Self(
413            p.consume().parse(Prec::Tuple.value())?,
414            p.expect(TKind::LCurly)?
415                .list(vec![], (), TKind::Semi, TKind::RCurly)?,
416        ))
417    }
418}
419
420impl<'t> Parse<'t> for MatchArm {
421    type Prec = ();
422
423    fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self>
424    where Self: Sized {
425        // <T,*>
426        // let generics = match p.next_if(TKind::Lt)? {
427        //     Ok(_) => p.list(vec![], (), TKind::Comma, TKind::Gt)?,
428        //     Err(_) => vec![],
429        // };
430
431        // Pat
432        let pat = p.parse(PPrec::Min)?;
433        p.expect(TKind::FatArrow)?;
434        let body = p.parse(Prec::Body.value())?;
435
436        Ok(Self(pat, body))
437    }
438}
439
440/// Parses a try-catch expression
441///
442/// ```rust,ignore
443/// try Expr
444/// catch Pat Expr? // repeat
445/// else Expr       // optional
446/// ```
447fn parse_try_catch(p: &mut Parser<'_>, _level: ()) -> PResult<Match> {
448    let scrutinee: At<_> = p.consume().parse(Prec::Body.next())?;
449    let mut arms = vec![];
450    while let Some(Ok(_)) = p.next_if(TKind::Catch).allow_eof()? {
451        let pat = p.parse(PPrec::Fn)?;
452        match p.peek().allow_eof()? {
453            Some(&Token { kind: TKind::Catch | TKind::Else, span, .. }) => {
454                arms.push(MatchArm(pat, Expr::Omitted.at(span)))
455            }
456            _ => arms.push(MatchArm(pat, p.parse(Prec::Body.next())?)),
457        }
458    }
459    if let Some(Ok(Token { span, .. })) = p.next_if(TKind::Else).allow_eof()? {
460        arms.push(MatchArm(Pat::Ignore.at(span), p.parse(Prec::Body.next())?));
461    }
462
463    Ok(Match(scrutinee, arms))
464}
465
466/// Parses a `for` loop expression
467fn parse_for(p: &mut Parser<'_>, _level: ()) -> PResult<Expr> {
468    // for Pat
469    let pat = p.consume().parse(PPrec::Tuple)?;
470    // in Expr
471    let iter: At<Expr> = p.expect(TKind::In)?.parse(Prec::Logical.next())?;
472    // Expr
473    let pass: At<Expr> = p.parse(Prec::Body.next())?;
474    let pspan = pass.1;
475    // else Expr?
476    let fail = match p.next_if(TKind::Else).allow_eof()? {
477        Some(Ok(_)) => p.parse(Prec::Body.next())?,
478        _ => Expr::Omitted.at(pspan),
479    };
480    /*
481    TODO: desugar for into loop-match:
482    for `pat in `iter `pass else `fail
483    ==>
484    match (`iter).into_iter() {
485        #iter => loop match #iter.next() {
486            None => break `fail,
487            Some(`pat) => `pass,
488        },
489    }
490    */
491
492    Ok(Expr::Bind(Box::new(Bind(
493        BindOp::For,
494        vec![],
495        pat,
496        vec![iter, pass, fail],
497    ))))
498}
499
500/// Returns the [BindOp], [pattern precedence](PPrec), [arrow TKind](TKind), [body precedence](Prec),
501/// and [else precedence](Prec), (if applicable,) which controls the parsing of Bind expressions.
502#[rustfmt::skip]
503#[allow(clippy::type_complexity)]
504fn from_bind(p: &mut Parser<'_>) -> PResult<(BindOp, PPrec, Option<TKind>, Option<Prec>, Option<Prec>)> {
505    let bk = match p.peek()?.kind {
506        // Token            Operator        Pat prec      Body Token             Body prec            Else prec
507        TKind::Let =>    (BindOp::Let,    PPrec::Tuple, Some(TKind::Eq),       Some(Prec::Tuple),  Some(Prec::Body)),
508        TKind::Type =>   (BindOp::Type,   PPrec::Alt,   Some(TKind::Eq),       Some(Prec::Tuple),  None),
509        TKind::Struct => (BindOp::Struct, PPrec::Tuple, None,                  None,               None),
510        TKind::Enum =>   (BindOp::Enum,   PPrec::Tuple, None,                  None,               None),
511        TKind::Fn =>     (BindOp::Fn,     PPrec::Fn,    None,                  Some(Prec::Body),   None),
512        TKind::Mod =>    (BindOp::Mod,    PPrec::Max,   None,                  Some(Prec::Body),   None),
513        TKind::Impl =>   (BindOp::Impl,   PPrec::Fn,    None,                  Some(Prec::Body),   None),
514        other => return Err(ParseError::NotBind(other, p.span()))
515    };
516
517    p.consume();
518    Ok(bk)
519}
520
521impl<'t> Parse<'t> for Bind {
522    type Prec = ();
523
524    fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
525        // let
526        let (level, patp, arrow, bodyp, failp) = from_bind(p)?;
527
528        // <T,*>
529        let generics = match p.next_if(TKind::Lt)? {
530            Ok(_) => p.list(vec![], (), TKind::Comma, TKind::Gt)?,
531            Err(_) => vec![],
532        };
533
534        // Pat
535        let pat = p.parse(patp)?;
536
537        let Some(bodyp) = bodyp else {
538            return Ok(Self(level, generics, pat, vec![]));
539        };
540
541        // `=>` for match, `=` for `let`, `type`
542        if let Some(arrow) = arrow {
543            if p.next_if(arrow).allow_eof()?.is_none_or(|v| v.is_err()) {
544                return Ok(Self(level, generics, pat, vec![]));
545            }
546        } else {
547            // Allow prefix `=`? for the rest of them
548            p.next_if(TKind::Eq).allow_eof()?;
549        }
550
551        // `=` Expr
552        let body = p.parse(bodyp.value())?;
553
554        let Some(failp) = failp else {
555            return Ok(Self(level, generics, pat, vec![body]));
556        };
557
558        // `else` Expr
559        if p.next_if(TKind::Else)
560            .allow_eof()?
561            .is_none_or(|v| v.is_err())
562        {
563            return Ok(Self(level, generics, pat, vec![body]));
564        }
565
566        let fail = p.parse(failp.value())?;
567
568        Ok(Self(level, generics, pat, vec![body, fail]))
569    }
570}
571
572impl<'t> Parse<'t> for MakeArm {
573    type Prec = ();
574
575    fn parse(p: &mut Parser<'t>, _level: ()) -> PResult<Self> {
576        let name = p
577            .next_if(TKind::Identifier)?
578            .map_err(|tk| ParseError::Expected(TKind::Identifier, tk, p.span()))?;
579        Ok(MakeArm(
580            name.lexeme
581                .str()
582                .expect("Identifier should have String")
583                .into(),
584            p.opt_if(Prec::Tuple.next(), TKind::Colon)?,
585        ))
586    }
587}