This is the first part of the Yet Another Useless Language series. For your convenience you can find other parts using the links below :
Part 1 — Introduction
Part 2 — Grammar
Part 3 — Variables
Part 4 — Compiler
Part 5 — Variables
Part 6 — If
Part 7 — Loop
Part 8 — Function
Part 9 — Standard library
Part 10 — Parser
Part 11 — Storing binary on the disk
Today we start implementing simple language compiler using C# and PLY library. Before we dig into code let’s write down language features we would like to implement.
YAUL
We are going to implement scripting language using .NET Expressions for compiling and executing the code. Basically, we will define custom grammar, parse script’s source code using PLY, and create expression tree representing the script. Next, we will compile the expression tree and execute it. Thanks to that we will be able to easily compile the script code to executable binary written in managed code (so it will require .NET Framework to run).
We will implement the following features:
- local variables declared ad-hoc
- arrays
- strings
- while loop
- function and recursive functions
- basic standard library
Our syntax will resemble Python’s, e.g., hello world will look like this:
1 |
print "Hello, world"; |
We will handle integers, arrays, and strings:
1 2 3 4 |
number = 5; text = "Hello!"; array = [1, "two", 3]; big_array = new [50]; |
We will handle common operations on numbers and strings. We will be able to extract characters from strings using array access operator.
We will handle if
with else
and while
loop with break
, continue
. We will also handle goto
to label.
We will be able to define recursive functions with our without return type. We will also have simple standard library with few functions.
All variables will be treated as local variables (no globals), also accessing the variable before its definition will be marked as an error. Flow instructions like if
or while
will not change the variables’ scoping — they will not define new scope. All functions will accept variables by value, there will be no passing by reference. Also, function’s parameters will be handled as an ordinary local variables.
Some basic programs written in YAUL:
Fibonacci:
1 2 3 4 5 6 7 8 |
first = 1; second = 1; while(first < 1000){ print first; temp = second; second = first + second; first = temp; } |
Finding prime numbers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function isPrime(number){ temp = 2; while(temp < number){ if(number % temp == 0){ return 0; } temp = temp + 1; } return 1; } function checkPrimes(low, up){ temp = low; while(temp <= up){ if(isPrime(temp) == 1){ print temp; } temp = temp + 1; } } checkPrimes(2,100); |
Printing pyramid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function printPyramid(length){ if(length > 1){ printPyramid(length - 1); } temp = 0; line = ""; while(temp < length){ line = line + "*"; temp = temp + 1; } print line; } printPyramid(8); |
In the next part we are going to write down the grammar for YAUL.