diff --git a/src/lexer.rs b/src/lexer.rs index 5c7295b..cf63953 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -5,7 +5,8 @@ pub enum TokenType { IDENTIFIER, OPERATOR, KEYWORD, - SEPARATOR + SEPARATOR, + OPEND } #[derive(Debug)] pub struct Token { @@ -14,6 +15,10 @@ pub struct Token { pub pos: usize, } +fn is_opend(char: &str) -> bool { + let chars = vec![";","\n"]; + return chars.contains(&char); +} fn is_ignored(char: &str) -> bool { let chars = vec![""," ","\n","\r","\t"]; return chars.contains(&char); @@ -194,6 +199,10 @@ pub fn lex(input: String) -> Vec { while pos < splitted.len() { let char = splitted[pos]; pos += 1; + if is_opend(char) { + out.push(Token { typ: TokenType::OPEND, value: String::from(char), pos: pos-1 }); + continue; + } if is_ignored(char) { continue; } @@ -224,5 +233,6 @@ pub fn lex(input: String) -> Vec { read_identifier(&splitted, &mut pos, &mut out); } } + out.push(Token { typ: TokenType::OPEND, value: String::from("EOF"), pos: pos-1 }); return out; } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 000f313..9d3215d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,29 @@ use std::fs; +use parser::ASTPart; + mod lexer; +mod parser; + +fn log_ast_part(part: &ASTPart, prefix: String) { + match part { + ASTPart::Number(number) => println!("{}{}: Number: {}", prefix, number.pos, number.value), + ASTPart::Assigment(assigment) => { + println!("{}{}: Assigment: {}", prefix, assigment.pos, assigment.variable); + println!("{} Value:", prefix); + log_ast_part(&assigment.value, format!("{} ", prefix)); + }, + ASTPart::Operation(operation) => { + println!("{}{}: Operation: {}", prefix, operation.pos, operation.operator); + println!("{} Left:", prefix); + log_ast_part(&operation.left, format!("{} ", prefix)); + println!("{} Right:", prefix); + log_ast_part(&operation.right, format!("{} ", prefix)); + }, + ASTPart::VarRead(var_read) => println!("{}{}: Variable Read: {}", prefix, var_read.pos, var_read.variable), + _ => {} + } +} fn main() { let inp = fs::read_to_string("./test.as"); @@ -8,9 +31,14 @@ fn main() { Result::Ok(data) => { let lexed = lexer::lex(data); println!("Lexer output: "); - for token in lexed { + for token in &lexed { println!(" {}: {:?}: {}", token.pos, token.typ, token.value); } + let ast = parser::parse(lexed); + println!("AST: "); + for part in &ast { + log_ast_part(part, String::from(" ")); + } }, Result::Err(err) => { panic!("Error while reading file: {}", err) diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..0332a22 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,91 @@ +use crate::lexer::{Token, TokenType}; + +pub enum ASTPart { + Number(AstNumber), + Assigment(AstAssigment), + Operation(AstOperation), + VarRead(AstVarRead), + NOOP +} +pub struct AstNumber { + pub value: i64, + pub pos: usize +} +pub struct AstAssigment { + pub variable: String, + pub value: Box, + pub pos: usize +} +pub struct AstOperation { + pub operator: String, + pub left: Box, + pub right: Box, + pub pos: usize +} +pub struct AstVarRead { + pub variable: 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 next_operation(pos: &mut usize, input: &Vec, prev: ASTPart, op_ends: &Vec, parse_ends: &Vec) -> ASTPart { + let token = &input[*pos]; + if is_end(token, &parse_ends) { + return prev; + } + *pos += 1; + if is_end(token, &op_ends) { + return prev; + } + if token.typ == TokenType::KEYWORD && token.value == "gethelj" { + let variable = &input[*pos]; + *pos += 1; + if variable.typ != TokenType::IDENTIFIER { + panic!("Unexpected {:?} at {}", variable.typ, variable.pos) + } + let eq = &input[*pos]; + if eq.typ == TokenType::SEPARATOR && eq.value == "=" { + *pos += 1; + } + let value = next_operation(pos, input, ASTPart::NOOP, op_ends, parse_ends); + return ASTPart::Assigment(AstAssigment { variable: variable.value.clone(), value: Box::new(value), pos: token.pos }); + } else if token.typ == TokenType::NUMBER { + return next_operation(pos, input, ASTPart::Number(AstNumber { value: token.value.parse().unwrap(), pos: token.pos }), op_ends, parse_ends); + } else if token.typ == TokenType::IDENTIFIER { + return next_operation(pos, input, ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos }), op_ends, parse_ends); + } else { + panic!("Unexpected {:?} at {}", token.typ, token.pos); + } +} +fn parse_internal(input: Vec, op_ends: Vec, parse_ends: Vec) -> Vec { + let mut out: Vec = vec![]; + let mut pos = 0; + while pos < input.len() { + let op = next_operation(&mut pos, &input, ASTPart::NOOP, &op_ends, &parse_ends); + out.push(op); + if is_end(&input[pos], &parse_ends) { + break; + } + } + return out; +} +pub fn parse(input: Vec) -> 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); + return out; +} \ No newline at end of file diff --git a/test.as b/test.as index 858b213..10d1db2 100644 --- a/test.as +++ b/test.as @@ -1,2 +1,2 @@ gethelj a = 1 -gethelj b = a + 2 \ No newline at end of file +gethelj b = a \ No newline at end of file