ty-parser 0.1.0

C-syntax parser for the Ty programming language
Documentation
use super::*;

impl Parser {
    pub(super) fn parse_block(&mut self) -> Result<Block> {
        self.expect(Token::LeftBrace)?;
        self.finish_block()
    }

    pub(super) fn finish_block(&mut self) -> Result<Block> {
        let mut statements = Vec::new();
        let mut result = None;

        while !self.at(&Token::RightBrace) && !self.at(&Token::End) {
            if self.is_statement_start() {
                statements.extend(self.parse_statement()?);
            } else {
                let expression = self.parse_expression()?;
                result = self.finish_block_statement(expression, &mut statements);
                if result.is_some() {
                    break;
                }
            }
        }

        self.expect(Token::RightBrace)?;
        Ok(Block { statements, result })
    }

    pub(super) fn finish_block_after_expression(&mut self, first: Expression) -> Result<Block> {
        let mut statements = Vec::new();
        let mut result = self.finish_block_statement(first, &mut statements);

        if result.is_none() {
            while !self.at(&Token::RightBrace) && !self.at(&Token::End) {
                if self.is_statement_start() {
                    statements.extend(self.parse_statement()?);
                } else {
                    let expression = self.parse_expression()?;
                    result = self.finish_block_statement(expression, &mut statements);
                    if result.is_some() {
                        break;
                    }
                }
            }
        }

        self.expect(Token::RightBrace)?;
        Ok(Block { statements, result })
    }

    fn finish_block_statement(
        &mut self,
        expression: Expression,
        statements: &mut Vec<Statement>,
    ) -> Option<Box<Expression>> {
        if self.at(&Token::Semicolon) {
            self.advance();
            statements.push(Statement::Expression(expression));
            None
        } else if is_block_expression(&expression)
            && !self.at(&Token::RightBrace)
            && !self.at(&Token::End)
        {
            statements.push(Statement::Expression(expression));
            None
        } else {
            Some(Box::new(auto_deref(expression, &self.context)))
        }
    }

    pub(super) fn is_statement_start(&self) -> bool {
        matches!(
            self.peek(),
            Token::Let
                | Token::Var
                | Token::Ref
                | Token::Return
                | Token::Label
                | Token::Jump
                | Token::Defer
                | Token::While
        )
    }

    pub(super) fn parse_statement(&mut self) -> Result<Vec<Statement>> {
        match self.peek().clone() {
            Token::Let => self.parse_let(Binding::Value),
            Token::Var => self.parse_let(Binding::Variable),
            Token::Ref => self.parse_let(Binding::Reference),
            Token::Return => self.parse_return().map(|s| vec![s]),
            Token::Label => self.parse_label().map(|s| vec![s]),
            Token::Jump => self.parse_jump().map(|s| vec![s]),
            Token::Defer => self.parse_defer().map(|s| vec![s]),
            Token::While => self.parse_while().map(|s| vec![s]),
            _ => unreachable!(),
        }
    }

    fn parse_while(&mut self) -> Result<Statement> {
        self.advance();
        let condition = auto_deref(self.parse_expression()?, &self.context);
        let body = self.parse_block()?;
        Ok(Statement::While { condition, body })
    }

    fn parse_defer(&mut self) -> Result<Statement> {
        self.advance();
        let inner = if self.is_statement_start() {
            let mut statements = self.parse_statement()?;
            if statements.len() == 1 {
                statements.remove(0)
            } else {
                return Err(Error {
                    message: "defer does not support multi-assignment".into(),
                    span: Some(self.span()),
                });
            }
        } else {
            let expression = self.parse_expression()?;
            self.expect(Token::Semicolon)?;
            Statement::Expression(expression)
        };
        Ok(Statement::Defer(Box::new(inner)))
    }

