use crate::{ ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, name, unexpected_token }; pub struct Parser { input: Vec, text: Vec, current: usize, token: Token, pub errors: Vec, } impl Parser { pub fn new(text: String, input: Vec) -> Self { Self { input: input.clone(), text: text.lines().collect::>().iter().map(|s| s.to_string()).collect(), current: 0, token: input[0].clone(), errors: Vec::new(), } } pub fn program(&mut self) -> AST { let mut program = Vec::new(); loop { if self.current >= self.input.len() { break; } match self.statement() { Ok(ast) => program.push(ast), Err(e) => self.errors.push(e), } } AST { ast_type: ASTType::Program(program), start_line: 0, end_line: 0, start_column: 0, end_column: 0, } } pub fn statement(&mut self) -> Result { match self.peek()?.token_type { TokenType::Function => self.function_statement(), TokenType::Return => self.return_statement(), TokenType::Loop => self.loop_statement(), TokenType::While => self.while_statement(), TokenType::For => self.for_statement(), TokenType::Break => self.break_statement(), TokenType::Continue => self.continue_statement(), TokenType::If => self.if_statement(), TokenType::LeftBrace => self.block(), TokenType::Print => self.print_statement(), // REMOVE LATER _ => self.expression_statement(), } } pub fn function_statement(&mut self) -> Result { let function_ident = self.read_token()?; let ident = self.read_token()?; if let TokenType::Ident(name) = ident.token_type { let left_paren = self.read_token()?; if let TokenType::LeftParen = left_paren.token_type { let mut expressions = Vec::new(); while self.peek()?.token_type != TokenType::RightParen { let ident = self.read_token()?; if let TokenType::Ident(name) = ident.token_type { expressions.push(name!(name, ident)); } else { return Err(unexpected_token!(self, "Expected identifier found {}", ident)); } if let TokenType::Comma = self.peek()?.token_type { self.read_token()?; } } let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; return Ok(ast_from_token_ast!( ASTType::Function( name!(name, ident), expressions, Box::new(block.clone()) ), function_ident, block )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } } else { return Err(unexpected_token!(self, "Expected ( found {}", left_paren)); } } else { return Err(unexpected_token!( self, "Expected identifier found {}", ident )); } } pub fn return_statement(&mut self) -> Result { let return_ident = self.read_token()?; if let TokenType::Semicolon = self.peek()?.token_type { let semicolon = self.read_token()?; return Ok(ast_from_token!( ASTType::Return(Box::new(None)), return_ident, semicolon )); } let expression = self.expression()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { Ok(ast_from_token!( ASTType::Return(Box::new(Some(expression))), return_ident, semicolon )) } else { return Err(unexpected_token!(self, "Expected ; found {}", semicolon)); } } pub fn loop_statement(&mut self) -> Result { let loop_ident = self.read_token()?; let block = self.block()?; Ok(ast_from_token_ast!( ASTType::Loop(Box::new(block.clone())), loop_ident, block )) } pub fn while_statement(&mut self) -> Result { let while_ident = self.read_token()?; let left_paren = self.read_token()?; if let TokenType::LeftParen = left_paren.token_type { let condition = self.expression()?; let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; return Ok(ast_from_token_ast!( ASTType::While(Box::new(condition), Box::new(block.clone())), while_ident, block )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } } else { return Err(unexpected_token!(self, "Expected ( found {}", left_paren)); } } pub fn for_statement(&mut self) -> Result { let for_ident = self.read_token()?; let left_paren = self.read_token()?; if let TokenType::LeftParen = left_paren.token_type { let expression1; if let TokenType::Semicolon = self.peek()?.token_type { expression1 = None; } else { expression1 = Some(self.expression()?); } let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { let expression2; if let TokenType::Semicolon = self.peek()?.token_type { expression2 = None; } else { expression2 = Some(self.expression()?); } let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { let expression3; if let TokenType::RightParen = self.peek()?.token_type { expression3 = None; } else { expression3 = Some(self.expression()?); } let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; return Ok(ast_from_token_ast!( ASTType::For( Box::new(expression1), Box::new(expression2), Box::new(expression3), Box::new(block.clone()) ), for_ident, block )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } } else { return Err(unexpected_token!(self, "Expected ; found {}", semicolon)); } } else { return Err(unexpected_token!(self, "Expected ; found {}", semicolon)); } } else { return Err(unexpected_token!(self, "Expected ( found {}", left_paren)); } } pub fn break_statement(&mut self) -> Result { let break_ident = self.read_token()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { Ok(ast_from_token!(ASTType::Break, break_ident, semicolon)) } else { Err(unexpected_token!(self, "Expected ; found {}", semicolon)) } } pub fn continue_statement(&mut self) -> Result { let continue_ident = self.read_token()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { Ok(ast_from_token!(ASTType::Continue, continue_ident, semicolon)) } else { Err(unexpected_token!(self, "Expected ; found {}", semicolon)) } } pub fn if_statement(&mut self) -> Result { let if_ident = self.read_token()?; let left_paren = self.read_token()?; if let TokenType::LeftParen = left_paren.token_type { let condition = self.expression()?; let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; if self.current < self.input.len() { let else_ident = self.peek()?; if let TokenType::Else = else_ident.token_type { self.read_token()?; if let TokenType::LeftBrace = self.peek()?.token_type { let else_block = self.block()?; return Ok(ast_from_token_ast!( ASTType::If( Box::new(condition), Box::new(block.clone()), Box::new(Some(else_block.clone())) ), if_ident, else_block )); } let else_if_ident = self.peek()?; if let TokenType::If = else_if_ident.token_type { let else_if = self.if_statement()?; return Ok(ast_from_token_ast!( ASTType::If( Box::new(condition), Box::new(block.clone()), Box::new(Some(else_if.clone())) ), if_ident, else_if )); } return Err(unexpected_token!(self, "Unexpected token {}", else_ident)); } } return Ok(ast_from_token_ast!( ASTType::If(Box::new(condition), Box::new(block.clone()), Box::new(None)), if_ident, block )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } } else { return Err(unexpected_token!(self, "Expected ( found {}", left_paren)); } } pub fn block(&mut self) -> Result { let left_brace = self.read_token()?; if let TokenType::LeftBrace = left_brace.token_type { let mut stmts = Vec::new(); while self.peek()?.token_type != TokenType::RightBrace { stmts.push(self.statement()?); } let right_brace = self.read_token()?; return Ok(ast_from_token!(ASTType::Block(stmts), left_brace, right_brace)); } else { return Err(unexpected_token!(self, "Expected {{ found {}", left_brace)); } } // REMOVE LATER pub fn print_statement(&mut self) -> Result { let print_ident = self.read_token()?; let expression = self.expression()?; let semicolon = self.read_token()?; if matches!(semicolon.token_type, TokenType::Semicolon) { Ok(ast_from_token!(ASTType::Print(Box::new(expression)), print_ident, semicolon)) } else { Err(unexpected_token!(self, "Expected ; found {}", semicolon)) } } pub fn expression_statement(&mut self) -> Result { let expression = self.expression()?; if self.current >= self.input.len() { let last = self.input.last().unwrap(); return Err(KabelError::new( ErrorKind::UnexpectedEof, "Unexpected end of file, expected ;".to_string(), expression.start_line, last.end_column, self.text[last.line].to_string(), )); } let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { return Ok(ast_from_ast_token!(ASTType::Expr(Box::new(expression.clone())), expression, semicolon)); } else { self.current -= 1; return Err(unexpected_token!(self, "Expected ; found {}", semicolon)); } } pub fn expression(&mut self) -> Result { if let TokenType::Var = self.peek()?.token_type { return self.declaration(); } let assignment = self.assignment()?; Ok(assignment) } pub fn declaration(&mut self) -> Result { let var = self.read_token()?; let ident = self.read_token()?; if let TokenType::Ident(name) = ident.token_type { let equal = self.read_token()?; if let TokenType::Equal = equal.token_type { let expr = self.expression()?; return Ok(ast_from_token_ast!( ASTType::Decl(name!(name, ident), Box::new(expr.clone())), var, expr )); } else { return Err(unexpected_token!(self, "Expected = found {}", equal)); } } else { return Err(unexpected_token!( self, "Expected identifier found {}", ident )); } } pub fn assignment(&mut self) -> Result { if let TokenType::Ident(name) = self.peek()?.token_type { let ident = self.read_token()?; if self.current >= self.input.len() { self.current -= 1; return self.logical_or(); } if let TokenType::Equal | TokenType::PlusEqual | TokenType::MinusEqual | TokenType::StarEqual | TokenType::SlashEqual | TokenType::PercentEqual | TokenType::AndEqual | TokenType::CaretEqual | TokenType::OrEqual = self.peek()?.token_type { let binop = self.read_token()?; let expr = self.expression()?; if binop.token_type == TokenType::Equal { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name, ident), Box::new(expr.clone()) ), ident, expr )); } else if binop.token_type == TokenType::PlusEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Add, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else if binop.token_type == TokenType::MinusEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Sub, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else if binop.token_type == TokenType::StarEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Mul, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else if binop.token_type == TokenType::SlashEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name.clone(), ident)), BinOp::Div, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else if binop.token_type == TokenType::PercentEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Mod, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else if binop.token_type == TokenType::AndEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::BitAnd, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else if binop.token_type == TokenType::CaretEqual { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::BitXor, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } else { return Ok(ast_from_token_ast!( ASTType::Assign( name!(name.clone(), ident), Box::new( ast_from_ast!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::BitOr, Box::new(expr.clone()) ), expr, expr ) .clone() ) ), ident, expr )); } } self.current -= 1; return self.ternary(); } return self.ternary(); } pub fn ternary(&mut self) -> Result { let condition = self.logical_or()?; if let TokenType::Question = self.peek()?.token_type { self.read_token()?; let true_expr = self.expression()?; if let TokenType::Colon = self.peek()?.token_type { self.read_token()?; let false_expr = self.expression()?; return Ok(ast_from_ast!( ASTType::Ternary( Box::new(condition.clone()), Box::new(true_expr), Box::new(false_expr.clone()) ), condition, false_expr )); } else { return Err(unexpected_token!(self, "Expected : found {}", self.token)); } } Ok(condition) } pub fn logical_or(&mut self) -> Result { let mut left = self.logical_and()?; while self.current < self.input.len() && self.peek()?.token_type == TokenType::OrOr { self.read_token()?; let right = self.logical_and()?; left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Or, Box::new(right.clone())), left, right ); } Ok(left) } pub fn logical_and(&mut self) -> Result { let mut left = self.bit_and()?; while self.current < self.input.len() && self.peek()?.token_type == TokenType::AndAnd { self.read_token()?; let right = self.bit_and()?; left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::And, Box::new(right.clone())), left, right ); } Ok(left) } pub fn bit_and(&mut self) -> Result { let mut left = self.bit_xor()?; while self.current < self.input.len() && self.peek()?.token_type == TokenType::And { self.read_token()?; let right = self.bit_xor()?; left = ast_from_ast!( ASTType::Binary( Box::new(left.clone()), BinOp::BitAnd, Box::new(right.clone()) ), left, right ); } Ok(left) } pub fn bit_xor(&mut self) -> Result { let mut left = self.bit_or()?; while self.current < self.input.len() && self.peek()?.token_type == TokenType::Caret { self.read_token()?; let right = self.bit_or()?; left = ast_from_ast!( ASTType::Binary( Box::new(left.clone()), BinOp::BitXor, Box::new(right.clone()) ), left, right ); } Ok(left) } pub fn bit_or(&mut self) -> Result { let mut left = self.equality()?; while self.current < self.input.len() && self.peek()?.token_type == TokenType::Or { self.read_token()?; let right = self.equality()?; left = ast_from_ast!( ASTType::Binary( Box::new(left.clone()), BinOp::BitOr, Box::new(right.clone()) ), left, right ); } Ok(left) } pub fn equality(&mut self) -> Result { let mut left = self.comparison()?; while self.current < self.input.len() && (self.peek()?.token_type == TokenType::EqualEqual || self.peek()?.token_type == TokenType::BangEqual) { let binop = self.read_token()?; let right = self.comparison()?; if binop.token_type == TokenType::EqualEqual { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Eq, Box::new(right.clone())), left, right ); } else { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Ne, Box::new(right.clone())), left, right ); } } Ok(left) } pub fn comparison(&mut self) -> Result { let mut left = self.term()?; while self.current < self.input.len() && (self.peek()?.token_type == TokenType::Less || self.peek()?.token_type == TokenType::LessEqual || self.peek()?.token_type == TokenType::Greater || self.peek()?.token_type == TokenType::GreaterEqual) { let binop = self.read_token()?; let right = self.term()?; if binop.token_type == TokenType::Less { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Ls, Box::new(right.clone())), left, right ); } else if binop.token_type == TokenType::LessEqual { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Le, Box::new(right.clone())), left, right ); } else if binop.token_type == TokenType::Greater { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Gr, Box::new(right.clone())), left, right ); } else { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Ge, Box::new(right.clone())), left, right ); } } Ok(left) } pub fn term(&mut self) -> Result { let mut left = self.factor()?; while self.current < self.input.len() && (self.peek()?.token_type == TokenType::Plus || self.peek()?.token_type == TokenType::Minus) { let binop = self.read_token()?; let right = self.factor()?; if binop.token_type == TokenType::Plus { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Add, Box::new(right.clone())), left, right ); } else { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Sub, Box::new(right.clone())), left, right ); } } Ok(left) } pub fn factor(&mut self) -> Result { let mut left = self.unary()?; while self.current < self.input.len() && (self.peek()?.token_type == TokenType::Star || self.peek()?.token_type == TokenType::Slash || self.peek()?.token_type == TokenType::Percent) { let binop = self.read_token()?; let right = self.unary()?; if binop.token_type == TokenType::Star { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Mul, Box::new(right.clone())), left, right ); } else if binop.token_type == TokenType::Slash { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Div, Box::new(right.clone())), left, right ); } else { left = ast_from_ast!( ASTType::Binary(Box::new(left.clone()), BinOp::Mod, Box::new(right.clone())), left, right ); } } Ok(left) } pub fn unary(&mut self) -> Result { if let TokenType::Bang | TokenType::Minus = self.peek()?.token_type { let token = self.read_token()?; let unary = self.unary()?; if token.token_type == TokenType::Bang { return Ok(ast_from_token_ast!( ASTType::Unary(UnOp::Not, Box::new(unary.clone())), token, unary )); } else { return Ok(ast_from_token_ast!( ASTType::Unary(UnOp::Neg, Box::new(unary.clone())), token, unary )); } } self.subscript() } pub fn subscript(&mut self) -> Result { let mut primary = self.primary()?; while self.current < self.input.len() && self.peek()?.token_type == TokenType::LeftSquare { self.read_token()?; let expr = self.expression()?; let right_brace = self.read_token()?; if let TokenType::RightSquare = right_brace.token_type { primary = ast_from_ast_token!( ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)), primary, right_brace ); } else { return Err(unexpected_token!(self, "Expected ] found {}", right_brace)); } } Ok(primary) } pub fn primary(&mut self) -> Result { let token = self.read_token()?; match token.token_type { TokenType::Ident(ref ident) => { if self.current < self.input.len() { if let TokenType::LeftParen = self.peek()?.token_type { return self.call(token); } if let TokenType::Period = self.peek()?.token_type { return self.member(token); } if let TokenType::PlusPlus | TokenType::MinusMinus = self.peek()?.token_type { return self.incdec(token); } } return Ok(lit!(Ident, ident.clone(), token)); } TokenType::Num(num) => { return Ok(lit!(Num, num, token)); } TokenType::Str(string) => { return Ok(lit!(Str, string, token)); } TokenType::True => return Ok(lit!(Bool, true, token)), TokenType::False => return Ok(lit!(Bool, false, token)), TokenType::LeftParen => { return self.group(token); } TokenType::LeftSquare => { return self.array(token); } _ => { return Err(unexpected_token!(self, "Unexpected token {}", token)); } } } pub fn array(&mut self, left_square: Token) -> Result { let mut expressions = Vec::new(); while self.peek()?.token_type != TokenType::RightSquare { expressions.push(self.expression()?); if let TokenType::Comma = self.peek()?.token_type { self.read_token()?; } } let right_square = self.read_token()?; Ok(ast_from_token!( ASTType::Lit(Lit::Array(expressions)), left_square, right_square )) } pub fn member(&mut self, ident: Token) -> Result { if let TokenType::Ident(first) = ident.token_type { let mut expr: AST = lit!(Ident, first, ident); while self.peek()?.token_type == TokenType::Period { self.read_token()?; let child = self.read_token()?; if let TokenType::Ident(child_str) = child.clone().token_type { if self.current < self.input.len() { if let TokenType::LeftParen = self.peek()?.token_type { let call = self.call(child)?; expr = ast_from_ast!( ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())), expr, call ); if self.current >= self.input.len() { break; } continue; } } expr = ast_from_ast_token!( ASTType::Member( Box::new(expr.clone()), Box::new(lit!(Ident, child_str, child)) ), expr, child ); } else { return Err(unexpected_token!(self, "Unexpected token {}", child)); } if self.current >= self.input.len() { break; } } return Ok(expr); } panic!("Bad member logic"); } pub fn call(&mut self, ident: Token) -> Result { self.read_token()?; let mut expressions = Vec::new(); while self.peek()?.token_type != TokenType::RightParen { expressions.push(self.expression()?); if let TokenType::Comma = self.peek()?.token_type { self.read_token()?; } } let right_paren = self.read_token()?; if let TokenType::Ident(name) = ident.token_type { return Ok(ast_from_token!( ASTType::Call(name!(name, ident), expressions), ident, right_paren )); } panic!("Call logic broke"); } pub fn incdec(&mut self, ident: Token) -> Result { if let TokenType::Ident(name) = ident.token_type { let oper = self.read_token()?; if oper.token_type == TokenType::PlusPlus { return Ok(ast_from_token!( ASTType::Assign( name!(name.clone(), ident), Box::new(ast_from_token!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Add, Box::new(lit!(Num, 1., oper)) ), oper, oper )) ), ident, oper )); } else { return Ok(ast_from_token!( ASTType::Assign( name!(name.clone(), ident), Box::new(ast_from_token!( ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Sub, Box::new(lit!(Num, 1., oper)) ), oper, oper )) ), ident, oper )); } } panic!("Inc/dec logic broke"); } pub fn group(&mut self, left_paren: Token) -> Result { let expr = self.expression()?; let right_paren = self.peek(); if let Ok(right_paren) = right_paren { if right_paren.token_type != TokenType::RightParen { return Err(KabelError::new( ErrorKind::MissingDelimiter, "Missing right parenthesis".to_string(), right_paren.line, right_paren.start_column, self.text[left_paren.line..right_paren.line].iter().fold("".to_string(), |acc, string| acc + string + "\n"), )); } self.read_token()?; return Ok(ast_from_token!( expr.ast_type, left_paren, right_paren )); } if let Err(e) = right_paren { return Err(KabelError::new( ErrorKind::MissingDelimiter, "Missing right parenthesis".to_string(), e.line, e.column, collect_lines!(self.text[left_paren.line..expr.end_line]), )); } unreachable!(); } pub fn read_token(&mut self) -> Result { if self.current >= self.input.len() { let last_token = self.input[self.input.len() - 1].clone(); return Err(KabelError::new( ErrorKind::UnexpectedEof, "Unexpected end of file".to_string(), last_token.line, last_token.start_column, self.text[last_token.line].clone(), )); } self.token = self.input[self.current].clone(); self.current += 1; return Ok(self.token.clone()); } pub fn peek(&mut self) -> Result { if self.current >= self.input.len() { let last_token = self.input[self.input.len() - 1].clone(); return Err(KabelError::new( ErrorKind::UnexpectedEof, "Unexpected end of file".to_string(), last_token.line, last_token.start_column, self.text[last_token.line].clone(), )); } return Ok(self.input[self.current].clone()); } } #[derive(Debug, Clone)] pub struct AST { pub ast_type: ASTType, pub start_line: usize, pub end_line: usize, pub start_column: usize, pub end_column: usize, } #[derive(Debug, Clone)] pub enum ASTType { Program(Vec), // statements Function(Name, Vec, Box), // name, args, block Return(Box>), // expression Loop(Box), // block While(Box, Box), // condition, block For( Box>, Box>, Box>, Box, ), // expr1, expr2, expr3, block Break, Continue, If(Box, Box, Box>), // condition, block, else/else if Block(Vec), // statements Expr(Box), // expr // REMOVE LATER Print(Box), // expressions Decl(Name, Box), // identifier, expression Assign(Name, Box), Ternary(Box, Box, Box), Subscript(Box, Box), Binary(Box, BinOp, Box), Unary(UnOp, Box), // primary Lit(Lit), Call(Name, Vec), Member(Box, Box), } #[derive(Debug, Clone)] pub struct Name { pub name: String, pub start_column: usize, pub end_column: usize, pub line: usize, } #[derive(Debug, Clone)] pub enum Lit { Ident(String), Num(f32), Str(String), Bool(bool), Array(Vec), } #[derive(Debug, Clone, Copy)] pub enum BinOp { Add, Sub, Mul, Div, Mod, BitAnd, BitXor, BitOr, Eq, Ne, Gr, Ge, Ls, Le, Or, And, } #[derive(Debug, Clone, Copy)] pub enum UnOp { Not, Neg, }