An implementation of the tree-walking interpreter from Crafting Interpreters written in Go.
To install, run:
go get github.com/chidiwilliams/glox
To start a new REPL session:
glox
To run a Lox file:
glox -filePath [filePath]
glox implements the original Lox definition as well as some features from the Challenges sections in the book: series expressions, function expressions, anonymous functions, and getter methods.
Here's the full parser grammar:
program => declaration* EOF
declaration => classDecl | funcDecl | varDecl | statement
classDecl => "class" IDENTIFIER ( "<" IDENTIFIER )? "{" function* "}"
funDecl => "fun" function
function => IDENTIFIER "(" parameters? ")" block
parameters => IDENTIFIER ( "," IDENTIFIER )*
varDecl => "var" IDENTIFIER ( "=" expression )? ";"
statement => exprStmt | ifStmt | forStmt | printStmt | returnStmt | whileStmt
| breakStmt | continueStmt | block
exprStmt => expression ";"
ifStmt => "if" "(" expression ")" statement ( "else" statement )?
forStmt => "for" "(" ( varDecl | exprStmt | ";" ) expression? ";" expression? ")" statement
printStmt => "print" expression ";"
returnStmt => "return" expression? ";"
whileStmt => "while" "(" expression ")" statement
block => "{" declaration* "}" ;
expression => series
series => assignment ( "," assignment )*
assignment => ( call "." )? IDENTIFIER "=" assignment | ternary
ternary => logic_or ( "?" ternary ":" ternary )*
logic_or => logic_and ( "or" logic_and )*
logic_and => equality ( "and" equality )*
equality => comparison ( ( "!=" | "==" ) comparison )
comparison => term ( ( ">" | ">=" | "<" | "<=" ) term )*
term => factor ( ( "+" | "-" ) factor )*
factor => unary ( ( "/" | "*" ) unary )*
unary => ( "!" | "-" ) unary | call
call => primary ( "(" arguments? ")" | "." IDENTIFIER )*
arguments => expression ( "," expression )*
primary => NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")"
| IDENTIFIER | functionExpr | "super" . IDENTIFIER
functionExpr => "fun" IDENTIFIER? "(" parameters? ")" block
A few example programs from Crafting Interpreters:
print "Hello, world!";
If statements:
if (condition) {
print "yes";
} else {
print "no";
}
Loops:
var a = 1;
while (a < 10) {
print a;
a = a + 1;
}
for (var a = 1; a < 10; a = a + 1) {
print a;
}
Functions and closures:
fun printSum(a, b) {
print a + b;
}
printSum(1, 2);
fun returnFunction() {
var outside = "outside";
fun inner() {
print outside;
}
return inner;
}
var fn = returnFunction();
fn();
Classes:
class Breakfast {
init(meat, bread) {
this.meat = meat;
this.bread = bread;
}
}
class Brunch < Breakfast {
init(meat, bread, drink) {
super.init(meat, bread);
this.drink = drink;
}
}