From ae22ff77da66594a55a01997c103f48c685e5128 Mon Sep 17 00:00:00 2001 From: vanten Date: Sun, 24 Sep 2023 13:24:52 +0200 Subject: [PATCH] Better Expressions And Function Calling Syntax --- src/ast.rs | 48 ++++++------- src/main.rs | 23 ++----- src/parse.rs | 189 +++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 168 insertions(+), 92 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 5e3a328..5cc83c1 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -13,9 +13,9 @@ pub struct Function { #[derive(Debug, Clone)] pub enum Statement { - FunctionCall(String, Vec), - VariableDeclaration(String, ValueNode), - VariableAssignment(String, ValueNode), + FunctionCall(String, Vec), + VariableDeclaration(String, Expression), + VariableAssignment(String, Expression), Scope(Vec), } @@ -24,17 +24,16 @@ pub enum Expression { Literal(Literal), Variable(String), Unary(Unary, Box), - Grouping(Box), Binary(BinOp, Box, Box), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Unary { PointerTo, ValueFrom, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum BinOp { Plus, Minus, @@ -309,12 +308,14 @@ ROM-OUT FLAGS-IN 0x00 ; Add Mode } } -impl Node for ValueNode { +impl Node for Expression { fn to_assembly(&self, state: &mut AssemblerState) -> String { match self { - ValueNode::Literal(v) => v.to_assembly(state), - ValueNode::Operator(o) => o.to_assembly(state), - ValueNode::Variable(name) => { + Expression::Literal(v) => v.to_assembly(state), + Expression::Binary(o, expr_1, expr_2) => { + expr_1.to_assembly(state) + &expr_2.to_assembly(state) + &o.to_assembly(state) + } + Expression::Variable(name) => { if !state.variables.contains(name) { dbg!(&name); dbg!(&state.variables); @@ -355,6 +356,9 @@ C-OUT RAM-IN 0xFF " ) } + Expression::Unary(operator, expr) => { + expr.to_assembly(state) + &operator.to_assembly(state) + } } } } @@ -385,14 +389,12 @@ ROM-OUT RAM-IN {v}; Store literal value in RAM" } } -impl Node for Operator { +impl Node for BinOp { fn to_assembly(&self, state: &mut AssemblerState) -> String { match self { - Operator::Add(a, b) => { + BinOp::Plus => { let assembly = format!( - "{} -{} - + " SE-OUT RAM-ADDR-U-IN 0xFF ; Set ram address to stack end RAM-OUT C-IN 0xFF ; Output top address onto output register @@ -421,17 +423,13 @@ ALU-OUT SE-IN 0xFF ; Store ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address C-OUT RAM-IN 0xFF ; Store address after jump in ram ", - a.to_assembly(state), - b.to_assembly(state) ); state.variables.pop(); assembly } - Operator::Sub(a, b) => { + BinOp::Minus => { format!( - "{} -{} - + " SE-OUT RAM-ADDR-U-IN 0xFF ; Set ram address to stack end RAM-OUT C-IN 0xFF ; Output top address onto output register @@ -462,14 +460,18 @@ ALU-OUT SE-IN 0xFF ; Store ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address C-OUT RAM-IN 0xFF ; Store address after jump in ram ", - a.to_assembly(state), - b.to_assembly(state) ) } } } } +impl Node for Unary { + fn to_assembly(&self, state: &mut AssemblerState) -> String { + todo!() + } +} + pub fn to_assembly(functions: Vec) -> String { let mut final_product: String = "".to_owned(); let mut std_function_assembly = "".to_owned(); diff --git a/src/main.rs b/src/main.rs index 05e071e..6a7b6db 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,28 +1,17 @@ -use crate::tokeniser::Token; - mod ast; mod parse; mod tokeniser; fn main() { - // let filename: &str = &std::env::args().collect::>()[1]; + let filename: &str = &std::env::args().collect::>()[1]; - // let contents = std::fs::read_to_string(filename).expect(&format!("No file named {}", filename)); + let contents = std::fs::read_to_string(filename).expect(&format!("No file named {}", filename)); - // let tokens = tokeniser::tokenise(contents); + let tokens = tokeniser::tokenise(contents); - // let functions = dbg!(parse::ast(tokens)); + let functions = dbg!(parse::ast(tokens)); - // let assembly = ast::to_assembly(functions); + let assembly = ast::to_assembly(functions); - // println!("{}", assembly); - - let mut i: usize = 0; - let tokens: Vec = vec![ - Token::OpenParanthesis, - Token::Star, - Token::Number("2".to_string()), - Token::CloseParanthesis, - ]; - dbg!(parse::parse_expression(&tokens, &mut i)); + println!("{}", assembly); } diff --git a/src/parse.rs b/src/parse.rs index 0576345..7f8e335 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -70,30 +70,16 @@ 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!(), + _other => { + dbg!(&i); + dbg!(_other); + 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)] @@ -103,11 +89,17 @@ pub fn parse_expression(tokens: &Vec, i: &mut usize) -> Expression { Unary(Unary), } + let start_i = *i; 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::OpenParanthesis => { + *i += 1; + let expr = OpExpr::Expression(parse_expression(tokens, i)); + *i += 1; + expr + } Token::Plus => { *i += 1; OpExpr::BinOp(BinOp::Plus) @@ -124,12 +116,123 @@ pub fn parse_expression(tokens: &Vec, i: &mut usize) -> Expression { *i += 1; OpExpr::Unary(Unary::PointerTo) } - Token::Number(_) => OpExpr::Expression(parse_basic(tokens, i)), + Token::Number(_) => { + dbg!(OpExpr::Expression(parse_basic(tokens, i))) + } + Token::Identifier(_) => OpExpr::Expression(parse_basic(tokens, i)), _other => break, }); } - dbg!(in_expressions_and_operators); - Expression::Variable("a".to_string()) + + dbg!(&i); + dbg!(&in_expressions_and_operators); + + if in_expressions_and_operators.len() == 1 { + return match &in_expressions_and_operators.pop().unwrap() { + OpExpr::Expression(expression) => expression.to_owned(), + _ => { + todo!() + } + }; + } + + *i = start_i; + + let prioritizing_order_binops: Vec> = vec![vec![BinOp::Plus, BinOp::Minus]]; + + let prioritizing_order_unaryops: Vec> = + vec![vec![Unary::ValueFrom, Unary::PointerTo]]; + + let mut ordered_ops: Vec<(usize, bool)> = Vec::new(); + + for prioritizing_order in prioritizing_order_binops { + for j in (0..in_expressions_and_operators.len()).rev() { + let operator = match &in_expressions_and_operators[j] { + OpExpr::BinOp(binop) => binop, + _ => continue, + }; + + if prioritizing_order.contains(operator) { + ordered_ops.push((j, true)); + }; + } + } + + for prioritizing_order in prioritizing_order_unaryops { + for j in (0..in_expressions_and_operators.len()).rev() { + let operator = match &in_expressions_and_operators[j] { + OpExpr::Unary(unary) => unary, + _other => continue, + }; + + if prioritizing_order.contains(operator) { + ordered_ops.push((j, false)); + }; + } + } + + let this_operator = ordered_ops.get(0); + + let this_operator = match this_operator { + Some(val) => val.to_owned(), + None => return parse_basic(tokens, i), + }; + + dbg!(this_operator); + + match this_operator { + (index, true) => { + let mut start_vec = Vec::new(); + + for i in 0..(index + *i) { + start_vec.push(tokens[i].clone()); + } + + start_vec.push(Token::Semi); + dbg!(&start_vec); + + let start = parse_expression(&start_vec, i); + // let start = Expression::Literal(Literal::Int(42)); + + dbg!(&start); + + *i += 1; + + dbg!(&i); + let end = parse_expression(tokens, i); + + Expression::Binary( + match &in_expressions_and_operators[index] { + OpExpr::BinOp(binop) => binop.to_owned(), + _other => { + dbg!(start); + dbg!(end); + dbg!(_other); + todo!() + } + }, + Box::new(start), + Box::new(end), + ) + } + (index, false) => { + *i += 1; + + let end = parse_expression(tokens, i); + + Expression::Unary( + match &in_expressions_and_operators[index] { + OpExpr::Unary(unary) => unary.to_owned(), + _other => { + dbg!(end); + dbg!(_other); + todo!() + } + }, + Box::new(end), + ) + } + } } fn parse_statements(tokens: &Vec, i: &mut usize) -> Vec { @@ -156,13 +259,7 @@ fn parse_statements(tokens: &Vec, i: &mut usize) -> Vec { }; *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)) + Statement::VariableDeclaration(name, parse_expression(tokens, i)) } Token::Keyword(Keyword::Assign) => { *i += 1; @@ -179,39 +276,27 @@ fn parse_statements(tokens: &Vec, i: &mut usize) -> Vec { *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)) + Statement::VariableAssignment(name, parse_expression(tokens, i)) } Token::Identifier(identifier) => { *i += 1; - let mut declaration_tokens: Vec> = Vec::new(); + let mut arguments: 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; + if tokens[*i] == Token::CloseParanthesis { + break; + } + dbg!(&i); + dbg!(tokens); + dbg!(&tokens[*i]); + arguments.push(parse_expression(tokens, i)); } *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)); - } + dbg!(&arguments); Statement::FunctionCall(identifier.to_owned(), arguments) }