use super::tokenizer::{Token, TokenKind}; pub fn parse(mut tokens: Vec) -> Program { let mut stmts: Vec> = vec![]; let mut current = 0; loop { if current >= tokens.len() { break; } // print!("{:?}", tokens[current]); if tokens[current].kind == TokenKind::Semicolon { stmts.push(tokens.drain(..=current).collect::>()); current = 0; } else { current += 1; } } let mut statements = vec![]; // for s in &stmts { // for t in s { // print!("{:?}", t.kind); // } // print!("\n"); // } for s in stmts { statements.push(parse_statement(s)); } statements } fn parse_statement(statement: Vec) -> Statement { if statement.len() == 1 { // Must just be a semicolon. return Statement::Nop; } let parse_function_call = |tokens: &Vec| -> Option { // Check for ( ... ); if tokens[0].kind != TokenKind::Identifier { return None; } else if tokens[1].kind != TokenKind::LeftParen { return None; } else if tokens[tokens.len() - 2].kind != TokenKind::RightParen { return None; } else if tokens[tokens.len() - 1].kind != TokenKind::Semicolon { return None; } else { let function_name = tokens[0].value.clone(); let mut args = vec![]; let mut current = 2; loop { args.push(parse_expression(tokens, &mut current)); if tokens[current].kind == TokenKind::Comma { current += 1; } if tokens[current].kind == TokenKind::RightParen { break; } } Some(Statement::FunctionCall { name: function_name, arguments: args, }) } }; // The only form of statement. parse_function_call(&statement).expect("could not parse function call") } fn parse_expression(tokens: &Vec, current: &mut usize) -> Expression { if tokens[*current].kind == TokenKind::StringLiteral { let out = Expression::Literal(Literal::StringLiteral(tokens[*current].value.clone())); *current += 1; out } else if tokens[*current].kind == TokenKind::IntLiteral { let val = tokens[*current] .value .clone() .parse::() .expect("could not parse int literal"); let out = Expression::Literal(Literal::IntLiteral(val)); *current += 1; out } else if tokens[*current].kind == TokenKind::FloatLiteral { let val = tokens[*current] .value .clone() .parse::() .expect("could not parse float literal"); let out = Expression::Literal(Literal::FloatLiteral(val)); *current += 1; out } else if tokens[*current].kind == TokenKind::BooleanLiteral { let mut val = false; if tokens[*current].value == "true" { val = true; } else if tokens[*current].value == "false" { val = false; } *current += 1; Expression::Literal(Literal::BooleanLiteral(val)) } else { Expression::Null } } pub type Program = Vec; #[derive(Debug, PartialEq)] pub enum Statement { FunctionCall { name: String, arguments: Vec, }, Nop, // Equivalent to a C nop statement. } #[derive(Debug, PartialEq)] pub enum Expression { Literal(Literal), Null, } #[derive(Debug, PartialEq)] pub enum Literal { StringLiteral(String), IntLiteral(i32), FloatLiteral(f32), BooleanLiteral(bool), }