diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 7478c7a..5256592 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -56,53 +56,55 @@ pub enum Postfix { #[derive(Debug, Clone, Serialize)] pub enum Statement { - // expr; Expression(Expression), - - // { ... } Block(Block), - // let/const/var x = ... - VarDecl { - mutable: bool, - name: String, - init: Option, - type_: Option, - }, + VarDecl(VarDeclStmt), + VarAssign(VarAssignStmt), + If(IfStmt), + While(WhileStmt), + For(ForStmt), - VarAssign { - target: Expression, - value: Expression, - }, - - // if (...) stmt else stmt - If { - condition: Expression, - then_branch: Box, - else_branch: Option>, - }, - - // while (...) stmt - While { - condition: Expression, - body: Box, - }, - - // for (...) stmt - For { - init: (bool, String, Option), - condition: Option, - update: Option>, - body: Box, - }, - - // return expr?; Return(Option), - Break, Continue, } +#[derive(Debug, Clone, Serialize)] +pub struct VarDeclStmt { + pub mutable: bool, + pub name: String, + pub init: Option, + pub type_: Option, +} + +#[derive(Debug, Clone, Serialize)] +pub struct VarAssignStmt { + pub target: Expression, + pub value: Expression, +} + +#[derive(Debug, Clone, Serialize)] +pub struct IfStmt { + pub condition: Expression, + pub then_branch: Box, + pub else_branch: Option>, +} + +#[derive(Debug, Clone, Serialize)] +pub struct WhileStmt { + pub condition: Expression, + pub body: Box, +} + +#[derive(Debug, Clone, Serialize)] +pub struct ForStmt { + pub init: (bool, String, Option), + pub condition: Option, + pub update: Option>, + pub body: Box, +} + #[derive(Debug, Clone, Serialize)] pub enum Expression { Identifier(String), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 0be7182..c08f422 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -11,19 +11,23 @@ boolean = { "true" | "false" } string_lit = { "\"" ~ inner_str ~ "\"" } inner_str = @{ (!"\"" ~ ANY)* } +export = { "public" } +mutable = { "mut" } +var_decl = { type_expr ~ mutable? ~ identifier } + // ================= TOP LEVEL ================= top_level = _{ import | function_decl | struct_decl } -export = { "public" } - import = { "import" ~ string_lit ~ ";" } -param_list = { param ~ ("," ~ param)* ~ ","? } -param = { export? ~ type_expr ~ identifier } +field_list = { field ~ ("," ~ field)* ~ ","? } +field = { export? ~ type_expr ~ identifier } + +param_list = { var_decl ~ ("," ~ var_decl)* ~ ","? } struct_decl = { - export? ~ "struct" ~ identifier ~ "{" ~ param_list? ~ "}" + export? ~ "struct" ~ identifier ~ "{" ~ field_list? ~ "}" } function_decl = { @@ -38,11 +42,9 @@ statement_list = { statement* } statement = _{ expr_stmt - | var_decl - | var_assign + | var_decl_statement | if_stmt | while_stmt - | for_stmt | return_stmt | break_stmt | continue_stmt @@ -59,19 +61,7 @@ break_stmt = { "break" ~ ";" } continue_stmt = { "continue" ~ ";" } -// --- variable declarations --- - -// var_decl_kind = { "let" | "const" | "var" } - -var_decl = { - type_expr ~ identifier ~ ("=" ~ expr)? ~ ";" -} - -var_assign = { - expr ~ "=" ~ expr ~ ";" -} - -// --- control flow --- +var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ ";" } if_stmt = { "if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)? @@ -81,14 +71,6 @@ while_stmt = { "while" ~ "(" ~ expr ~ ")" ~ statement } -for_stmt = { - "for" ~ "(" ~ var_decl ~ expr ~ ";" ~ var_assign_no_semicolon ~ ")" ~ statement -} - -var_assign_no_semicolon = { - expr ~ "=" ~ expr -} - // ================= EXPRESSIONS ================= type_expr = { identifier } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e9e15b8..3ab17af 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -17,6 +17,8 @@ pub type ParseError = pest::error::Error; pub fn parse(source: &str) -> Result, ParseError> { let mut pairs = MistParser::parse(Rule::program, source)?; + println!("{pairs:#?}"); + let mut statements = vec![]; for pair in pairs.next().unwrap().into_inner() { @@ -180,19 +182,27 @@ impl From> for Statement { Rule::block => Statement::Block(Block::from(pair.into_inner().next().unwrap())), - Rule::var_decl => { + Rule::var_decl_statement => { let mut inner = pair.into_inner(); - let type_ = inner.next().map(TypeExpr::try_from).unwrap().ok(); - let name = inner.next().unwrap().as_str().to_string(); + let mut var_decl = inner.next().unwrap().into_inner(); + + let type_ = var_decl.next().map(TypeExpr::try_from).unwrap().ok(); + let mutable = if var_decl.peek().unwrap().as_rule() == Rule::mutable { + var_decl.next(); + true + } else { + false + }; + let name = var_decl.next().unwrap().as_str().to_string(); let init = inner.next().map(Expression::from); - Statement::VarDecl { - mutable: false, + Statement::VarDecl(VarDeclStmt { + mutable, name: name.as_str().to_string(), init, type_, - } + }) } Rule::return_stmt => { @@ -215,11 +225,11 @@ impl From> for Statement { let else_branch = inner.next().map(Statement::from); - Statement::If { + Statement::If(IfStmt { condition, then_branch: Box::new(then_branch), else_branch: else_branch.map(Box::new), - } + }) } Rule::while_stmt => { @@ -228,53 +238,10 @@ impl From> for Statement { let condition = Expression::from(inner.next().unwrap()); let body = Statement::from(inner.next().unwrap()); - Statement::While { + Statement::While(WhileStmt { condition, body: Box::new(body), - } - } - - Rule::for_stmt => { - let mut inner = pair.into_inner(); - - let init = inner - .next() - .map(|p| match p.as_rule() { - Rule::var_decl => { - let mut it = p.into_inner(); - - let name = it.next().unwrap().as_str().to_string(); - let init_expr = it - .next() - .map(|e| Expression::from(e.into_inner().next().unwrap())); - - (false, name, init_expr) - } - _ => unimplemented!( - "For loop init parsing not implemented yet: {:?}", - p.as_rule() - ), - }) - .unwrap(); - - let condition = inner.next().map(Expression::from); - let update = inner.next().map(parse_var_assign_no_semicolon); - let body = Statement::from(inner.next().unwrap()); - - Statement::For { - init, - condition, - update: update.map(Box::new), - body: Box::new(body), - } - } - - Rule::var_assign => { - let mut inner = pair.into_inner(); - let target = Expression::from(inner.next().unwrap()); - let value = Expression::from(inner.next().unwrap()); - - Statement::VarAssign { target, value } + }) } _ => unimplemented!( @@ -381,11 +348,3 @@ impl From> for Postfix { } } } - -fn parse_var_assign_no_semicolon(pair: pest::iterators::Pair) -> Statement { - let mut inner = pair.into_inner(); - let target = Expression::from(inner.next().unwrap()); - let value = Expression::from(inner.next().unwrap()); - - Statement::VarAssign { target, value } -} diff --git a/src/codegen.rs b/src/codegen.rs index 04dcfce..7c8330f 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,4 +1,7 @@ -use parser::ast::{BinaryOp, Block, Expression, Postfix, Statement, TopLevel, TypeExpr}; +use parser::ast::{ + BinaryOp, Block, Expression, IfStmt, Postfix, Statement, TopLevel, TypeExpr, VarAssignStmt, + VarDeclStmt, WhileStmt, +}; pub struct RustCodegen { output: String, @@ -128,12 +131,12 @@ impl RustCodegen { self.add_indentedln("}"); } - Statement::VarDecl { + Statement::VarDecl(VarDeclStmt { mutable, name, init, type_, - } => { + }) => { let mutability = if *mutable { "mut " } else { "" }; let ty = type_ @@ -149,7 +152,7 @@ impl RustCodegen { self.add_indentedln(&format!("let {}{}{}{};", mutability, name, ty, init)); } - Statement::VarAssign { target, value } => { + Statement::VarAssign(VarAssignStmt { target, value }) => { self.add_indentedln(&format!( "{} = {};", self.generate_expression(target), @@ -157,11 +160,11 @@ impl RustCodegen { )); } - Statement::If { + Statement::If(IfStmt { condition, then_branch, else_branch, - } => { + }) => { self.add_indentedln(&format!("if {} {{", self.generate_expression(condition))); self.indent += 1; @@ -179,7 +182,7 @@ impl RustCodegen { } } - Statement::While { condition, body } => { + Statement::While(WhileStmt { condition, body }) => { self.add_indentedln(&format!("while {} {{", self.generate_expression(condition))); self.indent += 1; diff --git a/test/src/main.mist b/test/src/main.mist index 8df4404..a4ec76f 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,9 +1,3 @@ -public struct Idk { - int a, - int b, -} - -int test(int a, int b) { - Idk bro = Idk { a: 10, b: 10 }; - return a + b + bro.a; +int test() { + int mut a = 10; }