Skip to content

Java implementation of the Lox programming language from the book "Crafting Interpreters"

License

Notifications You must be signed in to change notification settings

geertguldentops/jlox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

README

What is this repository for?

  • Quick summary

This is a Java version of the lox interpreter from the wonderful book Crafting Interpreters

It is written in pure Java, using only 2 external Java libraries for testing: JUnit 5 and AssertJ.

This implementation focuses heavily on unit testing. I tried to unit test as many scenarios as is reasonably possible since I felt this really deepened my understanding of how exactly the interpreter works.

This is also the reason why this implementation contains relatively little acceptance tests.

be.guldentops.geert.lox.LoxMain and be.guldentops.geert.lox.tools.GenerateAbstractSyntaxTree are not tested by design, see their respective Javadocs why.

How do I get set up?

Compiling the interpreter

Maven (3) is used to compile the code and run the tests:

  • You can run maven manually using mvn clean install from the command line.
  • You can run the cleanInstall.sh script, e.g.:
    • > chmod +x cleanInstall.sh
    • > ./cleanInstall.sh
  • Run the project's only pom.xml file using your favourite IDE! (IntelliJ IDEA, Eclipse, Netbeans, etc.)

Running a Lox program

Lox has 2 modes it can run in:

  1. REPL mode: Run the main method in the LoxMain class with exactly 1 program argument, the path to the Lox script you want to run.

  2. Script mode: Run the main method in the LoxMain class with no program arguments.

Generating the AST

The Expression class and its subtypes are generated by the GenerateAbstractSyntaxTree class.

GenerateAbstractSyntaxTree has a main method which accepts exactly 1 program argument, the output directory of the generated Expression class.

E.g.: ${ABSOLUTE_PATH_TO_JLOX_PROJECT}/jlox/src/main/java/be/guldentops/geert/lox/grammar

Running all the tests (unit + acceptance)

Through maven: mvn clean test

Using an IDE, for instance IntelliJ IDEA: Run all JUnit tests in package be.guldentops.geert.lox

Running all the unit tests

Run all the tests except the acceptance tests which are located in the be.guldentops.geert.lox.LoxAcceptanceTest class

Running all the acceptance tests

Run all the tests in the be.guldentops.geert.lox.LoxAcceptanceTest class

Lox Lexical Grammar

NUMBER          → DIGIT+ ( "." DIGIT+ )? ;
STRING          → '"' <any char except '"'>* '"' ;
IDENTIFIER      → ALPHA ( ALPHA | DIGIT )* ;
ALPHA           → 'a' ... 'z' | 'A' ... 'Z' | '_' ;
DIGIT           → '0' ... '9' ;

Lox Syntax Grammar

program         → declaration* EOF ;

declaration     → classDecl
                | funDecl
                | varDecl
                | statement ;
classDecl       → "class" IDENTIFIER ( "<" IDENTIFIER )?
                "{" function* "}" ;
funDecl         → "fun" function ;
function        → IDENTIFIER "(" parameters? ")" block ;
parameters      → IDENTIFIER ( "," IDENTIFIER )* ;
varDecl         → "var" IDENTIFIER ( "=" expression )? ";" ;

statement       → exprStmt
                | forStmt
                | ifStmt
                | printStmt
                | returnStmt
                | whileStmt
                | block ;
                
exprStmt        → expression ";" ;                    
forStmt         → "for" "(" ( varDecl | exprStmt | ";" )
                            expression? ";"
                            expression? ")" statement ;
ifStmt          → "if" "(" expression ")" statement ( "else" statement )? ;
printStmt       → "print" expression ";" ;
returnStmt      → "return" expression? ";" ;
whileStmt       → "while" "(" expression ")" statement ; 
block           → "{" declaration* "}" ;

expression      → assignment ;

assignment      → ( call "." )? IDENTIFIER "=" assignment
                | logic_or ;
                
logic_or        → logic_and ( "or" logic_and )* ;
logic_and       → equality ( "and" equality )* ;
equality        → comparison ( ( "!=" | "==" ) comparison )* ;
comparison      → addition ( ( ">" | ">=" | "<" | "<=" ) addition )* ;
addition        → multiplication ( ( "-" | "+" ) multiplication )* ;
multiplication  → unary ( ( "/" | "*" ) unary )* ;

unary           → ( "!" | "-" ) unary | call ;
call            → primary ( "(" arguments? ")" | "." IDENTIFIER )* ;
arguments       → expression ( "," expression )* ;
primary         → "true" | "false" | "nil" | "this"
                | NUMBER | STRING | IDENTIFIER | "(" expression ")"
                | "super" "." IDENTIFIER ;

Lox Precedence Rules

Name Operators Associates
Unary ! - Right
Multiplication / * Left
Addition - + Left
Comparison > >= < <= Left
Equality == != Left

About

Java implementation of the Lox programming language from the book "Crafting Interpreters"

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published