Skip to content

Commit

Permalink
refactor(parser): add Block struct which contains statements and scope
Browse files Browse the repository at this point in the history
  • Loading branch information
MilkeeyCat committed Aug 27, 2024
1 parent 76624b1 commit 08a4f10
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 40 deletions.
6 changes: 3 additions & 3 deletions src/codegen/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ impl CodeGen {
fn function(&mut self, mut func: StmtFunction) -> Result<(), CodeGenError> {
let offset = self
.arch
.populate_offsets(&mut func.scope.symbol_table, &self.scope)?;
.populate_offsets(&mut func.block.scope.symbol_table, &self.scope)?;

self.scope.enter(*func.scope);
self.scope.enter(func.block.scope);
self.arch.fn_preamble(
&func.name,
&func
Expand All @@ -61,7 +61,7 @@ impl CodeGen {
&self.scope,
)?;

for stmt in func.body {
for stmt in func.block.statements {
self.stmt(stmt)?;
}

Expand Down
2 changes: 1 addition & 1 deletion src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ pub use error::ParserError;
pub use expr::*;
pub use op::{BinOp, CmpOp, OpParseError, UnOp};
pub use parser::Parser;
pub use stmt::{Stmt, StmtFunction, StmtReturn, StmtVarDecl};
pub use stmt::{Block, Stmt, StmtFunction, StmtReturn, StmtVarDecl};
77 changes: 44 additions & 33 deletions src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::{
expr::{ExprBinary, ExprLit, ExprUnary},
precedence::Precedence,
stmt::StmtReturn,
BinOp, Expr, ExprArrayAccess, ExprCast, ExprIdent, ExprStruct, Expression, ParserError, Stmt,
StmtFunction, StmtVarDecl, UIntLitRepr, UnOp,
BinOp, Block, Expr, ExprArrayAccess, ExprCast, ExprIdent, ExprStruct, Expression, ParserError,
Stmt, StmtFunction, StmtVarDecl, UIntLitRepr, UnOp,
};
use crate::{
codegen::Offset,
Expand Down Expand Up @@ -180,9 +180,14 @@ impl Parser {
Ok(())
}

fn compound_statement(&mut self) -> Result<Vec<Stmt>, ParserError> {
fn compound_statement(
&mut self,
context: Option<(String, Type)>,
) -> Result<Block, ParserError> {
let mut stmts = Vec::new();

self.scope
.enter_new(context.unwrap_or_else(|| self.scope.context().unwrap().clone()));
self.expect(&Token::LBrace)?;

while !self.cur_token_is(&Token::RBrace) {
Expand All @@ -209,8 +214,12 @@ impl Parser {
}

self.expect(&Token::RBrace)?;
let scope_impl = self.scope.leave();

Ok(stmts)
Ok(Block {
statements: stmts,
scope: scope_impl,
})
}

fn parse_type(&mut self) -> Result<Type, ParserError> {
Expand Down Expand Up @@ -357,31 +366,15 @@ impl Parser {
return Err(ParserError::ParseType(self.cur_token.to_owned()));
}
};

self.expect(&Token::LParen)?;
self.scope.enter_new((name.clone(), type_.clone()));

let params = self.params(Token::Comma, Token::RParen)?;
for (i, (name, type_)) in params.iter().enumerate() {
self.scope
.symbol_table_mut()
.push(Symbol::Param(SymbolParam {
name: name.to_owned(),
preceding: params[..i]
.iter()
.map(|(_, type_)| type_.to_owned())
.collect(),
type_: type_.to_owned(),
offset: Offset::default(),
}))?;
}
let mut has_body = false;
let body = if self.cur_token_is(&Token::LBrace) {
has_body = true;
self.compound_statement()?
let block = if self.cur_token_is(&Token::LBrace) {
Some(self.compound_statement(Some((name.clone(), type_.clone())))?)
} else {
Vec::new()
None
};
let scope_impl = self.scope.leave();
self.scope
.symbol_table_mut()
.push(Symbol::Function(SymbolFunction {
Expand All @@ -390,21 +383,32 @@ impl Parser {
parameters: params.clone().into_iter().map(|(_, type_)| type_).collect(),
}))?;

if has_body & !func_definition {
if block.is_some() & !func_definition {
panic!("Function definition is not supported here");
}

if !has_body {
self.expect(&Token::Semicolon)?;
Ok(None)
} else {
if let Some(mut block) = block {
for (i, (name, type_)) in params.iter().enumerate() {
block.scope.symbol_table.push(Symbol::Param(SymbolParam {
name: name.to_owned(),
preceding: params[..i]
.iter()
.map(|(_, type_)| type_.to_owned())
.collect(),
type_: type_.to_owned(),
offset: Offset::default(),
}))?;
}

Ok(Some(Stmt::Function(StmtFunction {
return_type: type_,
name,
params,
body,
scope: Box::new(scope_impl),
block,
})))
} else {
self.expect(&Token::Semicolon)?;
Ok(None)
}
}

Expand Down Expand Up @@ -806,8 +810,15 @@ mod test {

for (input, expected) in tests {
let mut parser = Parser::new(Lexer::new(input.to_string())).unwrap();
let ast = parser.compound_statement().unwrap();
assert_eq!(&ast, &expected, "expected: {:?}, got: {:?}", expected, ast);
let ast = parser
.compound_statement(Some(("".to_string(), Type::Void)))
.unwrap();

assert_eq!(
&ast.statements, &expected,
"expected: {:?}, got: {:?}",
expected, ast
);
}

Ok(())
Expand Down
9 changes: 7 additions & 2 deletions src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ pub enum Stmt {
Return(StmtReturn),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Block {
pub statements: Vec<Stmt>,
pub scope: ScopeImpl,
}

#[derive(Debug, Clone, PartialEq)]
pub struct StmtVarDecl {
pub type_: Type,
Expand All @@ -33,6 +39,5 @@ pub struct StmtFunction {
pub return_type: Type,
pub name: String,
pub params: Vec<(String, Type)>,
pub body: Vec<Stmt>,
pub scope: Box<ScopeImpl>,
pub block: Block,
}
2 changes: 1 addition & 1 deletion src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl Scope {
&mut self.0.last_mut().unwrap().type_table
}

pub fn context(&mut self) -> Option<&(String, Type)> {
pub fn context(&self) -> Option<&(String, Type)> {
self.0.last().unwrap().context.as_ref()
}

Expand Down

0 comments on commit 08a4f10

Please sign in to comment.