use crate::{lexer::{Token, TokenType}, Context}; use std::process; use crate::errors::{create_error, print_error, ErrorSubType, ErrorType}; #[derive(Debug, Clone, PartialEq)] pub enum ASTPart { String(AstString), Number(AstNumber), Boolean(AstBool), Null(AstNull), Assigment(AstAssigment), Operation(AstOperation), VarRead(AstVarRead), Call(AstCall), VarUpdate(AstVarUpdate), Function(AstFunction), If(AstIf), ElseIf(AstElseIf), Else(AstElse), While(AstWhile), Break(AstBreak), For(AstFor), Continue(AstContinue), Return(AstReturn), Table(AstTable), TableGet(AstTableGet), TableSet(AstTableSet), Import(AstImport), NOOP } #[derive(Debug, Clone, PartialEq)] pub struct AstString { pub value: String, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstNumber { pub value: f64, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstBool { pub value: bool, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstNull { pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstAssigment { pub variable: String, pub value: Box, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstOperation { pub operator: String, pub left: Box, pub right: Box, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstVarRead { pub variable: String, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstCall { pub function: Box, pub args: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstVarUpdate { pub variable: String, pub value: Box, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstFunction { pub args: Vec, pub body: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstIf { pub condition: Box, pub body: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstElseIf { pub condition: Box, pub body: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstElse { pub body: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstWhile { pub condition: Box, pub body: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstBreak { pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstFor { pub init: Box, pub condition: Box, pub update: Box, pub body: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstContinue { pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstReturn { pub value: Box, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstTable { pub values: Vec, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct TableValue { pub key: ASTPart, pub value: ASTPart, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstTableGet { pub table: Box, pub key: Box, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstTableSet { pub table: Box, pub key: Box, pub value: Box, pub pos: usize } #[derive(Debug, Clone, PartialEq)] pub struct AstImport { pub path: String, pub pos: usize } fn is_end(input: &Token, end: &Vec) -> bool { for token in end { if input.typ == token.typ && (token.value == "" || input.value == token.value) { return true; } } return false; } fn read_call(variable: ASTPart, pos: &mut usize, input: &Vec, ctx: &Context) -> ASTPart { let mut args: Vec = vec![]; *pos += 1; let start_pos = input[*pos-1].pos; while pos < &mut input.len() { let token = &input[*pos]; if token.typ == TokenType::SEPARATOR && token.value == "," { *pos += 1; continue; } if token.typ == TokenType::SEPARATOR && token.value == String::from(")") { *pos += 1; break; } let ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from(","), pos: 0 }, Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 } ]; let arg = read_exp(pos, input, &ends, &ends, ctx); args.push(arg); } return ASTPart::Call(AstCall { function: Box::new(variable), args: args, pos: start_pos }); } fn operator_precedence(op: &str) -> i64 { match op { "|" | "&" => 1, "==" | "!=" | "<=" | ">=" => 2, "+" | "-" => 3, "*" | "/" | "%" => 4, "^" => 5, _ => 0 } } fn shunt(input: Vec, ctx: &Context) -> 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::Boolean(_) => { output.push(part); }, ASTPart::Null(_) => { output.push(part); }, ASTPart::Function(_) => { output.push(part); }, ASTPart::Table(_) => { output.push(part); }, ASTPart::TableGet(_) => { output.push(part); }, ASTPart::Operation(op) => { if *op.left != ASTPart::NOOP && *op.right != ASTPart::NOOP { output.push(part); continue; } 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()); } let mut i = 0; while i < output.len() { match &output[i] { ASTPart::Operation(op) => { if *op.left != ASTPart::NOOP && *op.right != ASTPart::NOOP { i += 1; continue; } if op.operator == "!" { println!("{:?}", output); if i < 1 { let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation); print_error(&err, &ctx); process::exit(1); } let left = output[i-1].clone(); output[i] = ASTPart::Operation(AstOperation { operator: op.operator.clone(), left: Box::new(left), right: Box::new(ASTPart::NOOP), pos: op.pos, }); output.remove(i-1); } else { if i < 2 { let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation); print_error(&err, &ctx); process::exit(1); } let left = output[i-2].clone(); let right = output[i-1].clone(); output[i] = ASTPart::Operation(AstOperation { operator: op.operator.clone(), left: Box::new(left), right: Box::new(right), pos: op.pos, }); output.remove(i-2); output.remove(i-2); i -= 1; } } _ => { i += 1; } } } if output.len() == 0 { let err = create_error(&format!("No expressions found after applying order of operations"), 0, ErrorType::SemanticError, ErrorSubType::NoExpression); print_error(&err, &ctx); process::exit(1); } return output[0].clone(); } fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Context) -> ASTPart { let mut args: Vec = vec![]; let start_pos = input[*pos].pos; if with_args { if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "(" { let err = create_error(&format!("Expected `(`"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; while pos < &mut input.len() { let token = &input[*pos]; if token.typ == TokenType::SEPARATOR && token.value == ")" { break; } *pos += 1; if token.typ == TokenType::SEPARATOR && token.value == "," { continue; } if token.typ == TokenType::IDENTIFIER { args.push(token.value.clone()); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of arguments"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "{" { let err = create_error(&format!("Expected {{"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let op_ends: Vec = vec![ Token { typ: TokenType::OPEND, value: String::from("\n"), pos: 0 }, Token { typ: TokenType::OPEND, value: String::from(";"), pos: 0 }, Token { typ: TokenType::SEPARATOR, value: String::from("}"), pos: 0 } ]; let parse_ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from("}"), pos: 0 } ]; let body = parse_internal(input, &op_ends, &parse_ends, pos, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "}" { let err = create_error(&format!("Unexpected end of function"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; return ASTPart::Function(AstFunction { args: args, body: body, pos: start_pos }); } fn read_table(input: &Vec, pos: &mut usize, ctx: &Context) -> ASTPart { let start_pos = input[*pos].pos; let key_ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 }, ]; let ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from("}"), pos: 0 }, Token { typ: TokenType::SEPARATOR, value: String::from(","), pos: 0 }, Token { typ: TokenType::OPEND, value: String::from("\n"), pos: 0 }, ]; let mut tbl: Vec = vec![]; let mut key = 0; while *pos < input.len() { if input[*pos].typ == TokenType::OPEND && input[*pos].value == "\n" { *pos += 1; continue; } else if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "}" { *pos += 1; break; } if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "[" { *pos += 1; let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "=" { let err = create_error(&format!("Expected `=` after key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let value = read_exp(pos, input, &ends, &ends, ctx); tbl.push(TableValue { key: keyy, value: value, pos: input[*pos].pos }); } else { let value = read_exp(pos, input, &ends, &ends, ctx); tbl.push(TableValue { key: ASTPart::Number(AstNumber { value: key as f64, pos: 0 }), value: value, pos: input[*pos].pos }); key += 1; } if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "}" { *pos += 1; break; } else if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "," { *pos += 1; continue; } else if input[*pos].typ == TokenType::OPEND && input[*pos].value == "\n" { *pos += 1; continue; } else { let err = create_error(&format!("Unexpected end of table"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } } return ASTPart::Table(AstTable { values: tbl, pos: start_pos }); } fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: &Vec, ctx: &Context) -> ASTPart { let mut expressions: Vec = vec![]; while pos < &mut input.len() { let token = &input[*pos]; let mut next_token = &Token { typ: TokenType::OPEND, value: String::from("END"), pos: 0 }; if *pos+1 < input.len() { next_token = &input[*pos+1] } if is_end(token, &parse_ends) { break; } *pos += 1; if is_end(token, ends) { break; } if token.typ == TokenType::STRING { expressions.push(ASTPart::String(AstString { value: token.value.clone(), pos: token.pos })); } else if token.typ == TokenType::NUMBER { if expressions.len() == 1 { match &expressions[0] { ASTPart::Operation(op) => { if op.operator == "+" || op.operator == "-" { let mut nm = op.operator.clone(); nm.push_str(&token.value); expressions.push(ASTPart::Number(AstNumber { value: nm.parse().unwrap(), pos: token.pos })); expressions.remove(0); } else { expressions.push(ASTPart::Number(AstNumber { value: token.value.parse().unwrap(), pos: token.pos })); } }, _ => { expressions.push(ASTPart::Number(AstNumber { value: token.value.parse().unwrap(), pos: token.pos })); } } } else { expressions.push(ASTPart::Number(AstNumber { value: token.value.parse().unwrap(), pos: token.pos })); } } else if token.typ == TokenType::KEYWORD { if token.value == "piszv" { expressions.push(ASTPart::Boolean(AstBool { value: true, pos: token.pos })); } else if token.value == "nem piszv" { expressions.push(ASTPart::Boolean(AstBool { value: false, pos: token.pos })); } else if token.value == "nincs hám" { expressions.push(ASTPart::Null(AstNull { pos: token.pos })); } else if token.value == "lőcsve" { let func = read_function(input, pos, true, ctx); expressions.push(func); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } else if token.typ == TokenType::IDENTIFIER { if next_token.typ == TokenType::SEPARATOR && next_token.value == "(" { let var = ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos }); let cal = read_call(var, pos, input, ctx); expressions.push(check_continue(pos, input, cal, parse_ends, parse_ends, ctx)); } else if next_token.typ == TokenType::SEPARATOR && next_token.value == "[" { let var_pos = token.pos; let key_ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 } ]; *pos += 1; let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let gt = ASTPart::TableGet(AstTableGet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: var_pos })), key: Box::new(keyy), pos: var_pos+1 }); expressions.push(check_continue(pos, input, gt, parse_ends, parse_ends, ctx)); } else if next_token.typ == TokenType::SEPARATOR && next_token.value == "." { let var_pos = token.pos; *pos += 1; let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let gt = ASTPart::TableGet(AstTableGet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: var_pos })), key: Box::new(ASTPart::String(AstString { value: keyy.value.clone(), pos: keyy.pos })), pos: var_pos+1 }); expressions.push(check_continue(pos, input, gt, parse_ends, parse_ends, ctx)); } else { expressions.push(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos })); } } else if token.typ == TokenType::OPERATOR { expressions.push(ASTPart::Operation(AstOperation { operator: token.value.clone(), left: Box::new(ASTPart::NOOP), right: Box::new(ASTPart::NOOP), pos: token.pos })); } else if token.typ == TokenType::SEPARATOR { //We check for () and then send the into read_exp again, so we recursively parse the expression if token.value == "(" { let ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 } ]; let exp = read_exp(pos, input, &ends, &ends, ctx); if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == ")" { *pos += 1; } else { let err = create_error(&format!("Unclosed parenthesis"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Unclosed); print_error(&err, &ctx); process::exit(1); } expressions.push(exp); } else if token.value == "{" { let tbl = read_table(input, pos, ctx); expressions.push(tbl); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } let shunted = shunt(expressions, ctx); return shunted; } fn check_continue(pos: &mut usize, input: &Vec, prev: ASTPart, op_ends: &Vec, parse_ends: &Vec, ctx: &Context) -> ASTPart { let token = &input[*pos]; if is_end(token, &parse_ends) { return prev; } if is_end(token, &op_ends) { return prev; } if token.typ == TokenType::SEPARATOR && token.value == "(" { let cal = read_call(prev, pos, input, ctx); return check_continue(pos, input, cal, op_ends, parse_ends, ctx) } if token.typ == TokenType::SEPARATOR && token.value == "[" { let var_pos = token.pos; *pos += 1; let key_ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 } ]; let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let gt = ASTPart::TableGet(AstTableGet { table: Box::new(prev), key: Box::new(keyy), pos: var_pos+1 }); return check_continue(pos, input, gt, op_ends, parse_ends, ctx); } else if token.typ == TokenType::SEPARATOR && token.value == "." { let var_pos = token.pos; *pos += 1; let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let gt = ASTPart::TableGet(AstTableGet { table: Box::new(prev), key: Box::new(ASTPart::String(AstString { value: keyy.value.clone(), pos: keyy.pos })), pos: var_pos+1 }); return check_continue(pos, input, gt, op_ends, parse_ends, ctx); } return prev; } fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, parse_ends: &Vec, ctx: &Context) -> ASTPart { let token = &input[*pos]; let mut next_token = &Token { typ: TokenType::OPEND, value: String::from("END"), pos: 0 }; if *pos+1 < input.len() { next_token = &input[*pos+1] } if is_end(token, &parse_ends) { return ASTPart::NOOP; } *pos += 1; if is_end(token, &op_ends) { return ASTPart::NOOP; } if token.typ == TokenType::KEYWORD { if token.value == "gethelj" { let variable = &input[*pos]; *pos += 1; if variable.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Unexpected `{:?}`", variable.typ,), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } let eq = &input[*pos]; if eq.typ == TokenType::SEPARATOR && eq.value == "=" { *pos += 1; } let value = read_exp(pos, input, op_ends, parse_ends, ctx); return ASTPart::Assigment(AstAssigment { variable: variable.value.clone(), value: Box::new(value), pos: token.pos }); } else if token.value == "ha geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let condition_end = vec![ Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 } ]; let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let body = read_function(input, pos, false, ctx); let real_body = match body { ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } }; return ASTPart::If(AstIf { condition: Box::new(condition), body: real_body, pos: token.pos }); } else if token.value == "amíg geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let condition_end = vec![ Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 } ]; let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let body = read_function(input, pos, false, ctx); let real_body = match body { ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } }; return ASTPart::While(AstWhile { condition: Box::new(condition), body: real_body, pos: token.pos }); } else if token.value == "kraf" { return ASTPart::Break(AstBreak { pos: token.pos }); } else if token.value == "kopva" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let ends = vec![ Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 }, Token { typ: TokenType::OPEND, value: String::from(";"), pos: 0 } ]; let init = parse_internal(input, &ends, &ends, pos, ctx); if init.len() != 1 { let err = create_error(&format!("Only one expression is expected for init"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" { let err = create_error(&format!("Unexpected end of init"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let condition = read_exp(pos, input, &ends, &ends, ctx); if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let update = parse_internal(input, &ends, &ends, pos, ctx); if update.len() != 1 { let err = create_error(&format!("Only one expression is expected for update"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of update"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let body = read_function(input, pos, false, ctx); let real_body = match body { ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } }; return ASTPart::For(AstFor { init: Box::new(init[0].clone()), condition: Box::new(condition), update: Box::new(update[0].clone()), body: real_body, pos: token.pos }); } else if token.value == "szard le" { return ASTPart::Continue(AstContinue { pos: token.pos }); } else if token.value == "ha nem geny akkor geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let condition_end = vec![ Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 } ]; let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; let body = read_function(input, pos, false, ctx); let real_body = match body { ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } }; return ASTPart::ElseIf(AstElseIf { condition: Box::new(condition), body: real_body, pos: token.pos }); } else if token.value == "ha nem geny" { let body = read_function(input, pos, false, ctx); let real_body = match body { ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } }; return ASTPart::Else(AstElse { body: real_body, pos: token.pos }); } else if token.value == "reti" { if is_end(next_token, op_ends) || is_end(next_token, parse_ends) { return ASTPart::Return(AstReturn { value: Box::new(ASTPart::Null(AstNull { pos: token.pos })), pos: token.pos }); } else { let value = read_exp(pos, input, op_ends, parse_ends, ctx); return ASTPart::Return(AstReturn { value: Box::new(value), pos: token.pos }); } } else if token.value == "hámozd" { let var = &input[*pos]; *pos += 1; if var.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after hámozd"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } if input[*pos].typ != TokenType::KEYWORD || (input[*pos].value != "be" && input[*pos].value != "ba") { let err = create_error(&format!("Expected `be`/`ba` after hámozd"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let path = &input[*pos]; if path.typ != TokenType::STRING { let err = create_error(&format!("Expected string for hámozd"), path.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; return ASTPart::Assigment(AstAssigment { variable: var.value.clone(), value: Box::new(ASTPart::Import(AstImport { path: path.value.clone(), pos: token.pos })), pos: token.pos }); } else if token.value == "lőcsve" { if next_token.typ == TokenType::IDENTIFIER { *pos += 1; let func = read_function(input, pos, true, ctx); return ASTPart::Assigment(AstAssigment { variable: next_token.value.clone(), value: Box::new(func), pos: *pos - 1 }); } else { let func = read_function(input, pos, true, ctx); return check_continue(pos, input, func, op_ends, parse_ends, ctx); } } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } else if token.typ == TokenType::IDENTIFIER { if next_token.typ == TokenType::SEPARATOR && next_token.value == "(" { let var = ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos }); let cal = read_call(var, pos, input, ctx); return check_continue(pos, input, cal, op_ends, parse_ends, ctx) } else if next_token.typ == TokenType::SEPARATOR && next_token.value == "." { let var_pos = token.pos; *pos += 1; let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected); print_error(&err, &ctx); process::exit(1); } *pos += 1; let gt = ASTPart::TableGet(AstTableGet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: var_pos })), key: Box::new(ASTPart::String(AstString { value: keyy.value.clone(), pos: keyy.pos })), pos: var_pos+1 }); return check_continue(pos, input, gt, op_ends, parse_ends, ctx); } else if next_token.typ == TokenType::SEPARATOR && next_token.value == "[" { *pos += 1; let key_ends: Vec = vec![ Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 } ]; let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); print_error(&err, &ctx); process::exit(1); } *pos += 1; if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "=" { *pos += 1; let value = read_exp(pos, input, op_ends, parse_ends, ctx); return ASTPart::TableSet(AstTableSet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos })), key: Box::new(keyy), value: Box::new(value), pos: token.pos }); } else { let gt = ASTPart::TableGet(AstTableGet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos })), key: Box::new(keyy.clone()), pos: token.pos }); return check_continue(pos, input, gt, op_ends, parse_ends, ctx); } } else if next_token.typ == TokenType::SEPARATOR && next_token.value == "=" { *pos += 1; let value = read_exp(pos, input, op_ends, parse_ends, ctx); return ASTPart::VarUpdate(AstVarUpdate { variable: token.value.clone(), value: Box::new(value), pos: token.pos }); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); process::exit(1); } } fn parse_internal(input: &Vec, op_ends: &Vec, parse_ends: &Vec, pos: &mut usize, ctx: &Context) -> Vec { let mut out: Vec = vec![]; while *pos < input.len() { let op = next_operation(pos, &input, &op_ends, &parse_ends, ctx); match op { ASTPart::NOOP => {}, _ => { out.push(op); } } if is_end(&input[*pos], &parse_ends) { break; } } return out; } pub fn parse(input: Vec, ctx: &Context) -> Vec { let op_ends: Vec = vec![ Token { typ: TokenType::OPEND, value: String::from("\n"), pos: 0 }, Token { typ: TokenType::OPEND, value: String::from(";"), pos: 0 }, Token { typ: TokenType::OPEND, value: String::from("EOF"), pos: 0 } ]; let parse_ends: Vec = vec![ Token { typ: TokenType::OPEND, value: String::from("EOF"), pos: 0 } ]; let out = parse_internal(&input, &op_ends, &parse_ends, &mut 0, ctx); return out; }