Skip to content

Instantly share code, notes, and snippets.

@mwolicki
Last active November 18, 2016 23:28
Show Gist options
  • Save mwolicki/e7d398cd47a980b2cf94277ad8fa4ffc to your computer and use it in GitHub Desktop.
Save mwolicki/e7d398cd47a980b2cf94277ad8fa4ffc to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
static class BrainFuck
{
public static void Process (string txt)
{
var code = txt.Where (Single.AllowedChars.Union (Loop.AllowedChars).Contains);
var state = new State ();
foreach (var op in Parse (code)) {
op.Eval (state);
}
}
static IEnumerable<Op> Parse (IEnumerable<char> code)
{
var chs = code.ToArray ();
for (int i = 0; i < chs.Length; i++) {
var ch = chs [i];
if (Single.AllowedChars.Contains (ch)) {
yield return new Single (ch);
} else if (ch == '[') {
var vals = Parse (chs.Skip (i + 1));
var loop = new Loop (vals);
i += loop.Size - 1;
if (chs [i] != ']') { throw new Exception (":-("); }
yield return loop;
} else {
yield break;
}
}
}
class State
{
public void IncPointer () => index++;
public void DecPointer () => index--;
public void IncVal () => CurrVal++;
public void DecVal () => CurrVal--;
public byte CurrVal {
get {
byte val;
memory.TryGetValue (index, out val);
return val;
}
set {
memory [index] = value;
}
}
int index;
readonly Dictionary<int, byte> memory = new Dictionary<int, byte> ();
}
interface Op
{
void Eval (State state);
int Size { get; }
}
class Single : Op
{
public Single (char ch)
{
if (!AllowedChars.Contains (ch))
throw new ArgumentOutOfRangeException (nameof (ch));
Val = ch;
}
public int Size => 1;
public void Eval (State state)
{
switch (Val) {
case '+': state.IncVal (); return;
case '-': state.DecVal (); return;
case '>': state.IncPointer (); return;
case '<': state.DecPointer (); return;
case '.': Console.Write ((char)state.CurrVal); return;
case ',': state.CurrVal = (byte)Console.Read (); return;
default: throw new Exception ();
}
}
readonly char Val;
public static IEnumerable<char> AllowedChars { get; } = new [] { '.', ',', '<', '>', '+', '-' };
}
class Loop : Op
{
public Loop (IEnumerable<Op> ops)
{
Ops = ops;
}
public int Size => Ops.Sum (p => p.Size) + 2;
public void Eval (State state)
{
while (state.CurrVal != 0) {
foreach (var op in Ops) {
op.Eval (state);
}
}
}
readonly IEnumerable<Op> Ops;
public static IEnumerable<char> AllowedChars { get; } = new [] { '[', ']' };
}
}
class MainClass
{
public static void Main () =>
BrainFuck.Process (@"[[]]++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment