This is a compiler I wrote that compiles a language I created into Brainfuck.
Download the source : compile.c.
The parser is very simple. The source file is parsed into tokens, separated by spaces.
FizzBuzz example :
char three zero three char five zero five char num1 set num1 '0 char num2 set num2 '0 char count set count 40 while count dec count char out inc num2 equal out num2 ': ifz out set num2 '0 inc num1 end char fizzbuzz zero fizzbuzz inc three equal out three 3 ifz out zero three print Fizz inc fizzbuzz end inc five equal out five 5 ifz out zero five print Buzz inc fizzbuzz end ifnotz fizzbuzz char zero equal zero num1 '0 ifnotz zero put num1 end put num2 end print \n end
Which is compiled into the following Brainfuck code :
[-]>[-]>[-]++++++++++++++++++++++++++++++++++++++++++++++++>[-]++++++++++++++++++++++++++++++++++++++++++++++++>[-]++++++++++++++++++++++++++++++++++++++++[-<+>>>>[-]<[-]<<<[>>>>+<+<<<-][-]>>>>[-<<<<+>>>>]>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]>[-]<<<<<[-]>[>>>+<[>[-]>+<<-]>[<<<<+>>>>-]>[<<+>>-]<<-<<-]<[<<[-]++++++++++++++++++++++++++++++++++++++++++++++++<+>>>[-]]>>>>>>[-]<<<<<<<<<<<+>>>>>>>>>>>>>[-]<[-]<<<<<<<<<<<<[>>>>>>>>>>>>>+<+<<<<<<<<<<<<-][-]>>>>>>>>>>>>>[-<<<<<<<<<<<<<+>>>>>>>>>>>>>]>[-]+++[<<->>-]<<<<<<<<<[-]+>>>>>>>[<<<<<<<[-]>>>>>>>[-]]<<<<<<<[<<<<<[-]>>>>>>>>>>>>>>>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++++.+++++++++++++++++..<<<<+<<<<<<[-]]<<<<+>>>>>>>>>>>>>>>[-]<[-]<<<<<<<<<<<<<<[>>>>>>>>>>>>>>>+<+<<<<<<<<<<<<<<-][-]>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>]>[-]+++++[<<->>-]<<<<<<<<<<<<[-]+>>>>>>>>>>[<<<<<<<<<<[-]>>>>>>>>>>[-]]<<<<<<<<<<[<<<<[-]>>>>>>>>>>>>>>>>>[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++++++++++++++++++++++++++++.+++++..<<<<<<<+<<<<<<[-]]>>>>>>>>>>>>>[-]+<<<<<<<[>>>>>>>[-]<<<<<<<[-]][-]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[>>>>>>>>>>[-]<[-]<<<<<<<<<<<<<<<<<<[>>>>>>>>>>>>>>>>>>>+<+<<<<<<<<<<<<<<<<<<-][-]>>>>>>>>>>>>>>>>>>>[-<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>]>[-]++++++++++++++++++++++++++++++++++++++++++++++++[<<->>-]<<<[-]+>[<[-]>[-]]>>>[-]+<<<<[>>>>[-]<<<<[-]][-]>>>>[-<<<<+>>>>]<<<<[<<<<<<<<<<<<<<<<<.>>>>>>>>>>>>>>>>>[-]]<<<<<<<<<<<<<<<<.>>>>>>>>[-]]>>>>>>>>[-]++++++++++.<<<<<<<<<<<<<<<]
Commands may be split into multiple lines or can be written all in the same line. That is, the following are equivalent :
char hello zero hello inc hello
char hello zero hello inc hello
char hello zero hello inc hello
My compiler implements many commands that make it easier to create Brainfuck programs :
char coucou
coucou
.set coucou 123
coucou
variable to 123.set coucou 'A
coucou
variable to 65.copy coucou hello
hello
into coucou
.move coucou hello
hello
into coucou
.zero coucou
coucou
variable to zero.inc coucou
coucou
variable.incby coucou 5
coucou
variable by 5.dec coucou
coucou
variable.decby coucou 5
coucou
variable by 5.equal out coucou hello
coucou
and hello
are equal and stores the result into out
.equal out coucou 5
coucou
equals 5
and stores the result into out
.equal out coucou 'A
coucou
equals 65
and stores the result into out
.greater out coucou hello
coucou
is greater than hello
and stores the result into out
.greater out coucou 5
coucou
is greater than 5
and stores the result into out
.greater out coucou 'A
coucou
is greater than 65
and stores the result into out
.flip coucou
coucou
variable : nonzero becomes zero and zero becomes one.print Hello,\ World!\n
Hello, World!
.get coucou
coucou
.put coucou
coucou
.All loops follow the same syntax :
while coucou ... end
This loops while coucou
is nonzero.
...
may be any tokens.
This prints A five times :
char count set count 5 while count dec count print A end print \n
It may also be written into a single line :
char count set count 5 while count dec count print A end print \n
Ifs are loops that run only once.
There are four kinds of ifs :
if coucou ... end
ifnot coucou ... end
ifz coucou ... end
ifnotz coucou ... end
The ifs ending with z
clear their condition after they are run.
Use them to save memory.
The two other ifs make a copy of their condition and leave the original untouched.
if
tests if the condition is nonzero and ifnot
tests if the condition is zero.
If a block of code needs to be repeated, use functions.
The compiler's first pass through the token list is to parse and inline functions.
Use declare hello ... return
to define a function named hello
.
Use inline hello
to inline the function in your code.
Functions may be inlined anywhere, even in the middle of commands (commands are parsed in the compiler's second pass through the token list).
All of these print A :
declare lettre 65 return char coucou set coucou inline lettre put coucou
declare variable coucou return char coucou set inline variable 65 put coucou
declare line set coucou 65 return char coucou inline line put coucou
declare command set return char coucou inline command coucou 65 put coucou
Functions do not have arguments. Instead, functions may use local variables where the inline
command is.
It is also possible to use inline
inside a function :
declare lettre 65 return declare line set coucou inline lettre return char coucou inline line put coucou
Loops have their own set of variables.
If you want to create variables not accessible from outside your code, use blocks :
block char x set x 'X end char y put y print \n
This will print X because the two variables share the same position in memory.
You can also use blocks inside functions to localize their temporary variables :
declare hello block char x set x 'X put x print \n end return inline hello
This code implements a "greater than" function :
declare hello block char lvalue copy lvalue x char rvalue copy rvalue y char temp0 zero temp0 char temp1 zero temp1 zero out while lvalue inc temp0 while rvalue zero temp0 inc temp1 dec rvalue end while temp0 inc out dec temp0 end while temp1 inc rvalue dec temp1 end dec rvalue dec lvalue end end return char x set x 10 char y set y 9 char out inline hello ifnot out equal out x y end if out print GTE\n end ifnot out print LT\n end
This code does a ROT13 :
char loop set loop 1 while loop char input get input equal loop input 10 flip loop if loop # A-Z to a-z char beforeZ greater beforeZ 91 input if beforeZ incby input 32 end incby input 13 # after z char afterz greater afterz input 122 if afterz decby input 26 end # a-z to A-Z if beforeZ decby input 32 end put input end end print \n