Using size_t doesn't fix it. gparent didn't intend to fix it with that.
You just use size_t for array- and container-indices.
I know I was just trying to demonstrate what you get when you subtract 1 from an unsigned type, don't know why your compiler doesn't like that.
[code]+.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+.>[/code]
This is fun.
I am not happy about it but here goes.
[url]http://i43.tinypic.com/5pef0m.jpg[/url]
[highlight]C#[/highlight]
[b]Program.cs[/b]
[cpp]using System;
using System.Collections.Generic;
using System.Text;
namespace BrainfuckInterpreter
{
class Program
{
static void Main(string[] args)
{
BrainFuck.BFParser p = new BrainFuck.BFParser();
BrainFuck.Instruction[] ins = p.Parse(
@"++++++++++ initialises cell zero to 10
[
>+++++++>++++++++++>+++>+<<<<-
] this loop sets the next four cells to 70/100/30/10
>++. print 'H'
>+. print 'e'
+++++++. 'l'
. 'l'
+++. 'o'
>++. space
<<+++++++++++++++. 'W'
>. 'o'
+++. 'r'
------. 'l'
--------. 'd'
>+. '!'
>. newline
");
BrainFuck.BFSystem bfs = new BrainFuck.BFSystem();
bfs.Execute(ins);
Console.ReadKey();
}
}
}
[/cpp]
[b]BrainFuck.cs[/b]
[cpp]using System;
using System.Collections.Generic;
using System.Text;
namespace BrainFuck
{
public class BFParser
{
int Idx;
public List<Instruction> Instructions;
public BFParser()
{
Idx = 0;
}
public Instruction[] Parse(string str)
{
Instructions = new List<Instruction>();
Parse(str, false);
if (Instructions.Count > 1)
{
Instructions[0].Next = Instructions[1];
for (int i = 1; i < Instructions.Count - 1; i++)
{
Instructions[i].Prev = Instructions[i - 1];
Instructions[i].Next = Instructions[i + 1];
}
}
return Instructions.ToArray();
}
void Parse(string str, bool IsLoop)
{
for (; Idx < str.Length; Idx++)
{
if (str[Idx] == '[')
{
Instruction ins = Instruction.WhileStart.Clone() as Instruction;
Instructions.Add(ins);
Idx++;
Parse(str, true);
ins.Data = Instructions[Instructions.Count - 1];
Instructions[Instructions.Count - 1].Data = ins;
}
else if (str[Idx] == ']')
{
if (IsLoop)
{
Instructions.Add(Instruction.WhileEnd.Clone() as Instruction);
return;
}
else
{
throw new Exception(string.Format("Missing [ before ({0})", Idx));
}
}
for (int i = 0; i < BFSystem.Instructions.Length; i++)
{
if (BFSystem.Instructions[i].Symbol == str[Idx].ToString())
{
Instructions.Add(BFSystem.Instructions[i].Clone() as Instruction);
}
}
}
if (IsLoop)
{
throw new Exception(string.Format("Missing ] before (EOF)"));
}
}
}
public class BFSystem
{
public Dictionary<uint, byte> Data;
public uint Pointer;
public Instruction Current;
public void Execute(Instruction[] instructs)
{
if (instructs.Length < 1)
return;
Data = new Dictionary<uint, byte>();
Pointer = 0;
Current = instructs[0];
for (; Current != null; Current = Current.Next)
{
Current.Execute(this, Current);
}
}
public static readonly Instruction[] Instructions =
{
Instruction.AddDataPtr,
Instruction.SubDataPtr,
Instruction.Increment,
Instruction.Decrement,
Instruction.PutChar,
Instruction.GetChar,
Instruction.WhileStart,
Instruction.WhileEnd,
};
}
public class Instruction : ICloneable
{
public object Clone()
{
Instruction ins = new Instruction(Symbol, Data, Execute);
ins.Next = this.Next;
ins.Prev = this.Prev;
return ins;
}
public override string ToString()
{
return Symbol;
}
public Instruction(string symbol, ExecuteD exe)
: this(symbol, null, exe)
{
}
public Instruction(string symbol, object data, ExecuteD exe)
{
Symbol = symbol;
Data = data;
Execute = exe;
}
public Instruction Prev;
public Instruction Next;
public object Data;
public string Symbol;
public ExecuteD Execute;
public delegate void ExecuteD(BFSystem sys, Instruction self);
public static readonly Instruction AddDataPtr = new Instruction(">",
delegate(BFSystem sys, Instruction self)
{
sys.Pointer++;
});
public static readonly Instruction SubDataPtr = new Instruction("<",
delegate(BFSystem sys, Instruction self)
{
sys.Pointer--;
});
public static readonly Instruction Increment = new Instruction("+",
delegate(BFSystem sys, Instruction self)
{
if (!sys.Data.ContainsKey(sys.Pointer))
{
sys.Data.Add(sys.Pointer, 0);
}
sys.Data[sys.Pointer]++;
});
public static readonly Instruction Decrement = new Instruction("-",
delegate(BFSystem sys, Instruction self)
{
if (!sys.Data.ContainsKey(sys.Pointer))
{
sys.Data.Add(sys.Pointer, 0);
}
sys.Data[sys.Pointer]--;
});
public static readonly Instruction PutChar = new Instruction(".",
delegate(BFSystem sys, Instruction self)
{
if (!sys.Data.ContainsKey(sys.Pointer))
{
Console.Write(0);
}
else
{
Console.Write((char)sys.Data[sys.Pointer]);
}
});
public static readonly Instruction GetChar = new Instruction(",",
delegate(BFSystem sys, Instruction self)
{
if (!sys.Data.ContainsKey(sys.Pointer))
{
sys.Data.Add(sys.Pointer, 0);
}
sys.Data[sys.Pointer] = (byte)Console.Read();
});
public static readonly Instruction WhileStart = new Instruction("[",
delegate(BFSystem sys, Instruction self)
{
if (!sys.Data.ContainsKey(sys.Pointer) || sys.Data[sys.Pointer] == 0)
{
sys.Current = (self.Data as Instruction);
}
});
public static readonly Instruction WhileEnd = new Instruction("]",
delegate(BFSystem sys, Instruction self)
{
if (sys.Data.ContainsKey(sys.Pointer) && sys.Data[sys.Pointer] != 0)
{
sys.Current = (self.Data as Instruction);
}
else
{
}
});
}
}
[/cpp]
If I was to rewrite it or put more effort into it I would...
-Take the methods out of the Instruction class and give them their own class
-Include a method that can be provided for special parsing
-etc
Really was just messing around applying the concept. Never tried it before.
[QUOTE=Sporbie;14216524]Thanks gparent, that does look prettier, but why use size_t? What exactly is it?
Oh and what's the difference between reference and pointer? When do you use pointers and when references?[/QUOTE]
size_t is a type that can hold the largest size of an array, if I remember correctly.
So vector indices, malloc()'s 2nd parameter, the return value of str.size(), everything that deep-down is handled by an array, will return size_t.
As for references and pointers, I know the difference between them, however I'm not a great teacher.
However, the basic is:
A reference is similar to a pointer in that you are accessing an object that is not copied by value.
A reference is different to a pointer in that you cannot assign a reference after it is initialized
A reference cannot be NULL (Unless you try fairly hard IIRC)
You don't need to use the -> operator with a reference, you use . instead.
You use references whenever you can, and pointers whenever you can't. Start with a reference, if you can't do what you want with one (or if it requires a lot of extra code), use a pointer.
As for the other few things I've changed:
-Always use a const variable before using a #define if you can. const variables provide type safety, and they have a scope.
-Added default case to the switch to fix a compiler warning
-Changed every .at() to [] (Although I missed some, I edited my post to remove some more). The difference between .at() and [] is that .at() will throw an exception if you access an invalid indice. If you're not using try catch, it's pointless to use it.
-Changed !file.eof() condition to the state of the stream. More explanation here: [url]http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5[/url]
Let me know if you have more questions.
Haha, reminds me that I've made a Brainfuck compiler for my graphical calculator a long time ago. Compiles directly into executable machine code. It's way easier to do than an interpreter because most tokens are simple CPU instructions (increment, decrement), and loops in loops appear naturally when you make use of labels and jumps. On the other hand, console input and output were a pain in the ass to do because the CPU didn't have instructions to call a C function from assembly.
-snip-, nevermind.
[QUOTE=Sporbie;14218254]I know I was just trying to demonstrate what you get when you subtract 1 from an unsigned type, don't know why your compiler doesn't like that.[/QUOTE]
It's not weired. If sizeof(unsigned int) is x, then you get the number 2^x-1.
sizeof() returns bytes, not bits.
Right. >.<
If sizeof(unsigned int)*8 is x, then you get the number 2^x-1.
Jallen, for some reason your program doesn't work with this 99 bottles of beer program:
[url]http://99-bottles-of-beer.net/download/101?PHPSESSID=3e25b4af1261bc9c699d327ee2983544[/url]
Oh and I updated my program, now works with all kinds of loops and the above example, and yours doesn't, so that means I'm a better person than you, yeah (also you can just run the program and type in code, you don't have to drag and drop a text file, you can if you want to however): [url]http://www.speedyshare.com/511782933.html[/url]
[QUOTE=ZeekyHBomb;14219174]Right. >.<
If sizeof(unsigned int)*8 is x, then you get the number 2^x-1.[/QUOTE]
His implementation is entirely wrong anyway.
char's signedness is implementation specific, and he's using integer literals instead of the numeric_limits<T>::min() and max() calls. (The latter doesn't matter as much as the former, though, since char is guaranteed to be 1 byte).
[QUOTE=Sporbie;14219178]Jallen, for some reason your program doesn't work with this 99 bottles of beer program:
[url]http://99-bottles-of-beer.net/download/101?PHPSESSID=3e25b4af1261bc9c699d327ee2983544[/url]
Oh and I updated my program, now works with all kinds of loops and the above example, and yours doesn't, so that means I'm a better person than you, yeah (also you can just run the program and type in code, you don't have to drag and drop a text file, you can if you want to however): [url]http://www.speedyshare.com/511782933.html[/url][/QUOTE]
I can't be bothered to go through that whole program trying to find out why it's not working, but the interpreter seems to work for everything else i give to it...
I don't know what it is in there that's killing it.
Ok, I know why - fixing it.
I think I'll try one of my own interpreters now. Be right back.
Back:
[cpp]
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
typedef std::vector<unsigned char> stack_t;
const unsigned STACK_SIZE = 8092;
// returns src index to continue running at at
int run(const std::string &src, stack_t &stack, size_t &stackIdx, int srcIdx)
{
if (srcIdx < 0)
return -1; // EOF
int oldSrcIdx = srcIdx; // for looping
while (srcIdx < src.size())
{
switch (src[srcIdx])
{
case '[':
// run inner scope
srcIdx = run(src, stack, stackIdx, srcIdx + 1);
continue;
break;
case ']':
if (stack[stackIdx])
{
// if (not zero) loopp
srcIdx = oldSrcIdx;
continue;
}
else
// else (zero) return to outer scope
return srcIdx + 1;
break;
case '>': ++stackIdx; break;
case '<':
assert(stackIdx && "cannot < 0 stack idx");
--stackIdx;
break;
case '+': ++stack[stackIdx]; break;
case '-': --stack[stackIdx]; break;
case '.': std::cout << stack[stackIdx]; break;
case ',': std::cin >> stack[stackIdx]; break;
default: break;
}
++srcIdx;
}
return -1;
}
int main(int argc, char **argv)
{
assert(argc == 2 && "usage: bf.exe file_to_interpret.extension");
std::ifstream in(argv[1]);
assert(in && "file must be good");
std::string src, temp; // fill the src string from the file
while (std::getline(in, temp)) src += temp;
stack_t stack(STACK_SIZE, 0);
size_t stackIdx = 0;
run(src, stack, stackIdx, 0);
// pause
std::cin.ignore(std::cin.rdbuf()->in_avail() + 1);
}
[/cpp]
Runs two hello world examples fine.
[quote="Sporbie"]
Jallen, for some reason your program doesn't work with this 99 bottles of beer program:
[url]http://99-bottles-of-beer.net/downlo...9d327ee2983544[/url]
Oh and I updated my program, now works with all kinds of loops and the above example, and yours doesn't, so that means I'm a better person than you, yeah (also you can just run the program and type in code, you don't have to drag and drop a text file, you can if you want to however): [url]http://www.speedyshare.com/511782933.html[/url]
[/quote]
Also runs this fine.
It's nice and short, and was a good exercise to write. The only fallback to it is that I didn't do the primary non-zero check at the start of a loop, only at the end of a loop. Will add it later.
(compile as console app and drag-and-drop a brainfuck source file onto it, like the linked 101-bottles.txt)
[url=http://www.iwriteiam.nl/Ha_bf_inter.html]There[/url]'s a Brainfuck-interpreter in Brainfuck.
[QUOTE=ZeekyHBomb;14225058][url=http://www.iwriteiam.nl/Ha_bf_inter.html]There[/url]'s a Brainfuck-interpreter in Brainfuck.[/QUOTE]
Now that's brainfuck...
[QUOTE=BrokenGlass;14225326]Now that's brainfuck...[/QUOTE]
No, it's "Brainfuck Brainfuck"
[url]http://forum.lolcode.com/viewtopic.php?id=51[/url]
Some guy wrote a brainfuck interpreter in LOLCODE...
[code]HAI
BTW This is a BrainFuck interpreter written in LOLCode
BTW It accepts as input a BF program, followed by a "!", followed by any input to the BF program.
BTW Since BrainFuck is turing-complete, this proves that LOLCode is too
I HAS A INSTRUCTIONS BTW Array for BF instructions
I HAS A IPTR BTW Pointer to first empty element in INSTRUCTIONS
LOL IPTR R 0
I HAS A LOOPZ BTW Array of loop start/end addresses
I HAS A LOOPSTACKZ BTW Loop stack for building the above two
I HAS A LSPTR BTW Pointer to first empty element of LOOPSTACKZ
LOL LSPTR R 0
BTW Read in BF instructions, terminated with "!"
IM IN YR CODE
GIMMEH LETTAR IPTR IN MAH INSTRUCTIONS
IZ IPTR IN MAH INSTRUCTIONS LIEK "["?
LOL LSPTR IN MAH LOOPSTACKZ R IPTR
UPZ LSPTR!!
KTHX
IZ IPTR IN MAH INSTRUCTIONS LIEK "]"?
I HAS A STARTPTR
NERFZ LSPTR!!
LOL STARTPTR R LSPTR IN MAH LOOPSTACKZ
LOL STARTPTR IN MAH LOOPZ R IPTR
LOL IPTR IN MAH LOOPZ R STARTPTR
KTHX
IZ IPTR IN MAH INSTRUCTIONS LIEK "!"?
GTFO
NOWAI
UPZ IPTR!!
KTHX
KTHX
BTW Variables for BF's tape
I HAS A LTAPE
I HAS A RTAPE
I HAS A LPTR
LOL LPTR R 0
I HAS A RPTR
LOL RPTR R 0
I HAS A CELL
LOL CELL R 0
BTW Reset instruction pointer to start
LOL IPTR R 0
BTW Start interpreting
IM IN YR LOOP
I HAS A THING
LOL THING R IPTR IN MAH INSTRUCTIONS
BTW Move tape head right
IZ THING LIEK ">"?
LOL LPTR IN MAH LTAPE R CELL
UPZ LPTR!!
IZ RPTR LIEK 0?
LOL CELL R 0
NOWAI
NERFZ RPTR!!
LOL CELL R RPTR IN MAH RTAPE
KTHX
KTHX
BTW Move tape head left
IZ THING LIEK "<"?
LOL RPTR IN MAH RTAPE R CELL
UPZ RPTR!!
IZ LPTR LIEK 0?
LOL CELL R 0
NOWAI
NERFZ LPTR!!
LOL CELL R LPTR IN MAH LTAPE
KTHX
KTHX
BTW Increment
IZ THING LIEK "+"?
UPZ CELL!!
KTHX
BTW Decrement
IZ THING LIEK "-"?
NERFZ CELL!!
KTHX
BTW Output produces numbers instead of ASCII characters
IZ THING LIEK "."?
VISIBLE CELL!
VISIBLE " "!
KTHX
BTW Input doesn't work because we can't convert characters to integers
BTW Oh well, it doesn't stop it being turing complete
BTW Start of loop
IZ THING LIEK "[" AND CELL LIEK 0?
LOL IPTR R IPTR IN MAH LOOPZ
KTHX
BTW End of loop
IZ THING LIEK "]" AND CELL NOT LIEK 0?
LOL IPTR R IPTR IN MAH LOOPZ
KTHX
BTW End of program!
IZ THING LIEK "!"?
GTFO
KTHX
UPZ IPTR!!
KTHX
KTHXBYE[/code]
[QUOTE=DEADBEEF;14232665][url]http://forum.lolcode.com/viewtopic.php?id=51[/url]
Some guy wrote a brainfuck interpreter in LOLCODE...
[code]HAI
BTW This is a BrainFuck interpreter written in LOLCode
BTW It accepts as input a BF program, followed by a "!", followed by any input to the BF program.
BTW Since BrainFuck is turing-complete, this proves that LOLCode is too
I HAS A INSTRUCTIONS BTW Array for BF instructions
I HAS A IPTR BTW Pointer to first empty element in INSTRUCTIONS
LOL IPTR R 0
I HAS A LOOPZ BTW Array of loop start/end addresses
I HAS A LOOPSTACKZ BTW Loop stack for building the above two
I HAS A LSPTR BTW Pointer to first empty element of LOOPSTACKZ
LOL LSPTR R 0
BTW Read in BF instructions, terminated with "!"
IM IN YR CODE
GIMMEH LETTAR IPTR IN MAH INSTRUCTIONS
IZ IPTR IN MAH INSTRUCTIONS LIEK "["?
LOL LSPTR IN MAH LOOPSTACKZ R IPTR
UPZ LSPTR!!
KTHX
IZ IPTR IN MAH INSTRUCTIONS LIEK "]"?
I HAS A STARTPTR
NERFZ LSPTR!!
LOL STARTPTR R LSPTR IN MAH LOOPSTACKZ
LOL STARTPTR IN MAH LOOPZ R IPTR
LOL IPTR IN MAH LOOPZ R STARTPTR
KTHX
IZ IPTR IN MAH INSTRUCTIONS LIEK "!"?
GTFO
NOWAI
UPZ IPTR!!
KTHX
KTHX
BTW Variables for BF's tape
I HAS A LTAPE
I HAS A RTAPE
I HAS A LPTR
LOL LPTR R 0
I HAS A RPTR
LOL RPTR R 0
I HAS A CELL
LOL CELL R 0
BTW Reset instruction pointer to start
LOL IPTR R 0
BTW Start interpreting
IM IN YR LOOP
I HAS A THING
LOL THING R IPTR IN MAH INSTRUCTIONS
BTW Move tape head right
IZ THING LIEK ">"?
LOL LPTR IN MAH LTAPE R CELL
UPZ LPTR!!
IZ RPTR LIEK 0?
LOL CELL R 0
NOWAI
NERFZ RPTR!!
LOL CELL R RPTR IN MAH RTAPE
KTHX
KTHX
BTW Move tape head left
IZ THING LIEK "<"?
LOL RPTR IN MAH RTAPE R CELL
UPZ RPTR!!
IZ LPTR LIEK 0?
LOL CELL R 0
NOWAI
NERFZ LPTR!!
LOL CELL R LPTR IN MAH LTAPE
KTHX
KTHX
BTW Increment
IZ THING LIEK "+"?
UPZ CELL!!
KTHX
BTW Decrement
IZ THING LIEK "-"?
NERFZ CELL!!
KTHX
BTW Output produces numbers instead of ASCII characters
IZ THING LIEK "."?
VISIBLE CELL!
VISIBLE " "!
KTHX
BTW Input doesn't work because we can't convert characters to integers
BTW Oh well, it doesn't stop it being turing complete
BTW Start of loop
IZ THING LIEK "[" AND CELL LIEK 0?
LOL IPTR R IPTR IN MAH LOOPZ
KTHX
BTW End of loop
IZ THING LIEK "]" AND CELL NOT LIEK 0?
LOL IPTR R IPTR IN MAH LOOPZ
KTHX
BTW End of program!
IZ THING LIEK "!"?
GTFO
KTHX
UPZ IPTR!!
KTHX
KTHXBYE[/code][/QUOTE]
Now someone just have to write a lolcode interpreter in brainfuck and the circle would be complete.
[QUOTE=noctune9;14234784]Now someone just have to write a lolcode interpreter in brainfuck and the circle would be complete.[/QUOTE]
D:!
Flash AS3 BF Intepreter (The program is hard-coded, will post better version tomorrow (it's 1 am here)).
UNSUPPORTED MEDIA, use [url]http://spamtheweb.com/ul/upload/230309/4679_BrainFuck.php[/url]
[QUOTE=noctune9;14234784]Now someone just have to write a lolcode interpreter in brainfuck and the circle would be complete.[/QUOTE]
And feed the LOLCode Brainfuck interpreter to it and run the LOLCode interpreter in the Brainfuck interpreter written in Brainfuck.
But seriously, LOLCode should implement a Brainfuck call, similar to inline assembler in higher-level languages.
[QUOTE=itsbth;14260124]Flash AS3 BF Intepreter (The program is hard-coded, will post better version tomorrow (it's 1 am here)).
UNSUPPORTED MEDIA, use [url]http://spamtheweb.com/ul/upload/230309/4679_BrainFuck.php[/url][/QUOTE]
Awesome. Slow as hell though.
[QUOTE=DrDaxxy;14271637]And feed the LOLCode Brainfuck interpreter to it and run the LOLCode interpreter in the Brainfuck interpreter written in Brainfuck.
But seriously, LOLCode should implement a Brainfuck call, similar to inline assembler in higher-level languages.[/QUOTE]
It would probably be quite easily implement inline brainfuck into a lua interpreter.
I've just jumped on the brainfuck band wagon and created an interpreter in python! Though it reads from an input rather than a file. I don't have any ideas on how to implement loops, if anyone could explain how they did it I would be glad too know.
[QUOTE=iPope;14289012]I've just jumped on the brainfuck band wagon and created an interpreter in python! Though it reads from an input rather than a file. I don't have any ideas on how to implement loops, if anyone could explain how they did it I would be glad too know.[/QUOTE]
Use recursion. Think of each piece of code as its own runnable piece. When you encounter a loop, that's another runnable piece within the upper 'parent' piece. It'd recurse like so:
[code]
run [whole]
// encounter loop
run [loop 0]
// encounter another loop
run [loop 1]
// end condition not met, keep run this loop again and again
run [loop 1]
...
// end condition not met, run this loop again and again
run [loop 0]
..
// end condition for loop 0 is met, continue execution wherever loop 0 left off
[/code]
Notice how each iteration of the loop recurses if the loop must go on. There's no iteration or anything.
If that explanation doesn't do it for you, you can look at either my code (download at the top of the page) or nullsquared's, both use recursion, though nullsquared's method is alot more efficient than mine by the looks of it.
Isn't recursion an inherently bad idea for implementing a [B]loop[/B]? Without optimized tail calls, you can encounter a buffer overflow, and recursion isn't nice on memory usage.
[QUOTE=Robber;14272284]Awesome. Slow as hell though.[/QUOTE]
It runs at one instruction per frame, at 30 frames per second.
This is the program it's running:
[code]++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.[/code]
(It was the first result I found when searching for "BrainFuck hello world")
PS:
[code]def brainfuckize(str):
out = ">\n" # Start with a zero to mark the end
for c in str[::-1]: # Reverse over the characters in reverse direction
out += ">" + ("+" * ord(c)) + "\n" # Write the chars ASCII value
out += "[.<]" # The code that actually prints the string
return out
if __name__ == '__main__':
import sys
file = sys.stdin
if len(sys.argv) == 2:
file = open(sys.argv[1], "r")
print brainfuckize(file.read())[/code]
Sorry, you need to Log In to post a reply to this thread.