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 set three 3
char five set five 5
char ten set ten 10

char num1 set num1 '0
char num2 set num2 '0

char count set count 40
while count {
	dec count
	
	inc num2
	dec ten
	ifnot ten {
		set num2 '0
		inc num1
		set ten 10
	}
	
	char fizzbuzz zero fizzbuzz
	
	dec three
	ifnot three {
		set three 3
		print Fizz
		inc fizzbuzz
	}
	
	dec five
	ifnot five {
		set five 5
		print Buzz
		inc fizzbuzz
	}
	
	ifnotz fizzbuzz {
		char zero
		equal zero num1 '0
		ifnotz zero {
			put num1
		}
		put num2
	}
	
	print \n
}

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.

get coucou
Inputs a char and stores it into coucou.
put coucou
Outputs the char stored into coucou.

print Hello,\ World!\n
Prints Hello, World!.

Loops

All loops follow the same syntax :

while coucou { ... }

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
}
print \n

It may also be written into a single line :

char count set count 5 while count { dec count print A } 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.

Blocks

Loops have their own set of variables.

If you want to create variables not accessible from outside your code, use blocks :

{
	char x
	set x 'X
}
char y
put y
print \n

This will print X because the two variables share the same position in memory.

Arrays

To create an array, use the array command.

array str 4

This creates variables str, str+1, str+2 and str+3.

To navigate arrays, use the left and right commands.

right and left shift every variable.

This prints A :

array str 2
set str+1 'A
right 1
put str

This also prints A :

char a
char b
set b 'A
right 1
put a

Because a now points to b.

To start using normal variables again (and print), make sure you are back at the start of your array.

Strings

To more easily work with strings, use the read and write commands.

This reads a string and prints it back when you press Enter :

array str 10
read str '\n
write str

The second argument to read specifies when to stop reading. Here, it stops at a newline. It must be a decimal number or a character preceded by an apostrophe.

Internally, strings start and end with null bytes. So array size 10 means a maximum of 8 bytes.

Example

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
		}
		
		incby input 13
		
		# after z
		char afterz
		greater afterz input 122
		if afterz {
			decby input 26
		}
		
		# a-z to A-Z
		if beforeZ {
			decby input 32
		}
		
		put input
	}
}
print \n

This reads your name and prints it back with "Hello" before it :

print Your\ name\ :\ #
array name 10
read name '\n
print Hello,\ #
ifnot name+1 {
	print World
}
write name
print !\n

Functions

To reuse code, use functions.

Functions are declared with the function function. They may have zero or more arguments.

This prints "Hello, Philippe!" :

function hello name {
	print Hello,\ #
	print name
	print !\n
}
hello Philippe

Example : an implementation of an "if-then-else" function.

function ifelsez condition then else {
	char not
	set not 1
	while condition {
		zero condition
		zero not
		then
	}
	while not {
		zero not
		else
	}
}
char c
set c 0 # change to 0 or 1
ifelsez c {
	print IfThen
} {
	print IfElse
}

Note that functions only have access to variables where the funciton is called, not defined.

This prints A :

function test {
	put a
}
{
	char a
	set a 'A
	test
}

Internally, the curly brackets create anonymous functions that can be used by other functions.