begin parser
This commit is contained in:
parent
054c8d2fb7
commit
6aa40a3e3e
4 changed files with 132 additions and 3 deletions
12
src/lexer.rs
12
src/lexer.rs
|
@ -5,7 +5,8 @@ pub enum TokenType {
|
||||||
IDENTIFIER,
|
IDENTIFIER,
|
||||||
OPERATOR,
|
OPERATOR,
|
||||||
KEYWORD,
|
KEYWORD,
|
||||||
SEPARATOR
|
SEPARATOR,
|
||||||
|
OPEND
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Token {
|
pub struct Token {
|
||||||
|
@ -14,6 +15,10 @@ pub struct Token {
|
||||||
pub pos: usize,
|
pub pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_opend(char: &str) -> bool {
|
||||||
|
let chars = vec![";","\n"];
|
||||||
|
return chars.contains(&char);
|
||||||
|
}
|
||||||
fn is_ignored(char: &str) -> bool {
|
fn is_ignored(char: &str) -> bool {
|
||||||
let chars = vec![""," ","\n","\r","\t"];
|
let chars = vec![""," ","\n","\r","\t"];
|
||||||
return chars.contains(&char);
|
return chars.contains(&char);
|
||||||
|
@ -194,6 +199,10 @@ pub fn lex(input: String) -> Vec<Token> {
|
||||||
while pos < splitted.len() {
|
while pos < splitted.len() {
|
||||||
let char = splitted[pos];
|
let char = splitted[pos];
|
||||||
pos += 1;
|
pos += 1;
|
||||||
|
if is_opend(char) {
|
||||||
|
out.push(Token { typ: TokenType::OPEND, value: String::from(char), pos: pos-1 });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if is_ignored(char) {
|
if is_ignored(char) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -224,5 +233,6 @@ pub fn lex(input: String) -> Vec<Token> {
|
||||||
read_identifier(&splitted, &mut pos, &mut out);
|
read_identifier(&splitted, &mut pos, &mut out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out.push(Token { typ: TokenType::OPEND, value: String::from("EOF"), pos: pos-1 });
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
30
src/main.rs
30
src/main.rs
|
@ -1,6 +1,29 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
use parser::ASTPart;
|
||||||
|
|
||||||
mod lexer;
|
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() {
|
fn main() {
|
||||||
let inp = fs::read_to_string("./test.as");
|
let inp = fs::read_to_string("./test.as");
|
||||||
|
@ -8,9 +31,14 @@ fn main() {
|
||||||
Result::Ok(data) => {
|
Result::Ok(data) => {
|
||||||
let lexed = lexer::lex(data);
|
let lexed = lexer::lex(data);
|
||||||
println!("Lexer output: ");
|
println!("Lexer output: ");
|
||||||
for token in lexed {
|
for token in &lexed {
|
||||||
println!(" {}: {:?}: {}", token.pos, token.typ, token.value);
|
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) => {
|
Result::Err(err) => {
|
||||||
panic!("Error while reading file: {}", err)
|
panic!("Error while reading file: {}", err)
|
||||||
|
|
91
src/parser.rs
Normal file
91
src/parser.rs
Normal file
|
@ -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<ASTPart>,
|
||||||
|
pub pos: usize
|
||||||
|
}
|
||||||
|
pub struct AstOperation {
|
||||||
|
pub operator: String,
|
||||||
|
pub left: Box<ASTPart>,
|
||||||
|
pub right: Box<ASTPart>,
|
||||||
|
pub pos: usize
|
||||||
|
}
|
||||||
|
pub struct AstVarRead {
|
||||||
|
pub variable: String,
|
||||||
|
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 next_operation(pos: &mut usize, input: &Vec<Token>, prev: ASTPart, op_ends: &Vec<Token>, parse_ends: &Vec<Token>) -> 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<Token>, op_ends: Vec<Token>, parse_ends: Vec<Token>) -> Vec<ASTPart> {
|
||||||
|
let mut out: Vec<ASTPart> = 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<Token>) -> 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);
|
||||||
|
return out;
|
||||||
|
}
|
2
test.as
2
test.as
|
@ -1,2 +1,2 @@
|
||||||
gethelj a = 1
|
gethelj a = 1
|
||||||
gethelj b = a + 2
|
gethelj b = a
|
Loading…
Add table
Add a link
Reference in a new issue