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