Better Expressions And Function Calling Syntax
This commit is contained in:
parent
8f98528a15
commit
ae22ff77da
48
src/ast.rs
48
src/ast.rs
|
@ -13,9 +13,9 @@ pub struct Function {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
FunctionCall(String, Vec<ValueNode>),
|
FunctionCall(String, Vec<Expression>),
|
||||||
VariableDeclaration(String, ValueNode),
|
VariableDeclaration(String, Expression),
|
||||||
VariableAssignment(String, ValueNode),
|
VariableAssignment(String, Expression),
|
||||||
Scope(Vec<Statement>),
|
Scope(Vec<Statement>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +24,16 @@ pub enum Expression {
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Variable(String),
|
Variable(String),
|
||||||
Unary(Unary, Box<Expression>),
|
Unary(Unary, Box<Expression>),
|
||||||
Grouping(Box<Expression>),
|
|
||||||
Binary(BinOp, Box<Expression>, Box<Expression>),
|
Binary(BinOp, Box<Expression>, Box<Expression>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Unary {
|
pub enum Unary {
|
||||||
PointerTo,
|
PointerTo,
|
||||||
ValueFrom,
|
ValueFrom,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
|
@ -309,12 +308,14 @@ ROM-OUT FLAGS-IN 0x00 ; Add Mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for ValueNode {
|
impl Node for Expression {
|
||||||
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
||||||
match self {
|
match self {
|
||||||
ValueNode::Literal(v) => v.to_assembly(state),
|
Expression::Literal(v) => v.to_assembly(state),
|
||||||
ValueNode::Operator(o) => o.to_assembly(state),
|
Expression::Binary(o, expr_1, expr_2) => {
|
||||||
ValueNode::Variable(name) => {
|
expr_1.to_assembly(state) + &expr_2.to_assembly(state) + &o.to_assembly(state)
|
||||||
|
}
|
||||||
|
Expression::Variable(name) => {
|
||||||
if !state.variables.contains(name) {
|
if !state.variables.contains(name) {
|
||||||
dbg!(&name);
|
dbg!(&name);
|
||||||
dbg!(&state.variables);
|
dbg!(&state.variables);
|
||||||
|
@ -355,6 +356,9 @@ C-OUT RAM-IN 0xFF
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Expression::Unary(operator, expr) => {
|
||||||
|
expr.to_assembly(state) + &operator.to_assembly(state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,14 +389,12 @@ ROM-OUT RAM-IN {v}; Store literal value in RAM"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for Operator {
|
impl Node for BinOp {
|
||||||
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
||||||
match self {
|
match self {
|
||||||
Operator::Add(a, b) => {
|
BinOp::Plus => {
|
||||||
let assembly = format!(
|
let assembly = format!(
|
||||||
"{}
|
"
|
||||||
{}
|
|
||||||
|
|
||||||
SE-OUT RAM-ADDR-U-IN 0xFF ; Set ram address to stack end
|
SE-OUT RAM-ADDR-U-IN 0xFF ; Set ram address to stack end
|
||||||
RAM-OUT C-IN 0xFF ; Output top address onto output register
|
RAM-OUT C-IN 0xFF ; Output top address onto output register
|
||||||
|
|
||||||
|
@ -421,17 +423,13 @@ ALU-OUT SE-IN 0xFF ; Store
|
||||||
ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address
|
ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address
|
||||||
C-OUT RAM-IN 0xFF ; Store address after jump in ram
|
C-OUT RAM-IN 0xFF ; Store address after jump in ram
|
||||||
",
|
",
|
||||||
a.to_assembly(state),
|
|
||||||
b.to_assembly(state)
|
|
||||||
);
|
);
|
||||||
state.variables.pop();
|
state.variables.pop();
|
||||||
assembly
|
assembly
|
||||||
}
|
}
|
||||||
Operator::Sub(a, b) => {
|
BinOp::Minus => {
|
||||||
format!(
|
format!(
|
||||||
"{}
|
"
|
||||||
{}
|
|
||||||
|
|
||||||
SE-OUT RAM-ADDR-U-IN 0xFF ; Set ram address to stack end
|
SE-OUT RAM-ADDR-U-IN 0xFF ; Set ram address to stack end
|
||||||
RAM-OUT C-IN 0xFF ; Output top address onto output register
|
RAM-OUT C-IN 0xFF ; Output top address onto output register
|
||||||
|
|
||||||
|
@ -462,14 +460,18 @@ ALU-OUT SE-IN 0xFF ; Store
|
||||||
ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address
|
ALU-OUT RAM-ADDR-U-IN 0xFF ; Store in RAM address
|
||||||
C-OUT RAM-IN 0xFF ; Store address after jump in ram
|
C-OUT RAM-IN 0xFF ; Store address after jump in ram
|
||||||
",
|
",
|
||||||
a.to_assembly(state),
|
|
||||||
b.to_assembly(state)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Node for Unary {
|
||||||
|
fn to_assembly(&self, state: &mut AssemblerState) -> String {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_assembly(functions: Vec<Function>) -> String {
|
pub fn to_assembly(functions: Vec<Function>) -> String {
|
||||||
let mut final_product: String = "".to_owned();
|
let mut final_product: String = "".to_owned();
|
||||||
let mut std_function_assembly = "".to_owned();
|
let mut std_function_assembly = "".to_owned();
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,28 +1,17 @@
|
||||||
use crate::tokeniser::Token;
|
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod tokeniser;
|
mod tokeniser;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// let filename: &str = &std::env::args().collect::<Vec<String>>()[1];
|
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));
|
|
||||||
}
|
}
|
||||||
|
|
189
src/parse.rs
189
src/parse.rs
|
@ -70,30 +70,16 @@ fn parse_basic(tokens: &Vec<Token>, i: &mut usize) -> Expression {
|
||||||
let literal = match &tokens[*i] {
|
let literal = match &tokens[*i] {
|
||||||
Token::Identifier(identifier) => Expression::Variable(identifier.to_owned()),
|
Token::Identifier(identifier) => Expression::Variable(identifier.to_owned()),
|
||||||
Token::Number(number) => Expression::Literal(Literal::Int(number.parse::<i64>().unwrap())),
|
Token::Number(number) => Expression::Literal(Literal::Int(number.parse::<i64>().unwrap())),
|
||||||
_ => todo!(),
|
_other => {
|
||||||
|
dbg!(&i);
|
||||||
|
dbg!(_other);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
*i += 1;
|
*i += 1;
|
||||||
literal
|
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
|
// TODO: replace parse_math with this recursive function
|
||||||
pub fn parse_expression(tokens: &Vec<Token>, i: &mut usize) -> Expression {
|
pub fn parse_expression(tokens: &Vec<Token>, i: &mut usize) -> Expression {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -103,11 +89,17 @@ pub fn parse_expression(tokens: &Vec<Token>, i: &mut usize) -> Expression {
|
||||||
Unary(Unary),
|
Unary(Unary),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start_i = *i;
|
||||||
let mut in_expressions_and_operators: Vec<OpExpr> = Vec::new();
|
let mut in_expressions_and_operators: Vec<OpExpr> = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
in_expressions_and_operators.push(match &tokens[*i] {
|
in_expressions_and_operators.push(match &tokens[*i] {
|
||||||
Token::OpenParanthesis => OpExpr::Expression(parse_grouping(tokens, i)),
|
Token::OpenParanthesis => {
|
||||||
|
*i += 1;
|
||||||
|
let expr = OpExpr::Expression(parse_expression(tokens, i));
|
||||||
|
*i += 1;
|
||||||
|
expr
|
||||||
|
}
|
||||||
Token::Plus => {
|
Token::Plus => {
|
||||||
*i += 1;
|
*i += 1;
|
||||||
OpExpr::BinOp(BinOp::Plus)
|
OpExpr::BinOp(BinOp::Plus)
|
||||||
|
@ -124,12 +116,123 @@ pub fn parse_expression(tokens: &Vec<Token>, i: &mut usize) -> Expression {
|
||||||
*i += 1;
|
*i += 1;
|
||||||
OpExpr::Unary(Unary::PointerTo)
|
OpExpr::Unary(Unary::PointerTo)
|
||||||
}
|
}
|
||||||
Token::Number(_) => OpExpr::Expression(parse_basic(tokens, i)),
|
Token::Number(_) => {
|
||||||
|
dbg!(OpExpr::Expression(parse_basic(tokens, i)))
|
||||||
|
}
|
||||||
|
Token::Identifier(_) => OpExpr::Expression(parse_basic(tokens, i)),
|
||||||
_other => break,
|
_other => break,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dbg!(in_expressions_and_operators);
|
|
||||||
Expression::Variable("a".to_string())
|
dbg!(&i);
|
||||||
|
dbg!(&in_expressions_and_operators);
|
||||||
|
|
||||||
|
if in_expressions_and_operators.len() == 1 {
|
||||||
|
return match &in_expressions_and_operators.pop().unwrap() {
|
||||||
|
OpExpr::Expression(expression) => expression.to_owned(),
|
||||||
|
_ => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
*i = start_i;
|
||||||
|
|
||||||
|
let prioritizing_order_binops: Vec<Vec<BinOp>> = vec![vec![BinOp::Plus, BinOp::Minus]];
|
||||||
|
|
||||||
|
let prioritizing_order_unaryops: Vec<Vec<Unary>> =
|
||||||
|
vec![vec![Unary::ValueFrom, Unary::PointerTo]];
|
||||||
|
|
||||||
|
let mut ordered_ops: Vec<(usize, bool)> = Vec::new();
|
||||||
|
|
||||||
|
for prioritizing_order in prioritizing_order_binops {
|
||||||
|
for j in (0..in_expressions_and_operators.len()).rev() {
|
||||||
|
let operator = match &in_expressions_and_operators[j] {
|
||||||
|
OpExpr::BinOp(binop) => binop,
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if prioritizing_order.contains(operator) {
|
||||||
|
ordered_ops.push((j, true));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for prioritizing_order in prioritizing_order_unaryops {
|
||||||
|
for j in (0..in_expressions_and_operators.len()).rev() {
|
||||||
|
let operator = match &in_expressions_and_operators[j] {
|
||||||
|
OpExpr::Unary(unary) => unary,
|
||||||
|
_other => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if prioritizing_order.contains(operator) {
|
||||||
|
ordered_ops.push((j, false));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let this_operator = ordered_ops.get(0);
|
||||||
|
|
||||||
|
let this_operator = match this_operator {
|
||||||
|
Some(val) => val.to_owned(),
|
||||||
|
None => return parse_basic(tokens, i),
|
||||||
|
};
|
||||||
|
|
||||||
|
dbg!(this_operator);
|
||||||
|
|
||||||
|
match this_operator {
|
||||||
|
(index, true) => {
|
||||||
|
let mut start_vec = Vec::new();
|
||||||
|
|
||||||
|
for i in 0..(index + *i) {
|
||||||
|
start_vec.push(tokens[i].clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
start_vec.push(Token::Semi);
|
||||||
|
dbg!(&start_vec);
|
||||||
|
|
||||||
|
let start = parse_expression(&start_vec, i);
|
||||||
|
// let start = Expression::Literal(Literal::Int(42));
|
||||||
|
|
||||||
|
dbg!(&start);
|
||||||
|
|
||||||
|
*i += 1;
|
||||||
|
|
||||||
|
dbg!(&i);
|
||||||
|
let end = parse_expression(tokens, i);
|
||||||
|
|
||||||
|
Expression::Binary(
|
||||||
|
match &in_expressions_and_operators[index] {
|
||||||
|
OpExpr::BinOp(binop) => binop.to_owned(),
|
||||||
|
_other => {
|
||||||
|
dbg!(start);
|
||||||
|
dbg!(end);
|
||||||
|
dbg!(_other);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Box::new(start),
|
||||||
|
Box::new(end),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(index, false) => {
|
||||||
|
*i += 1;
|
||||||
|
|
||||||
|
let end = parse_expression(tokens, i);
|
||||||
|
|
||||||
|
Expression::Unary(
|
||||||
|
match &in_expressions_and_operators[index] {
|
||||||
|
OpExpr::Unary(unary) => unary.to_owned(),
|
||||||
|
_other => {
|
||||||
|
dbg!(end);
|
||||||
|
dbg!(_other);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Box::new(end),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_statements(tokens: &Vec<Token>, i: &mut usize) -> Vec<Statement> {
|
fn parse_statements(tokens: &Vec<Token>, i: &mut usize) -> Vec<Statement> {
|
||||||
|
@ -156,13 +259,7 @@ fn parse_statements(tokens: &Vec<Token>, i: &mut usize) -> Vec<Statement> {
|
||||||
};
|
};
|
||||||
|
|
||||||
*i += 1;
|
*i += 1;
|
||||||
|
Statement::VariableDeclaration(name, parse_expression(tokens, i))
|
||||||
let mut declaration_tokens: Vec<Token> = Vec::new();
|
|
||||||
while tokens[*i] != Token::Semi {
|
|
||||||
declaration_tokens.push(tokens[*i].clone());
|
|
||||||
*i += 1;
|
|
||||||
}
|
|
||||||
Statement::VariableDeclaration(name, parse_math(&declaration_tokens))
|
|
||||||
}
|
}
|
||||||
Token::Keyword(Keyword::Assign) => {
|
Token::Keyword(Keyword::Assign) => {
|
||||||
*i += 1;
|
*i += 1;
|
||||||
|
@ -179,39 +276,27 @@ fn parse_statements(tokens: &Vec<Token>, i: &mut usize) -> Vec<Statement> {
|
||||||
|
|
||||||
*i += 1;
|
*i += 1;
|
||||||
|
|
||||||
let mut declaration_tokens: Vec<Token> = Vec::new();
|
Statement::VariableAssignment(name, parse_expression(tokens, i))
|
||||||
while tokens[*i] != Token::Semi {
|
|
||||||
declaration_tokens.push(tokens[*i].clone());
|
|
||||||
*i += 1;
|
|
||||||
}
|
|
||||||
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 arguments: Vec<Expression> = Vec::new();
|
||||||
|
|
||||||
*i += 1;
|
|
||||||
while tokens[*i] != Token::CloseParanthesis {
|
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;
|
|
||||||
}
|
|
||||||
declaration_tokens.push(argument_tokens);
|
|
||||||
*i += 1;
|
*i += 1;
|
||||||
|
if tokens[*i] == Token::CloseParanthesis {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dbg!(&i);
|
||||||
|
dbg!(tokens);
|
||||||
|
dbg!(&tokens[*i]);
|
||||||
|
arguments.push(parse_expression(tokens, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
*i += 1;
|
*i += 1;
|
||||||
|
|
||||||
let mut arguments: Vec<ValueNode> = Vec::new();
|
dbg!(&arguments);
|
||||||
|
|
||||||
for token_vec in &declaration_tokens {
|
|
||||||
if token_vec == &Vec::new() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
arguments.push(parse_math(token_vec));
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::FunctionCall(identifier.to_owned(), arguments)
|
Statement::FunctionCall(identifier.to_owned(), arguments)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue