Started writing new expression parser (It does not work right now)
This commit is contained in:
parent
3753f6d8f5
commit
8f98528a15
106
src/ast.rs
106
src/ast.rs
|
@ -6,8 +6,8 @@ use std::collections::HashMap;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Function {
|
||||
pub name: String,
|
||||
pub statements: Vec<Statement>,
|
||||
pub n_args: u64,
|
||||
pub statement: Statement,
|
||||
pub args: Vec<String>,
|
||||
assembly: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,27 @@ pub enum 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)]
|
||||
pub enum ValueNode {
|
||||
Literal(Literal),
|
||||
|
@ -48,11 +69,11 @@ pub trait Node {
|
|||
}
|
||||
|
||||
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 {
|
||||
name,
|
||||
statements,
|
||||
n_args,
|
||||
statement,
|
||||
args,
|
||||
assembly: None,
|
||||
}
|
||||
}
|
||||
|
@ -78,8 +99,8 @@ fn get_default_functions() -> HashMap<String, Function> {
|
|||
"out".to_string(),
|
||||
Function {
|
||||
name: "out".to_string(),
|
||||
statements: vec![],
|
||||
n_args: 1,
|
||||
statement: Statement::FunctionCall("".to_string(), vec![]),
|
||||
args: vec!["value".to_string()],
|
||||
assembly: Some(
|
||||
"
|
||||
out:
|
||||
|
@ -118,8 +139,8 @@ F-OUT JMP 0xFF"
|
|||
"exit".to_string(),
|
||||
Function {
|
||||
name: "exit".to_string(),
|
||||
statements: vec![],
|
||||
n_args: 0,
|
||||
statement: Statement::FunctionCall("".to_string(), vec![]),
|
||||
args: vec![],
|
||||
assembly: Some(
|
||||
"
|
||||
exit:
|
||||
|
@ -136,9 +157,25 @@ impl Node for Function {
|
|||
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
||||
match &self.assembly {
|
||||
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
|
||||
;
|
||||
|
@ -154,15 +191,8 @@ ROM-OUT FLAGS-IN 0x00 ; Add mode
|
|||
|
||||
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 {
|
||||
match self {
|
||||
Statement::Scope(statements) => {
|
||||
let init_assembly = "
|
||||
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 dropped_length = state.variables.len();
|
||||
|
||||
let statement_assembly = statements
|
||||
.iter()
|
||||
|
@ -187,33 +209,20 @@ ALU-OUT SE-IN 0xFF
|
|||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
|
||||
let mut stop_assembly = "".to_string();
|
||||
|
||||
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"
|
||||
);
|
||||
while state.variables.len() > dropped_length {
|
||||
state.variables.pop();
|
||||
}
|
||||
dbg!(&state.variables);
|
||||
|
||||
format!(
|
||||
"{init_assembly}
|
||||
{statement_assembly}
|
||||
{stop_assembly}"
|
||||
)
|
||||
statement_assembly
|
||||
}
|
||||
Statement::FunctionCall(name, arguments) => {
|
||||
if !state.functions.contains_key(name) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
state.variables.push(name.to_owned());
|
||||
dbg!(&state.variables);
|
||||
let argument_assembly: String = arguments
|
||||
.into_iter()
|
||||
.map(|x| x.to_assembly(state))
|
||||
|
@ -226,7 +235,7 @@ ROM-OUT FLAGS-IN 0x00"
|
|||
.map(char::from)
|
||||
.collect();
|
||||
|
||||
for _ in 0..state.functions.get(name).unwrap().n_args {
|
||||
for _ in &state.functions.get(name).unwrap().args {
|
||||
state.variables.pop();
|
||||
}
|
||||
|
||||
|
@ -316,6 +325,7 @@ impl Node for ValueNode {
|
|||
- state.variables.iter().position(|x| x == name).unwrap()
|
||||
- 1;
|
||||
|
||||
dbg!(&state.variables);
|
||||
state.variables.push(name.to_owned());
|
||||
|
||||
format!(
|
||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,17 +1,28 @@
|
|||
use crate::tokeniser::Token;
|
||||
|
||||
mod ast;
|
||||
mod parse;
|
||||
mod tokeniser;
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
175
src/parse.rs
175
src/parse.rs
|
@ -66,77 +66,143 @@ fn parse_math(tokens: &Vec<Token>) -> ValueNode {
|
|||
};
|
||||
}
|
||||
|
||||
fn parse_statements(tokens: &Vec<Token>, starting_i: usize) -> (Vec<Statement>, usize) {
|
||||
let mut i = starting_i;
|
||||
fn parse_basic(tokens: &Vec<Token>, i: &mut usize) -> Expression {
|
||||
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();
|
||||
while i < tokens.len() {
|
||||
statements.push(match &tokens[i] {
|
||||
while *i < tokens.len() {
|
||||
statements.push(match &tokens[*i] {
|
||||
Token::OpenSquiglyBracket => {
|
||||
let (statements, added_to_i) = parse_statements(tokens, i + 1);
|
||||
i = added_to_i + 1;
|
||||
*i += 1;
|
||||
let statements = parse_statements(tokens, i);
|
||||
Statement::Scope(statements)
|
||||
}
|
||||
Token::Keyword(Keyword::Let) => {
|
||||
i += 1;
|
||||
let name = match tokens[i].clone() {
|
||||
*i += 1;
|
||||
let name = match tokens[*i].clone() {
|
||||
Token::Identifier(identifier) => identifier,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
i += 1;
|
||||
match tokens[i].clone() {
|
||||
*i += 1;
|
||||
match tokens[*i].clone() {
|
||||
Token::Equals => {}
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
i += 1;
|
||||
*i += 1;
|
||||
|
||||
let mut declaration_tokens: Vec<Token> = Vec::new();
|
||||
while tokens[i] != Token::Semi {
|
||||
declaration_tokens.push(tokens[i].clone());
|
||||
i += 1;
|
||||
while tokens[*i] != Token::Semi {
|
||||
declaration_tokens.push(tokens[*i].clone());
|
||||
*i += 1;
|
||||
}
|
||||
Statement::VariableDeclaration(name, parse_math(&declaration_tokens))
|
||||
}
|
||||
Token::Keyword(Keyword::Assign) => {
|
||||
i += 1;
|
||||
let name = match tokens[i].clone() {
|
||||
*i += 1;
|
||||
let name = match tokens[*i].clone() {
|
||||
Token::Identifier(identifier) => identifier,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
i += 1;
|
||||
match tokens[i].clone() {
|
||||
*i += 1;
|
||||
match tokens[*i].clone() {
|
||||
Token::Equals => {}
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
i += 1;
|
||||
*i += 1;
|
||||
|
||||
let mut declaration_tokens: Vec<Token> = Vec::new();
|
||||
while tokens[i] != Token::Semi {
|
||||
declaration_tokens.push(tokens[i].clone());
|
||||
i += 1;
|
||||
while tokens[*i] != Token::Semi {
|
||||
declaration_tokens.push(tokens[*i].clone());
|
||||
*i += 1;
|
||||
}
|
||||
Statement::VariableAssignment(name, parse_math(&declaration_tokens))
|
||||
}
|
||||
Token::Identifier(identifier) => {
|
||||
i += 1;
|
||||
*i += 1;
|
||||
|
||||
let mut declaration_tokens: Vec<Vec<Token>> = Vec::new();
|
||||
|
||||
i += 1;
|
||||
while tokens[i] != Token::CloseParanthesis {
|
||||
*i += 1;
|
||||
while tokens[*i] != Token::CloseParanthesis {
|
||||
let mut argument_tokens: Vec<Token> = Vec::new();
|
||||
while tokens[i] != Token::Comma {
|
||||
argument_tokens.push(tokens[i].clone());
|
||||
i += 1;
|
||||
while tokens[*i] != Token::Comma {
|
||||
argument_tokens.push(tokens[*i].clone());
|
||||
*i += 1;
|
||||
}
|
||||
declaration_tokens.push(argument_tokens);
|
||||
i += 1;
|
||||
*i += 1;
|
||||
}
|
||||
|
||||
i += 1;
|
||||
*i += 1;
|
||||
|
||||
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)
|
||||
}
|
||||
Token::CloseSquiglyBracket => {
|
||||
return (statements, i);
|
||||
*i += 1;
|
||||
return statements;
|
||||
}
|
||||
Token::Semi => {
|
||||
i += 1;
|
||||
*i += 1;
|
||||
continue;
|
||||
}
|
||||
_other => {
|
||||
dbg!(_other);
|
||||
dbg!(i);
|
||||
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> {
|
||||
|
@ -172,18 +254,23 @@ pub fn ast(tokens: Vec<Token>) -> Vec<Function> {
|
|||
while i < tokens.len() {
|
||||
match &tokens[i] {
|
||||
Token::Keyword(Keyword::Function) => {
|
||||
let (statements, added_to_i) = parse_statements(&tokens, i + 4);
|
||||
let statements = vec![Statement::Scope(statements)];
|
||||
let function_name = match &tokens[i + 1] {
|
||||
Token::Identifier(identifier) => identifier.to_owned(),
|
||||
i += 1;
|
||||
|
||||
let name = match &tokens[i] {
|
||||
Token::Identifier(identifier) => identifier,
|
||||
_ => todo!(),
|
||||
};
|
||||
let n_args = match &tokens[i + 2] {
|
||||
Token::Number(num) => num.parse::<u64>().unwrap(),
|
||||
_ => todo!(),
|
||||
};
|
||||
i += added_to_i;
|
||||
functions.push(Function::new(function_name, n_args, statements));
|
||||
}
|
||||
.to_owned();
|
||||
i += 1;
|
||||
|
||||
let arguments = parse_arguments(&tokens, &mut i);
|
||||
|
||||
i += 1;
|
||||
let statements = parse_statements(&tokens, &mut i);
|
||||
|
||||
let statement = Statement::Scope(statements);
|
||||
|
||||
functions.push(Function::new(name, arguments, statement));
|
||||
}
|
||||
_other => {
|
||||
dbg!(&functions);
|
||||
|
|
|
@ -5,6 +5,8 @@ pub enum Token {
|
|||
Comma,
|
||||
Plus,
|
||||
Minus,
|
||||
Ampersand,
|
||||
Star,
|
||||
Number(String),
|
||||
Identifier(String),
|
||||
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 TokenFinishedUnfinished::Unfinished as uf;
|
||||
|
||||
match current_character {
|
||||
';' => uf(s(T::Semi)),
|
||||
'(' => uf(s(T::OpenParanthesis)),
|
||||
')' => uf(s(T::CloseParanthesis)),
|
||||
'{' => uf(s(T::OpenSquiglyBracket)),
|
||||
'}' => uf(s(T::CloseSquiglyBracket)),
|
||||
'=' => uf(s(T::Equals)),
|
||||
',' => uf(s(T::Comma)),
|
||||
'+' => uf(s(T::Plus)),
|
||||
'-' => uf(s(T::Minus)),
|
||||
_ => uf(None),
|
||||
}
|
||||
uf(match current_character {
|
||||
';' => s(T::Semi),
|
||||
'(' => s(T::OpenParanthesis),
|
||||
')' => s(T::CloseParanthesis),
|
||||
'{' => s(T::OpenSquiglyBracket),
|
||||
'}' => s(T::CloseSquiglyBracket),
|
||||
'=' => s(T::Equals),
|
||||
',' => s(T::Comma),
|
||||
'+' => s(T::Plus),
|
||||
'-' => s(T::Minus),
|
||||
'&' => s(T::Ampersand),
|
||||
'*' => s(T::Star),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
Some(v) => Finished(v),
|
||||
|
|
Loading…
Reference in a new issue