An interpreter made in C for a custom programming language
fsnail is a simple, interpreted and stack based programming language. I wanted to make this interpreter to test my skills and to make a project that was not too hard but also not too easy. The choice of a not so complicated project has influenced the syntax of fsnail that took inspiration from Tanenbaum's MAL and tinybasic.
- First compile the file:
gcc -o fsnail fsnail.c -lm - Move it to the bin folder:
sudo mv fsnail /usr/local/bin/ - Use it:
fsnail file.fsn
Here's the list of all the operations: Arithmetic and Stack operations:
push value: Adds an element on top of the stackpop:Deletes the element on top of the stackdup: Duplicates the element on top of the stackclear: Clears the stack contentswap: Swaps the two elements on topsum: Sums the first two element of the stacksub: Same as sum but with the subtractionmult: Same but with multiplicationdiv: Same but with divisionrem: Gets the remainder of the division between the two elements on top (treats the elements integertoint: Converts the top element to an integer by rounding it downinc name: Increments the top element valuedec name: Decrements the top element value
The operations are always:
second_element # first_element = result, where#is the generic representation of an operator
Binary operations:
and: Actuate the AND operation between the top two elementsor: Same as or but with ORnot: Same but with NOTxor: Same but with XORlshift: Single left shiftrshift: Single right shift
IMPORTANT: the NOT and the two shift operations only affects the element on top of the stack and with this functions all the elements are treated as integer
Logical operations:
ifeq: Checks if the top element is equal to the second oneifdif: Checks if the top element is different to the second oneifgr: Checks if the top element is greater than the second oneiflw: Checks if the top element is lower than the second oneiftrue: Checks if the first element is equal to oneiffalse: Checks if the first element is equal to zeroendif: Ends the series of if instructions
If the one of these operations results as true, the program will execute the code contained between if and endif. Nested if are also supported
Jumps and labels:
labelname: Creates a new labelgoto name: Jumps to the given label
Input and output:
print "string": Prints the stringprintnl "string": Prints a string and goes to a new linein: Gets the value as an integer, the value is stored in a new element on top of the stackinchar: Gets the value a char, the value is stored in a new element on top of the stackout: Prints the element on top of the stackoutint: Prints the element on top of the stack as an integeroutchar: Prints the element on top of the stack as a characteracter (treats the element as an integer)sclear: Clears the screen
Variables:
var name: Creates a variabledel name: Deletes a variablestore name: Saves the content on the stack top into the variablepstore name:Saves the content on the stack top into the variable and pops itload name: Loads the content of the variable on top of the stackvclear: Clears variable stack content
Comments and extra instructions:
-->: Starts the the comment<--: Ends the commentstack: Prints out the current stackhalt: Terminates the programrandint value: Generates a number 0 < x <= value and pushes it on top of the stack
The comment delimiters need to be separated to the comment's content like any other token
Advanced Math:
abs: Returns the absolute value of the element on top of the stackpow: Elevates the second to last number to the power of the top element (it acts exactly as the arithmetical operators)ln: Calculates the natural logarithm of the top elementlog: Calculates the common (base 10) logarithm of the top elementlogtwo: Calculates the base 2 logarithm of the top elementfloor: Rounds up the top element (toint can be used as ceil)sqrt: Calculates the square root of the top elementsin: Calculates the sine of the top element (result in radians)cos: Calculates the cosine of the top element (result in radians)tan: Calculates the tangent of the top element (result in radians)
The interpreter comes with some debugging features, it checks if an if misses its endif and viceversa. It also applies checks to the types of data (invalid string, invalid number), to the stack (the stack is empty, the stack is composed of less than two elements), to the variable section (the variable doesn't exist), if a token is invalid or if a file exists and its extension is correct.
var lbase
var gbase
var height
printnl "Calculating the area of a trapezoid"
printnl "Insert the smaller base:"
in
pstore lbase
printnl "Insert the bigger base:"
in
pstore gbase
printnl "Insert the height"
in
pstore height
load lbase
load gbase
sum
load height
mult
push 2
div
print "The area is: "
out
printnl ""
label while
printnl "Insert a number:"
in
printnl "Insert a number:"
in
ifeq
printnl "The numbers are equal"
goto while
endif
printnl "The numbers are different"
goto while
label and
printnl ""
printnl "Insert a number:" --> Asks for the limit number <--
in
toint
dec --> Necessary to avoid an extra iteration <--
push 0 --> Acts as a counter <--
label for
outint
print ", "
ifeq
goto end
endif
inc
goto for
label end
printnl ""
printnl "Insert a number:" --> Asks for the limit number <--
in
toint
push 0 --> Acts as a counter <--
label for
ifdif
outint
print ", "
inc
goto for
endif
printnl ""
var a
var b
var c
var squareroot
printnl "Second grade equation solver. Its type must be: ax^2+by+c = 0"
printnl "Insert a:"
in
pstore a
printnl "Insert b:"
in
pstore b
printnl "Insert c:"
in
pstore c
--> Now we'll apply the standard formula for resolving second grade equations <--
load b --> Calculates b^2 <--
dup
mult
push -4 --> Calculates -4ac <--
load a mult
load c mult
sum
--> Now we have the delta on the top of the stack <--
push 0
iflw
goto invalid
endif
pop
sqrt
store squareroot
load b --> Calculates -b <--
push -1 mult
sum
load a --> Adds 2a on top of the stack and calculates x1 <--
push 2 mult
div
print "x1 = "
out printnl ""
load b --> Calculates the second solution <--
push -1 mult
load squareroot sub
load a
push 2 mult
div
print "x2 = "
out printnl ""
halt
label invalid
printnl "The equation has no solution"