diff --git a/src/parser.rs b/src/parser.rs index 51f3358..7b3ce17 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,6 @@ use crate::lexer::{Token, TokenType}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ASTPart { String(AstString), Number(AstNumber), @@ -10,35 +10,35 @@ pub enum ASTPart { Call(AstCall), NOOP } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstString { pub value: String, pub pos: usize } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstNumber { pub value: i64, pub pos: usize } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstAssigment { pub variable: String, pub value: Box, pub pos: usize } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstOperation { pub operator: String, pub left: Box, pub right: Box, pub pos: usize } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstVarRead { pub variable: String, pub pos: usize } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstCall { pub function: Box, pub args: Vec, @@ -57,7 +57,7 @@ fn is_end(input: &Token, end: &Vec) -> bool { fn read_call(variable: ASTPart, pos: &mut usize, input: &Vec) -> ASTPart { let mut args: Vec = vec![]; *pos += 1; - let start_pos = *pos; + let start_pos = input[*pos-1].pos; while pos < &mut input.len() { let token = &input[*pos]; if token.typ == TokenType::SEPARATOR && token.value == "," { @@ -78,11 +78,76 @@ fn read_call(variable: ASTPart, pos: &mut usize, input: &Vec) -> ASTPart return ASTPart::Call(AstCall { function: Box::new(variable), args: args, pos: start_pos }); } -fn shunt(input: Vec) -> ASTPart { - for part in input { - +fn operator_precedence(op: &str) -> i64 { + match op { + "|" | "&" => 1, + "+" | "-" => 2, + "*" | "/" | "%" => 3, + "^" => 4, + _ => 0 } - return ASTPart::NOOP; +} + +fn shunt(input: Vec) -> ASTPart { + let mut output: Vec = vec![]; + let mut stack: Vec = vec![]; + for part in input { + match &part { + ASTPart::String(_) => { + output.push(part); + }, + ASTPart::Number(_) => { + output.push(part); + }, + ASTPart::Call(_) => { + stack.push(part); + }, + ASTPart::VarRead(_) => { + output.push(part); + }, + ASTPart::Operation(op) => { + while stack.len() > 0 { + let top = &stack[stack.len()-1]; + match top { + ASTPart::Operation(top_op) => { + if operator_precedence(&top_op.operator) >= operator_precedence(&op.operator) { + output.push(stack.pop().unwrap()); + } else { + break; + } + }, + _ => break + } + } + stack.push(part); + }, + _ => {} + } + } + while stack.len() > 0 { + output.push(stack.pop().unwrap()); + } + for i in 0..output.len() { + match &output[i] { + ASTPart::Operation(op) => { + if i < 2 { + panic!("Unexpected operation at {}", op.pos); + } + let left = &output[i-2]; + let right = &output[i-1]; + output[i] = ASTPart::Operation(AstOperation { + operator: op.operator.clone(), + left: Box::new(left.clone()), + right: Box::new(right.clone()), + pos: op.pos + }); + output.remove(i-2); + output.remove(i-2); + }, + _ => {} + } + } + return output[0].clone(); } fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: &Vec) -> ASTPart { let mut expressions: Vec = vec![]; @@ -120,9 +185,8 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos); } } - println!("{:?}", expressions); let shunted = shunt(expressions); - return ASTPart::NOOP; + return shunted; } fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, parse_ends: &Vec) -> ASTPart { diff --git a/test.as b/test.as index 858b213..d41d1d4 100644 --- a/test.as +++ b/test.as @@ -1,2 +1,3 @@ gethelj a = 1 -gethelj b = a + 2 \ No newline at end of file +gethelj b = a + (2+2) +gethelj c = ugass(a,b) \ No newline at end of file