Started writing new expression parser (It does not work right now)

This commit is contained in:
vanten-s 2023-09-22 17:06:37 +02:00
parent 3753f6d8f5
commit 8f98528a15
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
4 changed files with 223 additions and 111 deletions

View file

@ -6,8 +6,8 @@ use std::collections::HashMap;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Function { pub struct Function {
pub name: String, pub name: String,
pub statements: Vec<Statement>, pub statement: Statement,
pub n_args: u64, pub args: Vec<String>,
assembly: Option<String>, assembly: Option<String>,
} }
@ -19,6 +19,27 @@ pub enum Statement {
Scope(Vec<Statement>), Scope(Vec<Statement>),
} }
#[derive(Debug, Clone)]
pub enum Expression {
Literal(Literal),
Variable(String),
Unary(Unary, Box<Expression>),
Grouping(Box<Expression>),
Binary(BinOp, Box<Expression>, Box<Expression>),
}
#[derive(Debug, Clone)]
pub enum Unary {
PointerTo,
ValueFrom,
}
#[derive(Debug, Clone)]
pub enum BinOp {
Plus,
Minus,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ValueNode { pub enum ValueNode {
Literal(Literal), Literal(Literal),
@ -48,11 +69,11 @@ pub trait Node {
} }
impl Function { impl Function {
pub fn new(name: String, n_args: u64, statements: Vec<Statement>) -> Function { pub fn new(name: String, args: Vec<String>, statement: Statement) -> Function {
Function { Function {
name, name,
statements, statement,
n_args, args,
assembly: None, assembly: None,
} }
} }
@ -78,8 +99,8 @@ fn get_default_functions() -> HashMap<String, Function> {
"out".to_string(), "out".to_string(),
Function { Function {
name: "out".to_string(), name: "out".to_string(),
statements: vec![], statement: Statement::FunctionCall("".to_string(), vec![]),
n_args: 1, args: vec!["value".to_string()],
assembly: Some( assembly: Some(
" "
out: out:
@ -118,8 +139,8 @@ F-OUT JMP 0xFF"
"exit".to_string(), "exit".to_string(),
Function { Function {
name: "exit".to_string(), name: "exit".to_string(),
statements: vec![], statement: Statement::FunctionCall("".to_string(), vec![]),
n_args: 0, args: vec![],
assembly: Some( assembly: Some(
" "
exit: exit:
@ -136,9 +157,25 @@ impl Node for Function {
fn to_assembly(&self, state: &mut AssemblerState) -> String { fn to_assembly(&self, state: &mut AssemblerState) -> String {
match &self.assembly { match &self.assembly {
Some(v) => v.to_string(), Some(v) => v.to_string(),
None => format!( None => {
"{}: let name = &self.name;
{}
let mut pop_argument_assembly = "ROM-OUT FLAGS-IN 0x80".to_string();
for argument in &self.args {
state.variables.push(argument.to_string());
pop_argument_assembly += "
SE-OUT A-IN 0xFF
ROM-OUT B-IN 0x01
ALU-OUT SE-IN 0xFF
"
}
let statement_assembly = self.statement.to_assembly(state);
format!(
"{name}:
{statement_assembly}
{pop_argument_assembly}
; ;
; Pop the return address of the stack ; Pop the return address of the stack
; ;
@ -154,15 +191,8 @@ ROM-OUT FLAGS-IN 0x00 ; Add mode
F-OUT JMP 0xFF F-OUT JMP 0xFF
", ",
self.name, )
{
self.statements
.iter()
.map(|x| x.to_assembly(state))
.collect::<Vec<String>>()
.join("\n")
} }
),
} }
} }
} }
@ -171,15 +201,7 @@ impl Node for Statement {
fn to_assembly(&self, state: &mut AssemblerState) -> String { fn to_assembly(&self, state: &mut AssemblerState) -> String {
match self { match self {
Statement::Scope(statements) => { Statement::Scope(statements) => {
let init_assembly = " let dropped_length = state.variables.len();
ROM-OUT FLAGS-IN 0x00
SE-OUT A-IN 0xFF
ROM-OUT B-IN 0x01
ALU-OUT SE-IN 0xFF
"
.to_string();
state.variables.push("start scope".to_string());
let statement_assembly = statements let statement_assembly = statements
.iter() .iter()
@ -187,33 +209,20 @@ ALU-OUT SE-IN 0xFF
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n"); .join("\n");
let mut stop_assembly = "".to_string(); while state.variables.len() > dropped_length {
while state.variables.contains(&"start scope".to_string()) {
stop_assembly += &format!(
"
ROM-OUT FLAGS-IN 0x80
SE-OUT A-IN 0xFF
ROM-OUT B-IN 0x01
ALU-OUT SE-IN 0xFF
ROM-OUT FLAGS-IN 0x00"
);
state.variables.pop(); state.variables.pop();
} }
dbg!(&state.variables);
format!( statement_assembly
"{init_assembly}
{statement_assembly}
{stop_assembly}"
)
} }
Statement::FunctionCall(name, arguments) => { Statement::FunctionCall(name, arguments) => {
if !state.functions.contains_key(name) { if !state.functions.contains_key(name) {
todo!() todo!()
} }
state.variables.push(name.to_owned()); state.variables.push(name.to_owned());
dbg!(&state.variables);
let argument_assembly: String = arguments let argument_assembly: String = arguments
.into_iter() .into_iter()
.map(|x| x.to_assembly(state)) .map(|x| x.to_assembly(state))
@ -226,7 +235,7 @@ ROM-OUT FLAGS-IN 0x00"
.map(char::from) .map(char::from)
.collect(); .collect();
for _ in 0..state.functions.get(name).unwrap().n_args { for _ in &state.functions.get(name).unwrap().args {
state.variables.pop(); state.variables.pop();
} }
@ -316,6 +325,7 @@ impl Node for ValueNode {
- state.variables.iter().position(|x| x == name).unwrap() - state.variables.iter().position(|x| x == name).unwrap()
- 1; - 1;
dbg!(&state.variables);
state.variables.push(name.to_owned()); state.variables.push(name.to_owned());
format!( format!(

View file

@ -1,17 +1,28 @@
use crate::tokeniser::Token;
mod ast; mod ast;
mod parse; mod parse;
mod tokeniser; mod tokeniser;
fn main() { fn main() {
let filename = "test.plonkus"; // let filename: &str = &std::env::args().collect::<Vec<String>>()[1];
let contents = std::fs::read_to_string(filename).expect(&format!("No file named {}", filename)); // let contents = std::fs::read_to_string(filename).expect(&format!("No file named {}", filename));
let tokens = tokeniser::tokenise(contents); // let tokens = tokeniser::tokenise(contents);
let functions = dbg!(parse::ast(tokens)); // let functions = dbg!(parse::ast(tokens));
let assembly = ast::to_assembly(functions); // let assembly = ast::to_assembly(functions);
println!("{}", assembly); // println!("{}", assembly);
let mut i: usize = 0;
let tokens: Vec<tokeniser::Token> = vec![
Token::OpenParanthesis,
Token::Star,
Token::Number("2".to_string()),
Token::CloseParanthesis,
];
dbg!(parse::parse_expression(&tokens, &mut i));
} }

View file

@ -66,77 +66,143 @@ fn parse_math(tokens: &Vec<Token>) -> ValueNode {
}; };
} }
fn parse_statements(tokens: &Vec<Token>, starting_i: usize) -> (Vec<Statement>, usize) { fn parse_basic(tokens: &Vec<Token>, i: &mut usize) -> Expression {
let mut i = starting_i; let literal = match &tokens[*i] {
Token::Identifier(identifier) => Expression::Variable(identifier.to_owned()),
Token::Number(number) => Expression::Literal(Literal::Int(number.parse::<i64>().unwrap())),
_ => todo!(),
};
*i += 1;
literal
}
fn parse_grouping(tokens: &Vec<Token>, i: &mut usize) -> Expression {
match &tokens[*i] {
Token::OpenParanthesis => {
*i += 1;
}
_ => todo!(),
};
let inner_expression = parse_expression(tokens, i);
match &tokens[*i] {
Token::CloseParanthesis => {}
_ => todo!(),
};
inner_expression
}
// TODO: replace parse_math with this recursive function
pub fn parse_expression(tokens: &Vec<Token>, i: &mut usize) -> Expression {
#[derive(Debug)]
enum OpExpr {
Expression(Expression),
BinOp(BinOp),
Unary(Unary),
}
let mut in_expressions_and_operators: Vec<OpExpr> = Vec::new();
loop {
in_expressions_and_operators.push(match &tokens[*i] {
Token::OpenParanthesis => OpExpr::Expression(parse_grouping(tokens, i)),
Token::Plus => {
*i += 1;
OpExpr::BinOp(BinOp::Plus)
}
Token::Minus => {
*i += 1;
OpExpr::BinOp(BinOp::Minus)
}
Token::Ampersand => {
*i += 1;
OpExpr::Unary(Unary::ValueFrom)
}
Token::Star => {
*i += 1;
OpExpr::Unary(Unary::PointerTo)
}
Token::Number(_) => OpExpr::Expression(parse_basic(tokens, i)),
_other => break,
});
}
dbg!(in_expressions_and_operators);
Expression::Variable("a".to_string())
}
fn parse_statements(tokens: &Vec<Token>, i: &mut usize) -> Vec<Statement> {
dbg!(&i);
let mut statements = Vec::new(); let mut statements = Vec::new();
while i < tokens.len() { while *i < tokens.len() {
statements.push(match &tokens[i] { statements.push(match &tokens[*i] {
Token::OpenSquiglyBracket => { Token::OpenSquiglyBracket => {
let (statements, added_to_i) = parse_statements(tokens, i + 1); *i += 1;
i = added_to_i + 1; let statements = parse_statements(tokens, i);
Statement::Scope(statements) Statement::Scope(statements)
} }
Token::Keyword(Keyword::Let) => { Token::Keyword(Keyword::Let) => {
i += 1; *i += 1;
let name = match tokens[i].clone() { let name = match tokens[*i].clone() {
Token::Identifier(identifier) => identifier, Token::Identifier(identifier) => identifier,
_ => todo!(), _ => todo!(),
}; };
i += 1; *i += 1;
match tokens[i].clone() { match tokens[*i].clone() {
Token::Equals => {} Token::Equals => {}
_ => todo!(), _ => todo!(),
}; };
i += 1; *i += 1;
let mut declaration_tokens: Vec<Token> = Vec::new(); let mut declaration_tokens: Vec<Token> = Vec::new();
while tokens[i] != Token::Semi { while tokens[*i] != Token::Semi {
declaration_tokens.push(tokens[i].clone()); declaration_tokens.push(tokens[*i].clone());
i += 1; *i += 1;
} }
Statement::VariableDeclaration(name, parse_math(&declaration_tokens)) Statement::VariableDeclaration(name, parse_math(&declaration_tokens))
} }
Token::Keyword(Keyword::Assign) => { Token::Keyword(Keyword::Assign) => {
i += 1; *i += 1;
let name = match tokens[i].clone() { let name = match tokens[*i].clone() {
Token::Identifier(identifier) => identifier, Token::Identifier(identifier) => identifier,
_ => todo!(), _ => todo!(),
}; };
i += 1; *i += 1;
match tokens[i].clone() { match tokens[*i].clone() {
Token::Equals => {} Token::Equals => {}
_ => todo!(), _ => todo!(),
}; };
i += 1; *i += 1;
let mut declaration_tokens: Vec<Token> = Vec::new(); let mut declaration_tokens: Vec<Token> = Vec::new();
while tokens[i] != Token::Semi { while tokens[*i] != Token::Semi {
declaration_tokens.push(tokens[i].clone()); declaration_tokens.push(tokens[*i].clone());
i += 1; *i += 1;
} }
Statement::VariableAssignment(name, parse_math(&declaration_tokens)) Statement::VariableAssignment(name, parse_math(&declaration_tokens))
} }
Token::Identifier(identifier) => { Token::Identifier(identifier) => {
i += 1; *i += 1;
let mut declaration_tokens: Vec<Vec<Token>> = Vec::new(); let mut declaration_tokens: Vec<Vec<Token>> = Vec::new();
i += 1; *i += 1;
while tokens[i] != Token::CloseParanthesis { while tokens[*i] != Token::CloseParanthesis {
let mut argument_tokens: Vec<Token> = Vec::new(); let mut argument_tokens: Vec<Token> = Vec::new();
while tokens[i] != Token::Comma { while tokens[*i] != Token::Comma {
argument_tokens.push(tokens[i].clone()); argument_tokens.push(tokens[*i].clone());
i += 1; *i += 1;
} }
declaration_tokens.push(argument_tokens); declaration_tokens.push(argument_tokens);
i += 1; *i += 1;
} }
i += 1; *i += 1;
let mut arguments: Vec<ValueNode> = Vec::new(); let mut arguments: Vec<ValueNode> = Vec::new();
@ -150,19 +216,35 @@ fn parse_statements(tokens: &Vec<Token>, starting_i: usize) -> (Vec<Statement>,
Statement::FunctionCall(identifier.to_owned(), arguments) Statement::FunctionCall(identifier.to_owned(), arguments)
} }
Token::CloseSquiglyBracket => { Token::CloseSquiglyBracket => {
return (statements, i); *i += 1;
return statements;
} }
Token::Semi => { Token::Semi => {
i += 1; *i += 1;
continue; continue;
} }
_other => { _other => {
dbg!(_other); dbg!(_other);
dbg!(i);
todo!() todo!()
} }
}); });
} }
(statements, i) *i += 1;
statements
}
pub fn parse_arguments(tokens: &Vec<Token>, i: &mut usize) -> Vec<String> {
let mut argument_variables = Vec::new();
while tokens[*i] != Token::OpenSquiglyBracket {
match &tokens[*i] {
Token::Identifier(identifier) => argument_variables.push(identifier.to_owned()),
Token::OpenSquiglyBracket => {}
_other => todo!(),
}
*i += 1;
}
argument_variables
} }
pub fn ast(tokens: Vec<Token>) -> Vec<Function> { pub fn ast(tokens: Vec<Token>) -> Vec<Function> {
@ -172,18 +254,23 @@ pub fn ast(tokens: Vec<Token>) -> Vec<Function> {
while i < tokens.len() { while i < tokens.len() {
match &tokens[i] { match &tokens[i] {
Token::Keyword(Keyword::Function) => { Token::Keyword(Keyword::Function) => {
let (statements, added_to_i) = parse_statements(&tokens, i + 4); i += 1;
let statements = vec![Statement::Scope(statements)];
let function_name = match &tokens[i + 1] { let name = match &tokens[i] {
Token::Identifier(identifier) => identifier.to_owned(), Token::Identifier(identifier) => identifier,
_ => todo!(), _ => todo!(),
}; }
let n_args = match &tokens[i + 2] { .to_owned();
Token::Number(num) => num.parse::<u64>().unwrap(), i += 1;
_ => todo!(),
}; let arguments = parse_arguments(&tokens, &mut i);
i += added_to_i;
functions.push(Function::new(function_name, n_args, statements)); i += 1;
let statements = parse_statements(&tokens, &mut i);
let statement = Statement::Scope(statements);
functions.push(Function::new(name, arguments, statement));
} }
_other => { _other => {
dbg!(&functions); dbg!(&functions);

View file

@ -5,6 +5,8 @@ pub enum Token {
Comma, Comma,
Plus, Plus,
Minus, Minus,
Ampersand,
Star,
Number(String), Number(String),
Identifier(String), Identifier(String),
Keyword(Keyword), Keyword(Keyword),
@ -85,22 +87,24 @@ fn tokenise_current_character(
} }
{ {
use std::option::Option::Some as s; use Option::Some as s;
use Token as T; use Token as T;
use TokenFinishedUnfinished::Unfinished as uf; use TokenFinishedUnfinished::Unfinished as uf;
match current_character { uf(match current_character {
';' => uf(s(T::Semi)), ';' => s(T::Semi),
'(' => uf(s(T::OpenParanthesis)), '(' => s(T::OpenParanthesis),
')' => uf(s(T::CloseParanthesis)), ')' => s(T::CloseParanthesis),
'{' => uf(s(T::OpenSquiglyBracket)), '{' => s(T::OpenSquiglyBracket),
'}' => uf(s(T::CloseSquiglyBracket)), '}' => s(T::CloseSquiglyBracket),
'=' => uf(s(T::Equals)), '=' => s(T::Equals),
',' => uf(s(T::Comma)), ',' => s(T::Comma),
'+' => uf(s(T::Plus)), '+' => s(T::Plus),
'-' => uf(s(T::Minus)), '-' => s(T::Minus),
_ => uf(None), '&' => s(T::Ampersand),
} '*' => s(T::Star),
_ => None,
})
} }
} }
Some(v) => Finished(v), Some(v) => Finished(v),