diff --git a/src/ast.rs b/src/ast.rs new file mode 100644 index 0000000..9669522 --- /dev/null +++ b/src/ast.rs @@ -0,0 +1,74 @@ +#[derive(Debug, Clone, PartialEq)] +pub struct Program { + pub statements: Vec, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Statement { + Let(LetStatement), + Show(ShowStatement), + When(WhenStatement), + FunctionDef(FunctionDef), + Expression(Expression), +} + +#[derive(Debug, Clone, PartialEq)] +pub struct LetStatement { + pub identifier: String, + pub value : Expression, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct ShowStatement { + pub value: Expression, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct WhenStatement { + pub condition: Expression, + pub then_block: Vec, + pub otherwise_block: Option>, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct FunctionDef { + pub name: String, + pub parameters: Vec, + pub body : Vec, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Expression { + Number(f64), + String(String), + Identifier(String), + BinaryOp(BinaryOperation), + FunctionCall(FunctionCall), +} + +#[derive(Debug, Clone, PartialEq)] +pub struct BinaryOperation { + pub left: Box, + pub operator: BinaryOperator, + pub right: Box, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum BinaryOperator { + GreaterThan, + LessThan, + GreaterThanOrEqual, + LessThanOrEqual, + Equal, + NotEqual, + Add, + Subtract, + Multiply, + Divide, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct FunctionCall { + pub name: String, + pub arguments: Vec, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c6e1f3a..4776b17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,11 @@ use std::fs; use std::process; mod lexer; +mod parser; +mod ast; use lexer::Lexer; +use parser::Parser; fn main() { let args: Vec = env::args().collect(); @@ -35,4 +38,17 @@ fn main() { }; println!("Tokens: {:?}", tokens); + + // Step 2: Parse into AST + let mut parser = Parser::new(tokens); + let ast = match parser.parse() { + Ok(ast) => ast, + Err(err) => { + eprintln!("Parser error: {}", err); + process::exit(1); + } + }; + + // Step 3: Print AST (debug output) + println!("AST: {:#?}", ast); } diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..866b7d9 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,259 @@ +use crate::ast::*; +use crate::lexer::Token; + +pub struct Parser { + tokens: Vec, + current: usize, +} + +impl Parser { + pub fn new(tokens: Vec) -> Self { + Parser { tokens, current: 0 } + } + + fn current_token(&self) -> &Token { + self.tokens.get(self.current).unwrap_or(&Token::Eof) + } + + fn advance(&mut self) -> &Token { + if self.current < self.tokens.len() { + self.current = self.current + 1; + } + self.current_token() + } + + fn expect(&mut self, expected: Token) -> Result<(), String> { + if std::mem::discriminant(self.current_token()) == std::mem::discriminant(&expected) { + self.advance(); + Ok(()) + } else { + Err(format!("Expected {:?}, found {:?}", expected, self.current_token())) + } + } + + fn skip_newlines(&mut self) { + while matches!(self.current_token(), Token::Newline) { + self.advance(); + } + } + + pub fn parse(&mut self) -> Result { + let mut statements = Vec::new(); + self.skip_newlines(); + + while !matches!(self.current_token(), Token::Eof) { + statements.push(self.parse_statement()?); + self.skip_newlines(); + } + + Ok(Program { statements }) + } + + fn parse_statement(&mut self) -> Result { + match self.current_token() { + Token::Let => self.parse_let_statement(), + Token::Show => self.parse_show_statement(), + Token::When => self.parse_when_statement(), + Token::Define => self.parse_function_def(), + _ => { + let expr = self.parse_expression()?; + Ok(Statement::Expression(expr)) + } + } + } + + fn parse_let_statement(&mut self) -> Result { + self.expect(Token::Let)?; + + let identifier = match self.current_token() { + Token::Identifier(name) => { + let name = name.clone(); + self.advance(); + name + } + _ => return Err("Expected identifier after 'let'".to_string()), + }; + + self.expect(Token::Be)?; + + let value = self.parse_expression()?; + + Ok(Statement::Let(LetStatement { identifier, value })) + } + + fn parse_show_statement(&mut self) -> Result { + self.expect(Token::Show)?; + let value = self.parse_expression()?; + Ok(Statement::Show(ShowStatement { value })) + } + + fn parse_when_statement(&mut self) -> Result { + self.expect(Token::When)?; + + let condition = self.parse_expression()?; + + self.expect(Token::Then)?; + self.skip_newlines(); + self.expect(Token::Indent)?; + + let mut then_block = Vec::new(); + while !matches!(self.current_token(), Token::Dedent | Token::Otherwise | Token::Eof) { + then_block.push(self.parse_statement()?); + self.skip_newlines(); + } + + let otherwise_block = if matches!(self.current_token(), Token::Otherwise) { + self.advance(); // consume 'otherwise' + self.skip_newlines(); + self.expect(Token::Indent)?; + + let mut otherwise_statements = Vec::new(); + while !matches!(self.current_token(), Token::Dedent | Token::Eof) { + otherwise_statements.push(self.parse_statement()?); + self.skip_newlines(); + } + + if matches!(self.current_token(), Token::Dedent) { + self.advance(); + } + + Some(otherwise_statements) + } else { + None + }; + + if matches!(self.current_token(), Token::Dedent) { + self.advance(); + } + + Ok(Statement::When(WhenStatement { + condition, + then_block, + otherwise_block, + })) + } + + fn parse_function_def(&mut self) -> Result { + self.expect(Token::Define)?; + + let name = match self.current_token() { + Token::Identifier(name) => { + let name = name.clone(); + self.advance(); + name + } + _ => return Err("Expected function name after 'define'".to_string()), + }; + + let mut parameters = Vec::new(); + + if matches!(self.current_token(), Token::With) { + self.advance(); // consume 'with' + + loop { + match self.current_token() { + Token::Identifier(param) => { + parameters.push(param.clone()); + self.advance(); + } + _ => break, + } + + // Check for more parameters (basic implementation) + if !matches!(self.current_token(), Token::Identifier(_)) { + break; + } + } + } + + self.skip_newlines(); + self.expect(Token::Indent)?; + + let mut body = Vec::new(); + while !matches!(self.current_token(), Token::End | Token::Dedent | Token::Eof) { + body.push(self.parse_statement()?); + self.skip_newlines(); + } + + if matches!(self.current_token(), Token::End) { + self.advance(); + } else if matches!(self.current_token(), Token::Dedent) { + self.advance(); + } + + Ok(Statement::FunctionDef(FunctionDef { + name, + parameters, + body, + })) + } + + fn parse_expression(&mut self) -> Result { + self.parse_comparison() + } + + fn parse_comparison(&mut self) -> Result { + let mut left = self.parse_primary()?; + + while let Some(op) = self.parse_comparison_operator() { + let right = self.parse_primary()?; + left = Expression::BinaryOp(BinaryOperation { + left: Box::new(left), + operator: op, + right: Box::new(right), + }); + } + + Ok(left) + } + + fn parse_comparison_operator(&mut self) -> Option { + match self.current_token() { + Token::IsGreaterThan => { + self.advance(); + Some(BinaryOperator::GreaterThan) + } + Token::IsLessThan => { + self.advance(); + Some(BinaryOperator::LessThan) + } + Token::IsGreaterThanOrEqual => { + self.advance(); + Some(BinaryOperator::GreaterThanOrEqual) + } + Token::IsLessThanOrEqual => { + self.advance(); + Some(BinaryOperator::LessThanOrEqual) + } + Token::IsEqual => { + self.advance(); + Some(BinaryOperator::Equal) + } + Token::IsNotEqual => { + self.advance(); + Some(BinaryOperator::NotEqual) + } + _ => None, + } + } + + // The `parse_primary` function is Generated by AI. + fn parse_primary(&mut self) -> Result { + match self.current_token().clone() { + Token::Number(n) => { + self.advance(); + Ok(Expression::Number(n)) + } + Token::String(s) => { + self.advance(); + Ok(Expression::String(s)) + } + Token::Identifier(name) => { + self.advance(); + // Check if this is a function call (basic implementation) + Ok(Expression::Identifier(name)) + } + _ => Err(format!("Unexpected token in expression: {:?}", self.current_token())), + } + } +} \ No newline at end of file