Repository: HigherOrderCO/Bend
File: src/term/parser/parser.rs (Rust)

Code before:
      .collect::<Vec<Pattern>>()
      .delimited_by(just(Token::LParen), just(Token::RParen))
      .map(|xs| make_tup_tree(&xs, |a, b| Pattern::Tup(Box::new(a), Box::new(b))))
      .boxed();

    let zero = select!(Token::Num(0) => Pattern::Num(MatchNum::Zero));

    let succ =
      just(Token::Add).ignore_then(name_or_era()).map(|nam| Pattern::Num(MatchNum::Succ(Some(nam)))).boxed();

    choice((zero, succ, var, ctr, tup))
  })
}

fn rule_pattern<'a, I>() -> impl Parser<'a, I, (Name, Vec<Pattern>), extra::Err<Rich<'a, Token>>>
where
  I: ValueInput<'a, Token = Token, Span = SimpleSpan>,
{
  let lhs = name().then(pattern().repeated().collect()).boxed();
  choice((lhs.clone(), lhs.clone().delimited_by(just(Token::LParen), just(Token::RParen))))
    .then_ignore(just(Token::Equals))
}

fn rule_body_missing_paren<'a, I>()
-> impl Parser<'a, I, ((Name, Vec<Pattern>), Term), extra::Err<Rich<'a, Token>>>
where
  I: ValueInput<'a, Token = Token, Span = SimpleSpan>,
{
  let terms = (tag(Tag::Static))
    .then(term())
    .foldl(term().and_is(soft_keyword("data").not()).repeated().at_least(1), |(tag, fun), arg| {
      (tag.clone(), Term::App { tag, fun: Box::new(fun), arg: Box::new(arg) })
    });

  let end_of_rule = end().or(soft_keyword("data")).rewind();

  rule_pattern()
    .then(terms)
    .map(|(rule, (_, app))| (rule, app))
    .then_ignore(end_of_rule)
    .validate(|((name, pats), term), span, emit| {
      emit.emit(Rich::custom(span, format!("Missing Parenthesis around rule `{}` body", name)));
      ((name, pats), term)
    })
    .boxed()
}

fn rule<'a, I>() -> impl Parser<'a, I, (Name, Rule), extra::Err<Rich<'a, Token>>>
where
  I: ValueInput<'a, Token = Token, Span = SimpleSpan>,
{

Review comment (bug):
Can you just add a comment explaining why this is here?
"We have a specific rule that always fails so that we can catch this type of error that would otherwise be confused with something else, etc."

Code after:
      .collect::<Vec<Pattern>>()
      .delimited_by(just(Token::LParen), just(Token::RParen))
      .map(|xs| make_tup_tree(&xs, |a, b| Pattern::Tup(Box::new(a), Box::new(b))))
      .boxed();

    let zero = select!(Token::Num(0) => Pattern::Num(MatchNum::Zero));

    let succ =
      just(Token::Add).ignore_then(name_or_era()).map(|nam| Pattern::Num(MatchNum::Succ(Some(nam)))).boxed();

    choice((zero, succ, var, ctr, tup))
  })
}

fn rule_pattern<'a, I>() -> impl Parser<'a, I, (Name, Vec<Pattern>), extra::Err<Rich<'a, Token>>>
where
  I: ValueInput<'a, Token = Token, Span = SimpleSpan>,
{
  let lhs = name().then(pattern().repeated().collect()).boxed();
  choice((lhs.clone(), lhs.clone().delimited_by(just(Token::LParen), just(Token::RParen))))
    .then_ignore(just(Token::Equals))
}

/// This rule always emits an error when it parses successfully 
/// It is used to report a parsing error that would be unclear otherwise 
fn rule_body_missing_paren<'a, I>()
-> impl Parser<'a, I, ((Name, Vec<Pattern>), Term), extra::Err<Rich<'a, Token>>>
where
  I: ValueInput<'a, Token = Token, Span = SimpleSpan>,
{
  let terms = tag(Tag::Static)
    .then(term())
    .foldl(term().and_is(soft_keyword("data").not()).repeated().at_least(1), |(tag, fun), arg| {
      (tag.clone(), Term::App { tag, fun: Box::new(fun), arg: Box::new(arg) })
    });

  let end_of_rule = end().or(soft_keyword("data")).rewind();

  rule_pattern()
    .then(terms)
    .map(|(rule, (_, app))| (rule, app))
    .then_ignore(end_of_rule)
    .validate(|((name, pats), term), span, emit| {
      emit.emit(Rich::custom(span, format!("Missing Parenthesis around rule `{}` body", name)));
      ((name, pats), term)
    })
    .boxed()
}

fn rule<'a, I>() -> impl Parser<'a, I, (Name, Rule), extra::Err<Rich<'a, Token>>>
where