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:
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user