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

Code before:
        unexpected_tag(self)?;
        let pat = self.parse_pattern(true)?;
        self.consume("=")?;
        let val = self.parse_term()?;
        self.try_consume(";");
        let nxt = self.parse_term()?;
        return Ok(Term::Let { pat: Box::new(pat), val: Box::new(val), nxt: Box::new(nxt) });
      }

      // Ask (monadic operation)
      if self.try_parse_keyword("ask") {
        unexpected_tag(self)?;
        let pat = self.parse_pattern(true)?;
        self.consume("=")?;
        let val = self.parse_term()?;
        self.try_consume(";");
        let nxt = self.parse_term()?;
        return Ok(Term::Ask { pat: Box::new(pat), val: Box::new(val), nxt: Box::new(nxt) });
      }

      // Def
      if self.try_parse_keyword("def") {
        self.skip_trivia();
        let (cur_name, rule) = self.parse_rule()?;
        let mut rules = vec![rule];
        // the current index to backtack in case of fail to parse the next rule.
        let mut nxt_term = *self.index();
        loop {
          self.skip_trivia();
          // save the start position of the rule that can be a next def term.
          let nxt_def = *self.index();
          match self.parse_rule() {
            Ok((name, rule)) => {
              if name == "def" {
                // parse the nxt def term.
                self.index = nxt_def;
                return Ok(Term::Def { nam: cur_name, rules, nxt: Box::new(self.parse_term()?) });
              }
              if name == cur_name {
                rules.push(rule);
                // save the current position.
                nxt_term = *self.index();
              } else {
                let cur = *self.index();
                let msg = format!("Expected a rule with name '{cur_name}'.");
                return self.with_ctx(Err(msg), nxt_def..cur);
              }
            }
            // if failed it is a term.
            Err(_) => break self.index = nxt_term,
          }

Review comment (bug):
```suggestion
        // the current index to backtrack in case of fail to parse the next rule.
```

Code after:
        unexpected_tag(self)?;
        let pat = self.parse_pattern(true)?;
        self.consume("=")?;
        let val = self.parse_term()?;
        self.try_consume(";");
        let nxt = self.parse_term()?;
        return Ok(Term::Let { pat: Box::new(pat), val: Box::new(val), nxt: Box::new(nxt) });
      }

      // Ask (monadic operation)
      if self.try_parse_keyword("ask") {
        unexpected_tag(self)?;
        let pat = self.parse_pattern(true)?;
        self.consume("=")?;
        let val = self.parse_term()?;
        self.try_consume(";");
        let nxt = self.parse_term()?;
        return Ok(Term::Ask { pat: Box::new(pat), val: Box::new(val), nxt: Box::new(nxt) });
      }

      // Def
      if self.try_parse_keyword("def") {
        self.skip_trivia();
        let (cur_name, rule) = self.parse_rule()?;
        let mut rules = vec![rule];
        // the current index to backtrack in case of fail to parse the next rule.
        let mut nxt_term = *self.index();
        loop {
          self.skip_trivia();
          // save the start position of the rule that can be a next def term.
          let nxt_def = *self.index();
          match self.parse_rule() {
            Ok((name, rule)) => {
              if name == "def" {
                // parse the nxt def term.
                self.index = nxt_def;
                return Ok(Term::Def { nam: cur_name, rules, nxt: Box::new(self.parse_term()?) });
              }
              if name == cur_name {
                rules.push(rule);
                // save the current position.
                nxt_term = *self.index();
              } else {
                let cur = *self.index();
                let msg = format!("Expected a rule with name '{cur_name}'.");
                return self.with_ctx(Err(msg), nxt_def..cur);
              }
            }
            // if failed it is a term.
            Err(_) => break self.index = nxt_term,
          }