/clox

C implementation of Lox interpreter

Primary LanguageC

cLox

Following the amazing book by Robert Nystorm, Crafting the Interpreter. This repo closely follows the book, including enhancement proposed as challenge questions.

This is the C implementation that follows Nystorm's implementation very closely, along with the challenge problems solved, as many as possible.

1. The Lox Grammar

Start

program → declaration* EOF ;

Declarations

declaration    → classDecl
               | funDecl
               | varDecl
               | statement ;

classDecl      → "class" IDENTIFIER ( "<" IDENTIFIER )?
                 "{" function* "}" ;
funDecl        → "fun" function ;
varDecl        → "var" IDENTIFIER ( "=" expression )? ";" ;

Statements

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* "}" ;` 

Note that block is a statement rule, but is also used as a nonterminal in a couple of other rules for things like function bodies.

Expressions

expression     → assignment ;

assignment     → ( call "." )? IDENTIFIER "=" assignment
               | logic_or ;

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 )* ;
primary        → "true" | "false" | "nil" | "this"
               | NUMBER | STRING | IDENTIFIER | "(" expression ")"
               | "super" "." IDENTIFIER ;

Utility Rules

Keep the other rules cleaner.

function       → IDENTIFIER "(" parameters? ")" block ;
parameters     → IDENTIFIER ( "," IDENTIFIER )* ;
arguments      → expression ( "," expression )* ; 

2. Lexical Grammar

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

3. Progress

  • 20230902: Built the bytecode table
  • 20230903: Added the code line info to the bytecode table
  • 20230904: Added basic VM, stack, stack tracing for arithmetic expressions.
  • 20230920: Code scanning finished.
  • 20230921: Expression parsing and compilation done!
  • 20230923: Unary and binary expression compilation done.
  • 20230924: Dealt with strings

License

Shield: CC BY 4.0

This is a derived work. Original source belongs to Nystorm's book and is licensed under the what the book specifies. The derivation -- all modifications and additions -- is licensed under a Creative Commons Attribution 4.0 International License.

CC BY 4.0