warming up your workspace

Python practice in Compilers & Interpreters

Browse the rooms before signing in. Opening a room requires an account and follows your existing access. Practice does not issue certificates.

  • Classify the Character

    Every scanner begins by asking what it is looking at. Decide whether a single character is a digit, the first question the lexer asks of every byte.

    characters. Free room.

  • Name the Operator

    The parser branches on token TYPES, not raw characters. Map a punctuation character to its operator name, the lexer's little dictionary.

    operators. Free room.

  • Scan the Line

    Put the scanner together: turn a line of source into a list of tokens, skipping the spaces that carry no meaning. The front door of every interpreter.

    scanner. Free room.

  • Spot the Keyword

    Names and reserved words look identical until the word is complete. Decide whether a finished word is one of the language's keywords.

    words. Free room.

  • Apply the Operator

    The evaluator's smallest step: given an operator and two numbers, compute the result. The atom of every arithmetic answer.

    evaluate. Account access required.

  • Print the Tree

    To debug a parser you read its trees back. Pretty-print an AST as a Lisp-style s-expression, so '1 + 2 * 3' becomes (+ 1 (* 2 3)).

    printer. Account access required.

  • Rank the Operators

    Pratt parsing replaces a function-per-level with one number per operator. Return an operator's binding power, the key that makes precedence work in a single loop.

    pratt. Account access required.

  • Walk the Tree

    An expression is a tree; its value is found by walking it. Evaluate a binary AST node by evaluating its children and combining them, the heart of a tree-walker.

    evaluate. Account access required.

  • Decide the Truth

    Every language draws its own line between true and false. Implement this one's rule: only nil and false are falsey, everything else (even 0) is truthy.

    truthiness. Account access required.

  • Desugar the Loop

    A for loop is not a new idea, just sugar. Rewrite it as an initializer, a while, and an increment, so the existing machinery runs it.

    control-flow. Account access required.

  • Look It Up

    Variables live in a chain of scopes. Resolve a name by walking the environment from innermost to outermost, the lookup that makes shadowing work.

    environment. Account access required.

  • Run the Loop

    Loops compute real results. Run a counting loop that sums 1 through n, the kind of program your interpreter exists to execute.

    control-flow. Account access required.

  • Bind the Arguments

    Calling a function opens a new scope binding each parameter to its argument. Build that frame, pushing a fresh scope onto the function's closure.

    functions. Account access required.

  • Call Yourself

    Recursion works because a function can find its own name in the scope it captured. Compute a factorial recursively, the canonical proof that it works.

    functions. Account access required.

  • Recover from the Error

    After a syntax error the parser cannot trust the next tokens, so it skips to a statement boundary and resumes. Synchronize the cursor past the next semicolon.

    resolving. Account access required.

  • Resolve the Depth

    Before running, the resolver pins each variable to a scope distance. Return how many scopes out a name lives, or -1 if it is global.

    resolving. Account access required.

  • Compile to Bytecode

    The second backend: walk the AST in post-order, emitting instructions so both operands sit on the stack before their operator runs. Compile an arithmetic tree.

    bytecode. Account access required.

  • Recurse for Real

    The whole language at work: compute Fibonacci with a doubly-recursive function, the program that exercises calls, returns, and the call stack all at once.

    mini-language. Account access required.

  • Run the Machine

    Execute bytecode on a stack VM: constants push, arithmetic pops two and pushes one. Run a whole chunk and return the value left on top.

    bytecode. Account access required.

  • Ship the Interpreter

    The finale: a self-contained interpreter that runs a counting program. The whole pipeline, lex, parse, evaluate, in one function that returns the printed output.

    mini-language. Account access required.