Add statement parsing with error recovery

- ast.rs: add Type, Block, ElseBranch, Stmt, StmtKind
- parser.rs: parse_type, parse_block, parse_stmt and all sub-parsers;
  missing-token insertion via expect(), synchronize() for panic-mode
  recovery on non-startable tokens; 26 new tests (62 total)
- main.rs: REPL now parses statements instead of bare expressions
This commit is contained in:
2026-03-10 17:55:22 +01:00
parent becc7a2d34
commit d556a54541
3 changed files with 645 additions and 4 deletions

View File

@@ -35,6 +35,38 @@ pub enum BinaryOp {
Rem, // `%`
}
// ── Types ──────────────────────────────────────────────────────────────────────
#[derive(Debug, Clone)]
pub enum Type {
// Unsigned integers
U8,
U16,
U32,
U64,
// Signed integers
I8,
I16,
I32,
I64,
// Floating-point
F32,
F64,
// Other primitives
Bool,
Char,
// User-defined named type (e.g. a struct)
Named(String, Span),
// Typed pointer: `*type`
Pointer(Box<Type>),
// Opaque (untyped) pointer: `*opaque`
OpaquePointer,
// Fixed-size array: `[type; INT_LIT]`
Array { elem: Box<Type>, size: String },
// Error placeholder for recovery
Error,
}
// ── Struct literal field ───────────────────────────────────────────────────────
#[derive(Debug, Clone)]
@@ -111,3 +143,61 @@ pub enum ExprKind {
// Placeholder for parse errors — allows parsing to continue
Error,
}
// ── Block ──────────────────────────────────────────────────────────────────────
#[derive(Debug, Clone)]
pub struct Block {
pub stmts: Vec<Stmt>,
pub span: Span,
}
// ── Else branch ───────────────────────────────────────────────────────────────
#[derive(Debug, Clone)]
pub enum ElseBranch {
If(Box<Stmt>), // `else if …`
Block(Block), // `else { … }`
}
// ── Statement ─────────────────────────────────────────────────────────────────
#[derive(Debug, Clone)]
pub struct Stmt {
pub kind: StmtKind,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum StmtKind {
/// `let [mut] name [: type] [= expr] ;`
Let {
mutable: bool,
name: String,
name_span: Span,
ty: Option<Type>,
init: Option<Expr>,
},
/// `return [expr] ;`
Return(Option<Expr>),
/// `if expr_ns block [else else_branch]`
If {
cond: Expr,
then_block: Block,
else_branch: Option<ElseBranch>,
},
/// `while expr_ns block`
While { cond: Expr, body: Block },
/// `loop block`
Loop { body: Block },
/// `break ;`
Break,
/// `continue ;`
Continue,
/// `{ stmts }`
Block(Block),
/// `expr ;`
Expr(Expr),
/// Error placeholder — emitted during recovery so the parent can continue.
Error,
}