Last active
November 18, 2016 23:28
-
-
Save mwolicki/e7d398cd47a980b2cf94277ad8fa4ffc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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