This repo contains my C++ implementation of Robert Nystrom's programming language Lox
(link to the original book: Crafting Interpreters,
link to the GitHub repo: craftinginterpreters). I started this project to learn C++ and, more importantly, to have fun! Because this is my first time using C++ in a serious project (sort of?),
there are lots of bad codes for sure. Refer to them at your own risk ;)
Surpher is a dynamically typed language that supports object-oriented programming and first-class functions. The current Surpher interpreter is a tree-walk interpreter implemented in C++17.
Load CMake project:
user@name:~/.../Surpher$ cmake [options] -S <path-to-source> -B <path-to-build>
Compile the project:
user@name:~/.../Surpher$ make
Run the following command to open the REPL:
./Surpher
run the following command to execute a script:
./Surpher [path to script]
In the REPL session, run the following command to exit:
!quit
program → declaration* EOF ;
declaration → "fixed"? ( classDecl | funDecl | varDecl | namespaceDecl )
| statement ;
classDecl → "class" IDENTIFIER ( "<" IDENTIFIER )?
"{" function* "}" ;
funDecl → "fun" function ;
varDecl → "var" (IDENTIFIER ( "=" expression )*)? ";" ;
namespaceDecl → "namespace" IDENTIFIER block ;
statement → exprStmt
| forStmt
| ifStmt
| printStmt
| returnStmt
| whileStmt
| continueStmt
| breakStmt
| importStmt
| haltStmt
| block ;
exprStmt → comma ";" ;
forStmt → "for" "(" ( varDecl | exprStmt | ";" )
expression? ";"
expression? ")" statement ;
ifStmt → "if" "(" expression ")" statement
( "else" statement )? ;
printStmt → "print" expression ";" ;
returnStmt → "return" expression? ";" ;
whileStmt → "while" "(" expression ")" statement ;
continueStmt → "continue" ";" ;
breakStmt → "break" ";" ;
importStmt → "import" expression ;
haltStmt → "halt" expression ;
block → "{" declaration* "}" ;
comma → expression ("," expression)* ;
expression → assignment ;
assignment → array "=" assignment | array ;
array → "[" array? "]" | "[" "alloc" ":" ternary "]" | ternary ;
ternary → logical_or "?" ternary ":" ternary ;
logic_or → logic_and ( "or" logic_and )* ;
logic_and → pipe ( "and" pipe )* ;
pipe → bit_wise_or ( "|>" bit_wise_or)* ;
bit_wise_or → bit_wise_xor ( "|" bit_wise_xor )* ;
bit_wise_xor → bit_wise_and ( "^" bit_wise_and )* ;
bit_wise_and → equality ( "&" equality )* ;
equality → comparison ( ( "!=" | "==" ) comparison )* ;
comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
term → factor ( ( "-" | "+" ) factor )* ;
factor → unary ( ( "/" | "*" | "%" ) unary )* ;
unary → ( "!" | "-" ) unary | access ;
access → "@" access "->" access | call ;
call → primary ( "(" arguments? ")" | "." IDENTIFIER )* ;
primary → "true" | "false" | "nil" | "this"
| NUMBER | STRING | IDENTIFIER | "(" expression ")"
| "super" "." IDENTIFIER | "\" IDENTIFIER* "->" expression ;
function → "sig"? "class"? IDENTIFIER "(" parameters? ")" block ;
parameters → IDENTIFIER ( "," IDENTIFIER )* ;
arguments → expression ( "," expression )* ;
NUMBER → "." ( DIGIT+ "e"* DIGIT* ) | ( DIGIT+ "e"* DIGIT* ) ( "." (DIGIT+ "e"* DIGIT*) )? ;
STRING → "\"" <any char except "\"">* "\"" ;
IDENTIFIER → ALPHA ( ALPHA | DIGIT )* ;
ALPHA → "a" ... "z" | "A" ... "Z" | "_" ;
DIGIT → "0" ... "9" ;
var x = \x -> (\ -> x);
fun A(k, x1, x2, x3, x4, x5) {
fun B() {
k = k - 1;
return A(k, B, x1, x2, x3, x4); //decrement k before use
}
return k > 0 ? B() : x4() + x5();
}
print A(10, x(1), x(-1), x(-1), x(1), x(0)); // result: -67
// Y-combinator as a lambda expression
var y_combinator = \f -> (\x -> x(x))(\x -> f(\y -> x(x)(y)));
// fibonacci function as a lambda expression
var fibonacci = \f -> (\x -> (x < 2 ? x : f(x - 1) + f(x - 2)));
// compute fibonacci(20) via Y-combinator
print y_combinator(fibonacci)(20);
// this example is taken from the original book
// base class
class Doughnut {
cook() {
print "Fry until golden brown.";
}
}
// derived class
class BostonCream < Doughnut {
cook() {
super.cook();
print "Pipe full of custard and coat with chocolate.";
}
}
BostonCream().cook();
Please refer
./example_programs/fractal_renderer/mandelbrot_set_renderer.sfr