rustcc 0.1.1

An little C Complier( now it's just WIP :) )
//! # RustCC Parser
//! A recursive descent parser for a simple expression language.
//! Implements parsing of arithmetic expressions with operator precedence.

use std::error::Error;
use crate::scanner::{Scanner, Token, TokenType};
use crate::ast::{ASTNode, NodeType};

/// A recursive descent parser that converts a stream of tokens into an abstract syntax tree.
/// The parser implements the following grammar:
/// ```
/// expr    : term (('+' | '-') term)*
/// term    : factor (('*' | '/') factor)*
/// factor  : INT_LIT | '(' expr ')'
/// ```
pub struct Parser {
    scanner: Scanner,
    current_token: Option<Token>,
}

impl Parser {
    /// Creates a new parser with the specified scanner.
    /// 
    /// # Arguments
    /// * `scanner` - The scanner to use for token input
    /// 
    /// # Returns
    /// * `Ok(Parser)` - A new parser instance
    /// * `Err(Box<dyn Error>)` - If an error occurs while initializing the parser
    pub fn new(scanner: Scanner) -> Result<Self, Box<dyn Error>> {
        let mut parser = Parser {
            scanner,
            current_token: None,
        };
        // Initialize with the first token
        parser.current_token = parser.scanner.scan()?;
        Ok(parser)
    }

    /// Advances to the next token in the input stream.
    /// 
    /// # Returns
    /// * `Ok(())` - If the next token was successfully read
    /// * `Err(Box<dyn Error>)` - If an error occurs while reading the next token
    fn advance(&mut self) -> Result<(), Box<dyn Error>> {
        self.current_token = self.scanner.scan()?;
        Ok(())
    }

    /// Parses a factor (integer literal).
    /// 
    /// # Returns
    /// * `Ok(Box<ASTNode>)` - The parsed factor as an AST node
    /// * `Err(Box<dyn Error>)` - If a syntax error occurs
    fn factor(&mut self) -> Result<Box<ASTNode>, Box<dyn Error>> {
        match &self.current_token {
            Some(token) => match token.token_type {
                TokenType::IntLit => {
                    let value = token.int_value.unwrap_or(0);
                    let node = Box::new(ASTNode::new_int_lit(value));
                    self.advance()?;
                    Ok(node)
                },
                _ => {
                    Err(format!(
                        "Unexpected token: {:?} at line {}",
                        token, self.scanner.line()
                    ).into())
                }
            },
            None => Err("Unexpected end of input".into())
        }
    }

    /// Parses a term (multiplication and division).
    /// 
    /// # Returns
    /// * `Ok(Box<ASTNode>)` - The parsed term as an AST node
    /// * `Err(Box<dyn Error>)` - If a syntax error occurs
    fn term(&mut self) -> Result<Box<ASTNode>, Box<dyn Error>> {
        let mut left = self.factor()?;

        while let Some(token) = &self.current_token {
            let op_type = match token.token_type {
                TokenType::Star => Some(NodeType::Multiply),
                TokenType::Slash => Some(NodeType::Divide),
                _ => None,
            };

            if let Some(op) = op_type {
                self.advance()?;
                let right = self.factor()?;
                left = Box::new(ASTNode::new_binary_op(op, left, right));
            } else {
                break;
            }
        }

        Ok(left)
    }

    /// Parses an expression (addition and subtraction).
    /// 
    /// # Returns
    /// * `Ok(Box<ASTNode>)` - The parsed expression as an AST node
    /// * `Err(Box<dyn Error>)` - If a syntax error occurs
    pub fn expr(&mut self) -> Result<Box<ASTNode>, Box<dyn Error>> {
        let mut left = self.term()?;

        while let Some(token) = &self.current_token {
            let op_type = match token.token_type {
                TokenType::Plus => Some(NodeType::Add),
                TokenType::Minus => Some(NodeType::Subtract),
                _ => None,
            };

            if let Some(op) = op_type {
                self.advance()?;
                let right = self.term()?;
                left = Box::new(ASTNode::new_binary_op(op, left, right));
            } else {
                break;
            }
        }

        Ok(left)
    }

    /// Parses the entire input and returns the root of the AST.
    /// 
    /// # Returns
    /// * `Ok(Box<ASTNode>)` - The root node of the parsed AST
    /// * `Err(Box<dyn Error>)` - If a syntax error occurs
    pub fn parse(&mut self) -> Result<Box<ASTNode>, Box<dyn Error>> {
        self.expr()
    }
}