kind-parser 0.1.3

Parser for the kind compiler
Documentation
use kind_tree::concrete::pat::{Pat, PatIdent, PatKind};

use crate::diagnostic::SyntaxDiagnostic;
use crate::lexer::tokens::Token;
use crate::macros::eat_single;
use crate::state::Parser;

impl<'a> Parser<'a> {
    fn is_pat_cons(&self) -> bool {
        self.get().same_variant(&Token::LPar) && self.peek(1).is_upper_id()
    }

    fn parse_pat_constructor(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let start = self.range();
        self.advance(); // '('
        let name = self.parse_upper_id()?;
        let mut pats = Vec::new();
        while let Some(res) = self.try_single(&|s| s.parse_pat())? {
            pats.push(res)
        }
        let end = self.eat_variant(Token::RPar)?.1;
        Ok(Box::new(Pat {
            range: start.mix(end),
            data: PatKind::App(name, pats),
        }))
    }

    fn parse_pat_u60(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let start = self.range();
        let num = eat_single!(self, Token::Num60(n) => *n)?;
        Ok(Box::new(Pat {
            range: start,
            data: PatKind::U60(num),
        }))
    }
    
    fn parse_pat_char(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let start = self.range();
        let num = eat_single!(self, Token::Char(n) => *n)?;
        Ok(Box::new(Pat {
            range: start,
            data: PatKind::Char(num),
        }))
    }

    fn parse_pat_u120(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let start = self.range();
        let num = eat_single!(self, Token::Num120(n) => *n)?;
        Ok(Box::new(Pat {
            range: start,
            data: PatKind::U120(num),
        }))
    }

    fn parse_pat_str(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let start = self.range();
        let string = eat_single!(self, Token::Str(str) => str.clone())?;
        Ok(Box::new(Pat {
            range: start,
            data: PatKind::Str(string),
        }))
    }

    fn parse_pat_group(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let start = self.range();
        self.advance(); // '('
        let mut pat = self.parse_pat()?;
        let end = self.eat_variant(Token::RPar)?.1;
        pat.range = start.mix(end);
        Ok(pat)
    }

    fn parse_pat_var(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let id = self.parse_id()?;
        Ok(Box::new(Pat {
            range: id.range,
            data: PatKind::Var(PatIdent(id)),
        }))
    }

    fn parse_pat_single_cons(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let id = self.parse_upper_id()?;
        Ok(Box::new(Pat {
            range: id.range,
            data: PatKind::App(id, vec![]),
        }))
    }

    fn parse_pat_hole(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let range = self.range();
        self.eat_variant(Token::Hole)?;
        Ok(Box::new(Pat {
            range,
            data: PatKind::Hole,
        }))
    }

    fn parse_pat_list(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        let range = self.range();
        self.advance(); // '['
        let mut vec = Vec::new();

        if self.check_actual(Token::RBracket) {
            let range = self.advance().1.mix(range);
            return Ok(Box::new(Pat {
                range,
                data: PatKind::List(vec),
            }));
        }

        vec.push(*self.parse_pat()?);
        let mut initialized = false;
        let mut with_comma = false;
        loop {
            let ate_comma = self.check_and_eat(Token::Comma);
            if !initialized {
                initialized = true;
                with_comma = ate_comma;
            }
            if with_comma {
                self.check_and_eat(Token::Comma);
            }

            match self.try_single(&|x| x.parse_pat())? {
                Some(res) => vec.push(*res),
                None => break,
            }
        }

        let range = self.eat_variant(Token::RBracket)?.1.mix(range);

        Ok(Box::new(Pat {
            range,
            data: PatKind::List(vec),
        }))
    }

    pub fn parse_pat(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
        if self.is_pat_cons() {
            self.parse_pat_constructor()
        } else if self.get().is_str() {
            self.parse_pat_str()
        } else if self.get().is_num60() {
            self.parse_pat_u60()
        } else if self.get().is_num120() {
            self.parse_pat_u120()
        } else if self.get().is_char() {
            self.parse_pat_char()
        } else if self.check_actual(Token::LPar) {
            self.parse_pat_group()
        } else if self.get().is_lower_id() {
            self.parse_pat_var()
        } else if self.get().is_upper_id() {
            self.parse_pat_single_cons()
        } else if self.check_actual(Token::LBrace) {
            self.parse_pat_list()
        } else if self.check_actual(Token::Hole) {
            self.parse_pat_hole()
        } else {
            self.fail(vec![])
        }
    }
}