Parsing Programs: Declarations and Statements
Lesson, slides, and applied problem sets.
View SlidesLesson
Parsing Programs: Declarations and Statements
Why this module exists
We already know how to parse expressions. Now we need to parse programs: a list of declarations and statements. This is the step that turns a single expression parser into a real language front end.
1) Program grammar (v2)
program -> decl* EOF
decl -> funDecl | stmt
funDecl -> "fn" IDENT "(" params? ")" block
params -> IDENT ("," IDENT)*
stmt -> varDecl
| ifStmt
| whileStmt
| returnStmt
| block
| assignStmt
| exprStmt
varDecl -> ("let" | "var" | "const") IDENT ("=" expr)? ";"
assignStmt -> IDENT "=" expr ";"
exprStmt -> expr ";"
block -> "{" stmt* "}"
ifStmt -> "if" "(" expr ")" block ("else" block)?
whileStmt -> "while" "(" expr ")" block
returnStmt -> "return" expr? ";"
We still use the same expression grammar from earlier modules.
2) Structure over cleverness
Parse statements with small, direct functions:
parseDeclfor top-levelparseStmtfor statements- one function per statement kind
Readable control flow beats clever tricks here.
3) AST shape
We keep a single Stmt struct with a Kind enum and explicit fields (Name, Expr, Body, Else, Params). This is easy to inspect and extend.
4) Errors
Good parse errors are precise:
- "expected ';' after expression"
- "expected ')' after condition"
The error message should help the learner fix the input quickly.