Parser & interpreter for a custom programming language. This project was made for study and research about compiler construction.
- I'm bad at naming things.
- This project began as a lexical analysis tool; the parser and interpreter were added later on. I may rename it in the future
- Maven
- jflex 1.9
- cup 11b
Run maven compile
to generate the lexer & parser classes.
The resulting java files should be inside of ${project.build.directory}/generated-sources
. Mark that folder as "Generated Sources Root" (if you're using IntelliJ).
Navigate to src/main/java/org/automatas/program/Main.java
and edit the main method.
Edit it to set your custom path to a source file (eg: engine.executeFile("path/to/source.txt")
).
code.txt
contains a sample code that can be run by the interpreter.
Run the main()
method and done!
The language supports these primitive types:
array
(java.util.ArrayList)bool
(java.lang.Boolean)float
(java.lang.Double)int
(java.lang.Long)string
(java.lang.String)
Numeric literals can be expressed in various forms:
- Bin:
0b00001010
- Hex:
0xffa500
- Oct:
0o276
- Exp:
1.30e5
// This is a line comment.
/*
And this is a
block comment.
*/
Use the :=
operator (borrowed from Go) to declare a new variable in the current scope.
var := "Hello";
The interpreter will throw a fatal error if you attempt to re-declare a variable within the same scope.
var := "Again!"; // Fatal Error: 'var' is already defined.
However, you can declare a variable with the same identifier (name) within a nested scope.
var := "Outer";
{
// This is allowed, as the inner-most variable
// shadows the variable in the parent scope.
var := "Inner";
print(var);
}
print(var);
Variables can be re-assigned with the =
operator.
var = "Hello there";
print(var);
And the interpreter will throw a fatal error if the variable is undefined.
unknown = "???"; // Fatal Error: undefined variable 'unknown'.
Variables can store any type of value at any moment:
var = [1, 2, 3];
var = true;
var = 3.1415;
var = 2023;
var = "A113";
The is
operator checks if the given value is of a specific type, while the as
operator
casts the value from one type to another:
// Check if the value is a string
if var is string {
// Cast to integer
casted := var as int;
}
Use the unset
operator to remove a variable:
unset var;
print(var); // Fatal Error: undefined variable 'var'.
Arrays follow the usual bracket-style syntax:
arr := ["a", "b", "c"];
val := arr[1];
arr[0] = "x";
Arrays grow dynamically, so you can append values by using the []
syntax (borrowed from PHP):
arr := []; // Empty array
arr[] = "hi"; // Append a string (note that you have to use = operator).
print(arr[0]);
And with the unset
operator, you can remove one value from the array (the array will be re-indexed):
arr := ["a", "b", "c"];
print(arr[0]); // "a"
unset arr[0];
print(arr[0]); // "b"
Operator | Meaning |
---|---|
expr && expr |
and |
expr || expr |
or |
!expr |
not |
Operator | Meaning |
---|---|
expr == expr |
equal |
expr != expr |
not equal |
expr < expr |
less |
expr <= expr |
less or equal |
expr > expr |
greater |
expr >= expr |
greater or equal |
Operator | Meaning |
---|---|
expr + expr |
addition / concatenation |
expr - expr |
subtraction |
expr * expr |
multiplication |
expr / expr |
division |
expr % expr |
modulo |
expr ** expr |
exponentiation |
The if/else statement looks like this:
if condition {
/* if-statements */
}
if condition {
/* if-statements */
} else {
/* else-statements */
}
Note that the condition doesn't require parenthesis.
while condition {
/* while-statements */
}
for declaration; condition; step {
/* for-statements */
}
There's no break
or continue
keywords yet.
print
prints to STDOUT followed by a \n
.
printf
prints a formatted string to STDOUT.
input
gets input from STDIN optionally printing a prompt message.
print("This program tells you if your number is even or odd.");
number := input("Number: ") as int;
if number % 2 == 0 {
printf("Your number %d is even!\n", number);
} else {
printf("Your number %d is odd!\n", number);
}
Using the fn
keyword you can declare your own functions!
fn fib(n)
{
if n <= 1 {
return n;
}
return fib(n - 1) + fib(n - 2);
}
n := fib(10);
printf("Fibonacci of 10 is: %d\n", n);