AstroLang/src/parser.rs

991 lines
No EOL
44 KiB
Rust

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),
TryCatch(AstTryCatch),
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<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstOperation {
pub operator: String,
pub left: Box<ASTPart>,
pub right: Box<ASTPart>,
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<ASTPart>,
pub args: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstVarUpdate {
pub variable: String,
pub value: Box<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstFunction {
pub args: Vec<String>,
pub body: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstIf {
pub condition: Box<ASTPart>,
pub body: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstElseIf {
pub condition: Box<ASTPart>,
pub body: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstElse {
pub body: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstWhile {
pub condition: Box<ASTPart>,
pub body: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstBreak {
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstFor {
pub init: Box<ASTPart>,
pub condition: Box<ASTPart>,
pub update: Box<ASTPart>,
pub body: Vec<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstContinue {
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstReturn {
pub value: Box<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstTable {
pub values: Vec<TableValue>,
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<ASTPart>,
pub key: Box<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstTableSet {
pub table: Box<ASTPart>,
pub key: Box<ASTPart>,
pub value: Box<ASTPart>,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstImport {
pub path: String,
pub pos: usize
}
#[derive(Debug, Clone, PartialEq)]
pub struct AstTryCatch {
pub try_block: AstFunction,
pub catch_block: AstFunction,
pub pos: usize
}
fn is_end(input: &Token, end: &Vec<Token>) -> 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<Token>, ctx: &Context) -> ASTPart {
let mut args: Vec<ASTPart> = 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<Token> = 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<ASTPart>, ctx: &Context) -> ASTPart {
let mut output: Vec<ASTPart> = vec![];
let mut stack: Vec<ASTPart> = vec![];
for part in input {
match &part {
ASTPart::String(_) => {
output.push(part);
},
ASTPart::Number(_) => {
output.push(part);
},
ASTPart::Call(_) => {
output.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, ctx);
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, ctx);
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, ctx);
print_error(&err, &ctx);
process::exit(1);
}
return output[0].clone();
}
fn read_function(input: &Vec<Token>, pos: &mut usize, with_args: bool, ctx: &Context) -> ASTPart {
let mut args: Vec<String> = 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, ctx);
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, ctx);
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, ctx);
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, ctx);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let op_ends: Vec<Token> = 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<Token> = 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, ctx);
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<Token>, pos: &mut usize, ctx: &Context) -> ASTPart {
let start_pos = input[*pos].pos;
let key_ends: Vec<Token> = vec![
Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 },
];
let ends: Vec<Token> = 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<TableValue> = 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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
print_error(&err, &ctx);
process::exit(1);
}
}
return ASTPart::Table(AstTable { values: tbl, pos: start_pos });
}
fn read_exp(pos: &mut usize, input: &Vec<Token>, ends: &Vec<Token>, parse_ends: &Vec<Token>, ctx: &Context) -> ASTPart {
let mut expressions: Vec<ASTPart> = 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, ctx);
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<Token> = 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, ctx);
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, ctx);
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, ctx);
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, ctx);
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<Token> = 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, ctx);
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, ctx);
print_error(&err, &ctx);
process::exit(1);
}
} else {
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx);
print_error(&err, &ctx);
process::exit(1);
}
}
let shunted = shunt(expressions, ctx);
return shunted;
}
fn check_continue(pos: &mut usize, input: &Vec<Token>, prev: ASTPart, op_ends: &Vec<Token>, parse_ends: &Vec<Token>, 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<Token> = 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, ctx);
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, ctx);
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, ctx);
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, ctx);
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<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Token>, 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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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, ctx);
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 if token.value == "piszolj" {
let func = read_function(input, pos, false, ctx);
let tryp = match func {
ASTPart::Function(f) => f,
_ => {
let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx);
print_error(&err, &ctx);
process::exit(1);
}
};
if input[*pos].typ != TokenType::KEYWORD || input[*pos].value != "csecs" {
let err = create_error(&format!("Expected `csecs` after piszolj"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let func2 = read_function(input, pos, true, ctx);
let catchp = match func2 {
ASTPart::Function(f) => f,
_ => {
let err = create_error(&format!("Expected function body"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx);
print_error(&err, &ctx);
process::exit(1);
}
};
return ASTPart::TryCatch(AstTryCatch { try_block: tryp, catch_block: catchp, pos: token.pos });
} else {
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx);
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, ctx);
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<Token> = 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, ctx);
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, ctx);
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, ctx);
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, ctx);
print_error(&err, &ctx);
process::exit(1);
}
} else {
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx);
print_error(&err, &ctx);
process::exit(1);
}
}
fn parse_internal(input: &Vec<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Token>, pos: &mut usize, ctx: &Context) -> Vec<ASTPart> {
let mut out: Vec<ASTPart> = 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<Token>, ctx: &Context) -> Vec<ASTPart> {
let op_ends: Vec<Token> = 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<Token> = 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;
}