This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize
for the AI-speak, we are working on rewriting it!
The program’s map: every function and which calls which.
There’s no recorded run of this program yet.
This program declares a record type (Node), and records run only in compiled C for now, so the Run buttons here are off. Open it in the workbench and use its C tab to compile it.
Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.
[1]lines 1–516
# The parser: tokens in, an abstract syntax tree out.## A recursive-descent parser: one def per rule of the grammar, each reading# tokens from the front and returning the node it built. The nodes live in# one array, the arena; a node names its children by their index in it.# Every parse def takes the parser state and returns the new state and the# index of the node it made: `p, n = expr(p)`.## The grammar so far:## program = function* eof# function = "int" ident "(" params? ")" "{" compound_stmt# params = "int" ident ("," "int" ident)*# declaration = "int" ident ("=" expr)? ("," ident ("=" expr)?)* ";"# stmt = "return" expr ";"# | "if" "(" expr ")" stmt ("else" stmt)?# | "for" "(" expr? ";" expr? ";" expr? ")" stmt# | "while" "(" expr ")" stmt# | "{" compound_stmt# | expr? ";"# compound_stmt = (declaration | stmt)* "}"# expr = assign# assign = logor ("=" assign)?# logor = logand ("||" logand)*# logand = equality ("&&" equality)*# equality = relational ("==" relational | "!=" relational)*# relational = add ("<" add | "<=" add | ">" add | ">=" add)*# add = mul ("+" mul | "-" mul)*# mul = unary ("*" unary | "/" unary | "%" unary)*# unary = ("+" | "-" | "!") unary | primary# primary = "(" expr ")" | ident "(" args? ")" | ident | num# args = assign ("," assign)*## Precedence comes from the nesting: mul is called from add, so * binds# tighter than +.from cc.lexer import Token, TokKind, tokenize
enum NodeKind {
Num# an integer literal: val
Add # lhs + rhs
Sub # lhs - rhs
Mul # lhs * rhs
Div # lhs / rhs
Mod # lhs % rhs
Neg # -lhs
Not # !lhs: 1 when lhs is 0, else 0
LogAnd # lhs && rhs: rhs is computed only when lhs is not 0
LogOr # lhs || rhs: rhs is computed only when lhs is 0
Eq # lhs == rhs: 1 or 0
Ne # lhs != rhs
Lt # lhs < rhs
Le # lhs <= rhs (a > b and a >= b are made as b < a and b <= a)
Var # a local variable: val is its slot in the function's locals
Assign # lhs = rhs, lhs a Var
Call # name(args): a call; body holds the argument expressions
ExprStmt # lhs ";": an expression computed for its effect
Return # "return" lhs ";"
If # "if" (cond) then (else els)?
For # "for" (init; cond; inc) then, and "while" (cond) then