A tree-walk interpreter for the Lox programming language, built in Java following the book Crafting Interpreters by Robert Nystrom.
Chapter 11: Resolving and Binding The interpreter now includes a semantic analysis pass (Resolver) that resolves variable bindings before execution, fixing closure semantics and enabling static error detection.
- Scanning, parsing, and tree-walk interpretation
- Variables, scopes, and block environments
- Control flow:
if,while,for,break,continue - Functions, closures, and recursion
- Lambda expressions
- Resolver for static variable resolution and closure correctness
- Unused variable detection (reports error for unused local variables)
- Index-based environment lookup for faster variable access
The project follows a classic interpreter pipeline:
-
Scanner (
Scanner.java)- Converts raw source code into a stream of
Tokens. - Handles keywords, literals, and operators.
- Converts raw source code into a stream of
-
Parser (
Parser.java)- Recursive Descent Parser that constructs an Abstract Syntax Tree (AST).
- Handles operator precedence, error synchronization, and statement parsing.
-
AST (
Expr.java,Stmt.java)- Represents the code structure (expressions and statements).
- Uses the Visitor Pattern for operations like printing (
AstPrinter) and evaluation (Interpreter).
-
Resolver (
Resolver.java)- Performs a static analysis pass over the AST before execution.
- Resolves each variable to its exact scope depth and index.
- Detects errors such as
returnoutside functions,break/continueoutside loops, and unused local variables.
-
Interpreter (
Interpreter.java)- Traverses the AST recursively to execute code.
- Uses pre-resolved variable locations for correct and efficient lookup.
-
Environment (
Environment.java,GlobalEnvironment.java)- Local environments use an index-based
List<Object>for fast variable access. - Global environment uses a
Map<String, Object>for named variable lookup.
- Local environments use an index-based
src/lox/
├── Lox.java # Entry point (REPL & Script runner)
├── Scanner.java # Lexical Analysis
├── Token.java # Token definition
├── TokenType.java # Enum of token types
├── Parser.java # Syntax Analysis
├── Expr.java # AST Expression Node definitions
├── Stmt.java # AST Statement Node definitions
├── Resolver.java # Semantic Analysis & Variable Resolution
├── Interpreter.java # Evaluation logic
├── Environment.java # Local scope management (index-based)
├── GlobalEnvironment.java # Global scope management (name-based)
├── LoxCallable.java # Callable interface
├── LoxFunction.java # Function representation
├── BreakException.java # Break control flow
├── ContinueException.java # Continue control flow
├── Return.java # Return control flow
└── AstPrinter.java # Debug utility to print AST
java lox.Lox script.loxjava lox.Lox
> var a = 1;
> var b = 2;
> print a + b;
3