Browse Source

Generalize block into own statement

github-actions
Garrit Franke 3 years ago
parent
commit
b23a9bd751
  1. 1
      TODO
  2. 33
      src/generator/js.rs
  3. 17
      src/generator/x86.rs
  4. 43
      src/parser/mod.rs
  5. 5
      src/parser/node_type.rs

1
TODO

@ -11,5 +11,4 @@
# Cleanups
- Generalize function/if/loop bodies into a "Block" node to remove redundancy
- Improve error reporting (See ./util/string_util::highlight_position_in_file)

33
src/generator/js.rs

@ -27,15 +27,26 @@ fn generate_function(func: Function) -> String {
.join(", ");
let mut raw = format!("function {N}({A})", N = func.name, A = arguments);
raw += " {\n";
raw += &generate_block(func.body);
for statement in func.statements {
raw += &generate_statement(statement);
raw
}
fn generate_block(block: Statement) -> String {
let mut generated = String::from("{\n");
let statements = match block {
Statement::Block(blk) => blk,
_ => panic!("Block body should be of type Statement::Block"),
};
for statement in statements {
generated += &generate_statement(statement);
}
raw += "}\n";
generated += "}\n";
raw
generated
}
fn generate_statement(statement: Statement) -> String {
@ -44,8 +55,9 @@ fn generate_statement(statement: Statement) -> String {
Statement::Declare(name, val) => generate_declare(name.name, val),
Statement::Exp(val) => generate_expression(val),
Statement::If(expr, if_state, else_state) => {
generate_conditional(expr, if_state, else_state.map(|x| *x))
generate_conditional(expr, *if_state, else_state.map(|x| *x))
}
Statement::Block(_) => generate_block(statement),
Statement::While(_, _) => todo!(),
}
}
@ -63,15 +75,20 @@ fn generate_expression(expr: Expression) -> String {
fn generate_conditional(
expr: Expression,
if_state: Vec<Statement>,
if_state: Statement,
else_state: Option<Statement>,
) -> String {
let expr_str = generate_expression(expr);
let body = match if_state {
Statement::Block(blk) => blk,
_ => panic!("Conditional body should be of type block"),
};
let mut outcome = format!("if ({})", expr_str);
outcome += "{\n";
for statement in if_state {
for statement in body {
outcome += &generate_statement(statement);
}
outcome += "}";

17
src/generator/x86.rs

@ -67,13 +67,16 @@ impl X86Generator {
fn gen_function(&mut self, func: Function) -> Assembly {
let mut asm = Assembly::new();
let has_return: bool = func.statements.iter().any(|s| {
if let Statement::Return(_) = *s {
true
} else {
false
}
});
let has_return: bool = match &func.body {
Statement::Block(statements) => statements.iter().any(|s| {
if let Statement::Return(_) = *s {
true
} else {
false
}
}),
_ => panic!("Function body should be of type Block"),
};
asm.add(format!(".globl _{}", func.name));
asm.add(format!("_{}:", func.name));

43
src/parser/mod.rs

@ -148,6 +148,22 @@ impl Parser {
})
}
fn parse_block(&mut self) -> Result<Statement, String> {
self.match_token(TokenKind::CurlyBracesOpen)?;
let mut statements = vec![];
while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) {
let statement = self.parse_statement()?;
dbg!("{:?}", &statement);
statements.push(statement);
}
self.match_token(TokenKind::CurlyBracesClose)?;
Ok(Statement::Block(statements))
}
fn parse_function(&mut self) -> Result<Function, String> {
self.match_keyword(Keyword::Function)?;
let name = self.match_identifier()?;
@ -162,22 +178,13 @@ impl Parser {
};
self.match_token(TokenKind::BraceClose)?;
self.match_token(TokenKind::CurlyBracesOpen)?;
let mut statements = vec![];
while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) {
let statement = self.parse_statement()?;
dbg!("{:?}", &statement);
statements.push(statement);
}
self.match_token(TokenKind::CurlyBracesClose)?;
let body = self.parse_block()?;
Ok(Function {
name: name,
arguments: arguments,
statements: statements,
body: body,
})
}
@ -305,27 +312,19 @@ impl Parser {
fn parse_conditional_statement(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::If)?;
let condition = self.parse_expression()?;
self.match_token(TokenKind::CurlyBracesOpen)?;
let mut statements = Vec::new();
while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) {
let statement = self.parse_statement()?;
dbg!("{:?}", &statement);
statements.push(statement);
}
self.match_token(TokenKind::CurlyBracesClose)?;
let body = self.parse_block()?;
match self.peek() {
Some(tok) if tok.kind == TokenKind::Keyword(Keyword::Else) => {
self.next_token();
Ok(Statement::If(
condition,
statements,
Box::new(body),
Some(Box::new(self.parse_conditional_statement()?)),
))
}
_ => Ok(Statement::If(condition, statements, None)),
_ => Ok(Statement::If(condition, Box::new(body), None)),
}
}

5
src/parser/node_type.rs

@ -11,7 +11,7 @@ pub struct Program {
pub struct Function {
pub name: String,
pub arguments: Vec<Variable>,
pub statements: Vec<Statement>,
pub body: Statement,
}
#[derive(Debug, Eq, PartialEq)]
@ -21,9 +21,10 @@ pub struct Variable {
#[derive(Debug, Eq, PartialEq)]
pub enum Statement {
Block(Vec<Statement>),
Declare(Variable, Option<Expression>),
Return(Option<Expression>),
If(Expression, Vec<Statement>, Option<Box<Statement>>),
If(Expression, Box<Statement>, Option<Box<Statement>>),
While(Expression, Box<Statement>),
Exp(Expression),
}

Loading…
Cancel
Save