Statements

This commit is contained in:
2026-04-14 04:38:56 +02:00
parent 6c46c1f0bb
commit 3223a8c854
4 changed files with 221 additions and 10 deletions
+63 -8
View File
@@ -1,5 +1,11 @@
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct ParamList(pub Vec<(String, TypeExpr)>);
#[derive(Debug, Clone, Serialize)]
pub struct Block(pub Vec<Statement>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")] #[serde(tag = "type", content = "value")]
pub enum TypeExpr { pub enum TypeExpr {
@@ -24,10 +30,55 @@ pub enum TopLevel {
}, },
} }
#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum Postfix {
FieldAccess(String),
FunctionCall(Vec<Expression>),
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")] #[serde(tag = "type", content = "value")]
pub enum Statement { pub enum Statement {
// expr;
Expression(Expression), Expression(Expression),
// { ... }
Block(Block),
// let/const/var x = ...
VarDecl {
kind: VarKind,
name: String,
init: Option<Expression>,
},
// if (...) stmt else stmt
If {
condition: Expression,
then_branch: Box<Statement>,
else_branch: Option<Box<Statement>>,
},
// while (...) stmt
While {
condition: Expression,
body: Box<Statement>,
},
// for (...) stmt
For {
init: Option<ForInit>,
condition: Option<Expression>,
update: Option<Expression>,
body: Box<Statement>,
},
// return expr?;
Return(Option<Expression>),
Break,
Continue,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
@@ -45,14 +96,18 @@ pub enum Expression {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "value")] pub enum VarKind {
pub enum Postfix { Let,
FieldAccess(String), Const,
FunctionCall(Vec<Expression>), Var,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct ParamList(pub Vec<(String, TypeExpr)>); pub enum ForInit {
VarDecl {
#[derive(Debug, Clone, Serialize)] kind: VarKind,
pub struct Block(pub Vec<Statement>); name: String,
init: Option<Expression>,
},
Expr(Expression),
}
+47 -1
View File
@@ -36,10 +36,56 @@ block = { "{" ~ statement_list ~ "}" }
statement_list = { statement* } statement_list = { statement* }
statement = _{ expr_stmt } statement = _{
expr_stmt
| var_decl
| if_stmt
| while_stmt
| for_stmt
| return_stmt
| break_stmt
| continue_stmt
| block
}
// --- basic statements ---
expr_stmt = { expr ~ ";" } expr_stmt = { expr ~ ";" }
return_stmt = { "return" ~ expr? ~ ";" }
break_stmt = { "break" ~ ";" }
continue_stmt = { "continue" ~ ";" }
// --- variable declarations ---
var_decl = {
("let" | "const" | "var") ~ identifier ~ ("=" ~ expr)? ~ ";"
}
// --- control flow ---
if_stmt = {
"if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)?
}
while_stmt = {
"while" ~ "(" ~ expr ~ ")" ~ statement
}
for_stmt = {
"for" ~ "(" ~ (var_decl_no_semicolon | expr_stmt | ";")
~ expr? ~ ";"
~ expr? ~ ")"
~ statement
}
// helper (same as var_decl but no trailing ;)
var_decl_no_semicolon = {
("let" | "const" | "var") ~ identifier ~ ("=" ~ expr)?
}
// ================= EXPRESSIONS ================= // ================= EXPRESSIONS =================
type_expr = { identifier } type_expr = { identifier }
+108
View File
@@ -154,10 +154,118 @@ impl Statement {
let inner = pair.into_inner().next().unwrap(); let inner = pair.into_inner().next().unwrap();
Statement::from_pair(inner) Statement::from_pair(inner)
} }
Rule::expr_stmt => { Rule::expr_stmt => {
let expr_pair = pair.into_inner().next().unwrap(); let expr_pair = pair.into_inner().next().unwrap();
Statement::Expression(Expression::from_pair(expr_pair)) Statement::Expression(Expression::from_pair(expr_pair))
} }
Rule::block => Statement::Block(Block::from_pair(pair.into_inner().next().unwrap())),
Rule::var_decl => {
let mut inner = pair.into_inner();
let kind_pair = inner.next().unwrap(); // let/const/var
let name_pair = inner.next().unwrap(); // identifier
let init = inner.next().map(|expr_pair| {
// expects "=" expr
Expression::from_pair(expr_pair.into_inner().next().unwrap())
});
let kind = match kind_pair.as_str() {
"let" => VarKind::Let,
"const" => VarKind::Const,
"var" => VarKind::Var,
_ => unreachable!(),
};
Statement::VarDecl {
kind,
name: name_pair.as_str().to_string(),
init,
}
}
Rule::return_stmt => {
let mut inner = pair.into_inner();
let expr = inner.next().map(Expression::from_pair);
Statement::Return(expr)
}
Rule::break_stmt => Statement::Break,
Rule::continue_stmt => Statement::Continue,
Rule::if_stmt => {
let mut inner = pair.into_inner();
let condition = Expression::from_pair(inner.next().unwrap());
let then_branch = Statement::from_pair(inner.next().unwrap());
let else_branch = inner.next().map(Statement::from_pair);
Statement::If {
condition,
then_branch: Box::new(then_branch),
else_branch: else_branch.map(Box::new),
}
}
Rule::while_stmt => {
let mut inner = pair.into_inner();
let condition = Expression::from_pair(inner.next().unwrap());
let body = Statement::from_pair(inner.next().unwrap());
Statement::While {
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_no_semicolon => {
let mut it = p.into_inner();
let kind = match it.next().unwrap().as_str() {
"let" => VarKind::Let,
"const" => VarKind::Const,
"var" => VarKind::Var,
_ => unreachable!(),
};
let name = it.next().unwrap().as_str().to_string();
let init_expr = it
.next()
.map(|e| Expression::from_pair(e.into_inner().next().unwrap()));
ForInit::VarDecl {
kind,
name,
init: init_expr,
}
}
_ => ForInit::Expr(Expression::from_pair(p)),
});
let condition = inner.next().map(Expression::from_pair);
let update = inner.next().map(Expression::from_pair);
let body = Statement::from_pair(inner.next().unwrap());
Statement::For {
init,
condition,
update,
body: Box::new(body),
}
}
_ => unimplemented!( _ => unimplemented!(
"Statement parsing not implemented yet: {:?}", "Statement parsing not implemented yet: {:?}",
pair.as_rule() pair.as_rule()
+3 -1
View File
@@ -6,5 +6,7 @@ struct Point {
} }
function add(a: int, b: int): int { function add(a: int, b: int): int {
idk.do_something(123, "abc"); if (x) {
if (y) return 1;
}
} }