Language based on lox and tweaked from book "Crafting Interpreters" by @munificent.
Statements:
program → declaration* EOF ;
declaration → classDecl
| funDecl
| varDecl
| statement ;
classDecl → "class" IDENTIFIER ( "<" IDENTIFIER )?
"{" function* "}" ;
funDecl → "fun" function ;
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 ";" ;
doWhileStmt → "do" statement "while" "(" expression ")" ";" ;
whileStmt → "while" "(" expression ")" statement ;
breakStmt → "break" ";" ;
continueStmt → "continue" ";" ;
block → "{" declaration* "}" ;
Expressions:
expression → comma ;
comma → assignment ( "," assignment )*
assignment → ( call "." )? ( ( "=" | "+=" | "-=" | "*=" | "/=" | "**=" ) assignment )?
| ternary ;
ternary → logic_or ( "?" expression ":" 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
| exponent ;
exponent → (prefix "**" unary)
| prefix ;
prefix → ("++" | "--") primary
| postfix ;
postfix → primary ( "++" | "--" )*
| call ;
call → primary ( "(" arguments? ")" | "." IDENTIFIER )* ;
primary → "true" | "false" | "none" | "this"
| NUMBER | STRING | IDENTIFIER | "(" expression ")"
| lambda
| "super" "." IDENTIFIER
// Error productions...
| ( "!=" | "==" ) equality
| ( ">" | ">=" | "<" | "<=" ) comparison
| ( "+" ) term
| ( "/" | "*" ) factor
| ("**") exponent;
Other:
arguments → expression ( "," expression )* ;
parameters → IDENTIFIER ( "," IDENTIFIER )* ;
function → IDENTIFIER functionBody;
method → function;
static method→ "class" method;
constructor → "init" functionBody; # returns this
functionBody → "(" parameters? ")" block ;
lambda → "fun" functionBody ;
Unary '+' operator is not supported.
Currently continue statement does not work as expected for for loops, incrementors must be manually incremented.
Name Operators Associates
Call a() Left
Postfix a++ a-- Left
Prefix ++a --a Right
Exponent ** Right
Unary ! - Right
Factor / * Left
Term - + Left
Comparison > >= < <= Left
Equality == != Left
Logical And and Left
Logical Or or Left
Ternary ?: Right
Assignment =, +=, -=, /=, *=, **= Right
Comma , Left
Fail follows Ruby’s simple rule: false and none are falsey and everything else is truthy.
\" – double quote
\\ – single backslash
\b – backspace
\r – carriage return
\n – newline
\t – tab
Variables can change it's data type at runtime as in Python. Data types are implied from expressions.
double
precision)Those can be defined via class
keyword.
clock()
- Gets the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC. Then it changes milliseconds to seconds as a floating point value.len(x)
- This function changes input to a string and gets its length.str(x)
- Changes input to its string representation.Additional features mostly based on tasks from book: