phil2bf

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

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
Creates a variable named coucou.
set coucou 123
Assigns the coucou variable to 123.
set coucou 'A
Assigns the coucou variable to 65.
copy coucou hello
Copies hello into coucou.
move coucou hello
Moves hello into coucou.
zero coucou
Resets the coucou variable to zero.
inc coucou
Increments the coucou variable.
incby coucou 5
Increments the coucou variable by 5.
dec coucou
Decrements the coucou variable.
decby coucou 5
Decrements the coucou variable by 5.
equal out coucou hello
Tests if coucou and hello are equal and stores the result into out.
equal out coucou 5
Tests if coucou equals 5 and stores the result into out.
equal out coucou 'A
Tests if coucou equals 65 and stores the result into out.
greater out coucou hello
Tests if coucou is greater than hello and stores the result into out.
greater out coucou 5
Tests if coucou is greater than 5 and stores the result into out.
greater out coucou 'A
Tests if coucou is greater than 65 and stores the result into out.
flip coucou
Flips the coucou variable : nonzero becomes zero and zero becomes one.
print Hello,\ World!\n
Prints Hello, World!.
get coucou
Inputs a char and stores it into coucou.
put coucou
Outputs the char stored into coucou.

Loops

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

Ifs are loops that run only once.

There are four kinds of ifs :

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.

Functions

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

Blocks

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

Example

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