use std::collections::{HashMap, HashSet}; use crate::ast::*; use crate::tokeniser::Keyword; use crate::tokeniser::Token; fn parse_math(tokens: &Vec) -> ValueNode { let mut prioritizing_order: HashMap> = HashMap::new(); prioritizing_order.insert(0, HashSet::from([Token::Plus, Token::Minus])); let mut ordered_binops: Vec = Vec::new(); let mut ordered_binops_indexes: Vec = Vec::new(); if tokens.len() == 1 { return match &tokens[0] { Token::Number(n) => ValueNode::Literal(Literal::Int(n.parse::().unwrap())), Token::Identifier(identifier) => ValueNode::Variable(identifier.to_owned()), _ => todo!(), }; } for j in prioritizing_order.keys() { let mut i = 0; let current_order_binops = prioritizing_order.get(j).unwrap(); while i < tokens.len() { for binop in current_order_binops { if &tokens[i] == binop { ordered_binops.push(binop.to_owned()); ordered_binops_indexes.push(i); } } i += 1; } } let binop = ordered_binops.pop().unwrap(); let binop_index = ordered_binops_indexes.pop().unwrap(); let mut a: Vec = Vec::new(); let mut b: Vec = Vec::new(); let mut i = 0; while i < tokens.len() { if i < binop_index { a.push(tokens[i].clone()); } if i > binop_index { b.push(tokens[i].clone()); } i += 1; } return match binop { Token::Plus => ValueNode::Operator(Operator::Add( Box::new(parse_math(&a)), Box::new(parse_math(&b)), )), Token::Minus => ValueNode::Operator(Operator::Sub( Box::new(parse_math(&a)), Box::new(parse_math(&b)), )), _ => todo!(), }; } fn parse_basic(tokens: &Vec, i: &mut usize) -> Expression { let literal = match &tokens[*i] { Token::Identifier(identifier) => Expression::Variable(identifier.to_owned()), Token::Number(number) => Expression::Literal(Literal::Int(number.parse::().unwrap())), _ => todo!(), }; *i += 1; literal } fn parse_grouping(tokens: &Vec, i: &mut usize) -> Expression { match &tokens[*i] { Token::OpenParanthesis => { *i += 1; } _ => todo!(), }; let inner_expression = parse_expression(tokens, i); match &tokens[*i] { Token::CloseParanthesis => {} _ => todo!(), }; inner_expression } // TODO: replace parse_math with this recursive function pub fn parse_expression(tokens: &Vec, i: &mut usize) -> Expression { #[derive(Debug)] enum OpExpr { Expression(Expression), BinOp(BinOp), Unary(Unary), } let mut in_expressions_and_operators: Vec = Vec::new(); loop { in_expressions_and_operators.push(match &tokens[*i] { Token::OpenParanthesis => OpExpr::Expression(parse_grouping(tokens, i)), Token::Plus => { *i += 1; OpExpr::BinOp(BinOp::Plus) } Token::Minus => { *i += 1; OpExpr::BinOp(BinOp::Minus) } Token::Ampersand => { *i += 1; OpExpr::Unary(Unary::ValueFrom) } Token::Star => { *i += 1; OpExpr::Unary(Unary::PointerTo) } Token::Number(_) => OpExpr::Expression(parse_basic(tokens, i)), _other => break, }); } dbg!(in_expressions_and_operators); Expression::Variable("a".to_string()) } fn parse_statements(tokens: &Vec, i: &mut usize) -> Vec { dbg!(&i); let mut statements = Vec::new(); while *i < tokens.len() { statements.push(match &tokens[*i] { Token::OpenSquiglyBracket => { *i += 1; let statements = parse_statements(tokens, i); Statement::Scope(statements) } Token::Keyword(Keyword::Let) => { *i += 1; let name = match tokens[*i].clone() { Token::Identifier(identifier) => identifier, _ => todo!(), }; *i += 1; match tokens[*i].clone() { Token::Equals => {} _ => todo!(), }; *i += 1; let mut declaration_tokens: Vec = Vec::new(); while tokens[*i] != Token::Semi { declaration_tokens.push(tokens[*i].clone()); *i += 1; } Statement::VariableDeclaration(name, parse_math(&declaration_tokens)) } Token::Keyword(Keyword::Assign) => { *i += 1; let name = match tokens[*i].clone() { Token::Identifier(identifier) => identifier, _ => todo!(), }; *i += 1; match tokens[*i].clone() { Token::Equals => {} _ => todo!(), }; *i += 1; let mut declaration_tokens: Vec = Vec::new(); while tokens[*i] != Token::Semi { declaration_tokens.push(tokens[*i].clone()); *i += 1; } Statement::VariableAssignment(name, parse_math(&declaration_tokens)) } Token::Identifier(identifier) => { *i += 1; let mut declaration_tokens: Vec> = Vec::new(); *i += 1; while tokens[*i] != Token::CloseParanthesis { let mut argument_tokens: Vec = Vec::new(); while tokens[*i] != Token::Comma { argument_tokens.push(tokens[*i].clone()); *i += 1; } declaration_tokens.push(argument_tokens); *i += 1; } *i += 1; let mut arguments: Vec = Vec::new(); for token_vec in &declaration_tokens { if token_vec == &Vec::new() { continue; } arguments.push(parse_math(token_vec)); } Statement::FunctionCall(identifier.to_owned(), arguments) } Token::CloseSquiglyBracket => { *i += 1; return statements; } Token::Semi => { *i += 1; continue; } _other => { dbg!(_other); dbg!(i); todo!() } }); } *i += 1; statements } pub fn parse_arguments(tokens: &Vec, i: &mut usize) -> Vec { let mut argument_variables = Vec::new(); while tokens[*i] != Token::OpenSquiglyBracket { match &tokens[*i] { Token::Identifier(identifier) => argument_variables.push(identifier.to_owned()), Token::OpenSquiglyBracket => {} _other => todo!(), } *i += 1; } argument_variables } pub fn ast(tokens: Vec) -> Vec { let mut functions: Vec = Vec::new(); let mut i = 0; while i < tokens.len() { match &tokens[i] { Token::Keyword(Keyword::Function) => { i += 1; let name = match &tokens[i] { Token::Identifier(identifier) => identifier, _ => todo!(), } .to_owned(); i += 1; let arguments = parse_arguments(&tokens, &mut i); i += 1; let statements = parse_statements(&tokens, &mut i); let statement = Statement::Scope(statements); functions.push(Function::new(name, arguments, statement)); } _other => { dbg!(&functions); dbg!(i); dbg!(_other); todo!(); } }; i += 1; } functions }