    fn parse_let(&mut self, binding: Binding) -> Result<Vec<Statement>> {
        self.advance();
        let name = self.expect_identifier()?;

        let start_line = self.span().line;

        if self.at(&Token::Comma) {
            return self.parse_multi_let(binding, name);
        }

        let (declared_type, value) = if self.at(&Token::Colon) {
            self.advance();
            let declared = self.parse_type_expression()?;
            self.expect(Token::Equal)?;
            let value = auto_deref(self.parse_expression()?, &self.context);
            (Some(declared), value)
        } else {
            self.expect(Token::Equal)?;
            let value = auto_deref(self.parse_expression()?, &self.context);
            (None, value)
        };

        self.expect(Token::Semicolon)?;

        let inner_type = declared_type
            .clone()
            .unwrap_or_else(|| value.resolved_type.clone());
        self.context
            .define_variable(name.clone(), wrap_binding_type(binding, inner_type));
        if matches!(binding, Binding::Variable | Binding::Reference) {
            self.context.mark_auto_ref(&name);
        }

        Ok(vec![Statement::Let {
            name,
            binding,
            declared_type,
            value,
            line: start_line,
        }])
    }

    fn parse_multi_let(&mut self, binding: Binding, first_name: String) -> Result<Vec<Statement>> {
        let mut names = vec![first_name];
        while self.at(&Token::Comma) {
            self.advance();
            names.push(self.expect_identifier()?);
        }
        self.expect(Token::Equal)?;
        let mut values = vec![auto_deref(self.parse_expression()?, &self.context)];
        while self.at(&Token::Comma) {
            self.advance();
            values.push(auto_deref(self.parse_expression()?, &self.context));
        }
        self.expect(Token::Semicolon)?;

        if names.len() != values.len() {
            return Err(Error {
                message: format!(
                    "multi-let: {} names but {} values",
                    names.len(),
                    values.len()
                ),
                span: Some(self.span()),
            });
        }

        let mut statements = Vec::new();
        for (name, value) in names.into_iter().zip(values) {
            let inner_type = value.resolved_type.clone();
            self.context
                .define_variable(name.clone(), wrap_binding_type(binding, inner_type));
            if matches!(binding, Binding::Variable | Binding::Reference) {
                self.context.mark_auto_ref(&name);
            }
            statements.push(Statement::Let {
                name,
                binding,
                declared_type: None,
                value,
                line: self.span().line,
            });
        }
        Ok(statements)
    }

    fn parse_return(&mut self) -> Result<Statement> {
        self.advance();
        if self.at(&Token::Semicolon) {
            self.advance();
            return Ok(Statement::Return(None));
        }
        let value = auto_deref(self.parse_expression()?, &self.context);
        self.expect(Token::Semicolon)?;
        Ok(Statement::Return(Some(value)))
    }

    fn parse_label(&mut self) -> Result<Statement> {
        self.advance();
        let name = self.expect_identifier()?;

        let mut parameters = Vec::new();
        let mut initial_arguments = Vec::new();
        if self.at(&Token::LeftParen) {
            self.advance();
            if !self.at(&Token::RightParen) {
                loop {
                    let parameter_name = self.expect_identifier()?;
                    let parameter_type = if self.at(&Token::Colon) {
                        self.advance();
                        Some(self.parse_type_expression()?)
                    } else {
                        None
                    };
                    self.expect(Token::Equal)?;
                    let init = auto_deref(self.parse_expression()?, &self.context);
                    let parameter_type =
                        parameter_type.unwrap_or_else(|| init.resolved_type.clone());
                    parameters.push(Parameter {
                        name: parameter_name,
                        parameter_type,
                    });
                    initial_arguments.push(init);
                    if !self.at(&Token::Comma) {
                        break;
                    }
                    self.advance();
                }
            }
            self.expect(Token::RightParen)?;
        }
        self.expect(Token::Semicolon)?;

        for parameter in &parameters {
            self.context
                .define_variable(parameter.name.clone(), parameter.parameter_type.clone());
        }

        Ok(Statement::Label {
            name,
            parameters,
            initial_arguments,
        })
    }

    fn parse_jump(&mut self) -> Result<Statement> {
        self.advance();
        let label = self.expect_identifier()?;

        let mut arguments = Vec::new();
        if self.at(&Token::LeftParen) {
            self.advance();
            if !self.at(&Token::RightParen) {
                arguments.push(auto_deref(self.parse_expression()?, &self.context));
                while self.at(&Token::Comma) {
                    self.advance();
                    arguments.push(auto_deref(self.parse_expression()?, &self.context));
                }
            }
            self.expect(Token::RightParen)?;
        }
        self.expect(Token::Semicolon)?;

        Ok(Statement::Jump { label, arguments })
    }
}