Advertisement
AyrA

Brainfuck.cs

Apr 29th, 2016
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.47 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using System.Text;
  3. using System.CodeDom.Compiler;
  4. using Microsoft.CSharp;
  5. using System.IO;
  6. using System;
  7.  
  8. namespace BrainfuckCompiler
  9. {
  10.     /// <summary>
  11.     /// Brainfuck compiler and transpiler
  12.     /// </summary>
  13.     public class Brainfuck
  14.     {
  15.         /// <summary>
  16.         /// Main frame for the output
  17.         /// </summary>
  18.         public const string MAIN = @"using System;
  19. static class Program
  20. {
  21. static int Main(string[] Args)
  22. {
  23. int Index=0;
  24. char[] Values=new char[/*MEMSIZE*/];
  25. /*COMPILED*/
  26. return (int)Values[Index];
  27. }
  28.  
  29. static void Put(char C)
  30. {
  31. Console.Write(C);
  32. }
  33.  
  34. static char Get()
  35. {
  36. Put('>');
  37. char C=Console.ReadKey(true).KeyChar;
  38. return C==27?'\0':C;
  39. }
  40. }
  41. ";
  42.         /// <summary>
  43.         /// Memory size in bytes
  44.         /// </summary>
  45.         public const int MEMSIZE = 32000;
  46.  
  47.         //no changes needed below
  48.  
  49.         public const string REPLACE = "/*COMPILED*/";
  50.         public const string CODE = "/*SOURCE*/";
  51.         public const string MEM = "/*MEMSIZE*/";
  52.         private const string VALUE = "VAL";
  53.         private Dictionary<char, string> Commands;
  54.         private Dictionary<char, string> MultiCommands;
  55.  
  56.         /// <summary>
  57.         /// Creates a new Brainfuck instance
  58.         /// </summary>
  59.         public Brainfuck()
  60.         {
  61.             Init();
  62.         }
  63.  
  64.         /// <summary>
  65.         /// Resets all codes
  66.         /// </summary>
  67.         private void Init()
  68.         {
  69.             Commands = new Dictionary<char, string>();
  70.             MultiCommands = new Dictionary<char, string>();
  71.             //add strings
  72.             Commands.Add('>', "++Index;\r\n");
  73.             Commands.Add('<', "--Index;\r\n");
  74.             Commands.Add('+', "++Values[Index];\r\n");
  75.             Commands.Add('-', "--Values[Index];\r\n");
  76.             Commands.Add('[', "while(Values[Index]!=0)\r\n{\r\n");
  77.             Commands.Add(']', "}\r\n");
  78.             Commands.Add('.', "Put(Values[Index]);\r\n");
  79.             Commands.Add(',', "Values[Index]=Get();\r\n");
  80.             //add multi-commands
  81.             MultiCommands.Add('>', "Index+=VAL;\r\n");
  82.             MultiCommands.Add('<', "Index-=VAL;\r\n");
  83.             MultiCommands.Add('+', "Values[Index]+=(char)VAL;\r\n");
  84.             MultiCommands.Add('-', "Values[Index]-=(char)VAL;\r\n");
  85.         }
  86.  
  87.         /// <summary>
  88.         /// Removes all non-code data
  89.         /// </summary>
  90.         /// <param name="Source">Source code</param>
  91.         /// <returns>Cleaned brainfuck</returns>
  92.         public string Filter(string SourceCode)
  93.         {
  94.             Init();
  95.             StringBuilder SB = new StringBuilder();
  96.             foreach (char C in SourceCode)
  97.             {
  98.                 if (Commands.ContainsKey(C))
  99.                 {
  100.                     SB.Append(C);
  101.                 }
  102.             }
  103.             return SB.ToString();
  104.         }
  105.  
  106.         /// <summary>
  107.         /// Parses a brainfuck file and returns optimized C# code
  108.         /// </summary>
  109.         /// <param name="SourceCode">Source code</param>
  110.         /// <returns>C# code</returns>
  111.         public string Parse(string SourceCode)
  112.         {
  113.             return Parse(SourceCode, true);
  114.         }
  115.  
  116.         /// <summary>
  117.         /// Parses a brainfuck file and returns C# code
  118.         /// </summary>
  119.         /// <param name="SourceCode">Source code</param>
  120.         /// <param name="optimize">true, to optimize commands</param>
  121.         /// <returns>C# code</returns>
  122.         public string Parse(string SourceCode, bool optimize)
  123.         {
  124.             Init();
  125.             //CurrentIndent = 2;
  126.             List<string> Parts = new List<string>();
  127.             //add dummy item
  128.             Parts.Add("YAY");
  129.             SourceCode = Filter(SourceCode);
  130.             //add optimizations here
  131.             if (optimize)
  132.             {
  133.                 //[-] sets the current value to 0 ([+] does too)
  134.                 Commands.Add('!', "Values[Index]='\\0';\r\n");
  135.                 SourceCode = SourceCode
  136.                     .Replace("[-]", "!")
  137.                     .Replace("[+]", "!");
  138.             }
  139.  
  140.             foreach (char c in SourceCode)
  141.             {
  142.                 if (Commands.ContainsKey(c))
  143.                 {
  144.                     if (optimize && Parts[Parts.Count - 1][0] == c)
  145.                     {
  146.                         Parts[Parts.Count - 1] += c;
  147.                     }
  148.                     else
  149.                     {
  150.                         Parts.Add(c.ToString());
  151.                     }
  152.                 }
  153.             }
  154.             //remove dummy item
  155.             Parts.RemoveAt(0);
  156.             StringBuilder SB = new StringBuilder();
  157.             foreach (string s in Parts)
  158.             {
  159.                 SB.Append(MultiCommand(s));
  160.             }
  161.             return MAIN
  162.                 .Replace(REPLACE, SB.ToString())
  163.                 .Replace(CODE, SourceCode)
  164.                 .Replace(MEM, MEMSIZE.ToString());
  165.         }
  166.  
  167.         /// <summary>
  168.         /// Compresses code using simple Replacements (still valid C#)
  169.         /// </summary>
  170.         /// <param name="Code">Code</param>
  171.         /// <returns>Compressed code</returns>
  172.         public string Compress(string SourceCode)
  173.         {
  174.             return SourceCode
  175.                 .Replace("Put", "W")
  176.                 .Replace("Get", "R")
  177.                 //.Replace("32000", "1<<15") //not actually shorter, just obfuscated
  178.                 .Replace("Values", "V")
  179.                 .Replace("Index", "I")
  180.                 .Replace('\t', '\n')
  181.                 .Replace('\r', '\n')
  182.                 .Replace("\n", "");
  183.         }
  184.  
  185.         /// <summary>
  186.         /// gets the shortest version of a multicommand
  187.         /// </summary>
  188.         /// <param name="Command">Command</param>
  189.         /// <returns>multicommand</returns>
  190.         private string MultiCommand(string Command)
  191.         {
  192.             return MultiCommand(Command[0], Command.Length);
  193.         }
  194.  
  195.         /// <summary>
  196.         /// gets the shortest version of a multicommand
  197.         /// </summary>
  198.         /// <param name="Command">Command</param>
  199.         /// <param name="Count">How often it is repeated</param>
  200.         /// <returns>multicommand</returns>
  201.         public string MultiCommand(char Command, int Count)
  202.         {
  203.             if (Count == 1)
  204.             {
  205.                 return Commands[Command];
  206.             }
  207.             if (MultiCommands.ContainsKey(Command))
  208.             {
  209.                 return MultiCommands[Command].Replace(VALUE, Count.ToString());
  210.             }
  211.             else
  212.             {
  213.                 StringBuilder SB = new StringBuilder(Commands[Command].Length * Count);
  214.                 for (int i = 0; i < Count; i++)
  215.                 {
  216.                     SB.Append(Commands[Command]);
  217.                 }
  218.                 return SB.ToString();
  219.             }
  220.         }
  221.  
  222.         /// <summary>
  223.         /// Compiles C# source code
  224.         /// </summary>
  225.         /// <param name="SourceCode">Source code (not the file name)</param>
  226.         /// <param name="TargetFile">Target file</param>
  227.         /// <returns>true, if successful</returns>
  228.         public bool Compile(string SourceCode,string TargetFile)
  229.         {
  230.             using (CodeDomProvider codeProvider = new CSharpCodeProvider())
  231.             {
  232.                 CompilerParameters compilerParams = new CompilerParameters();
  233.                 compilerParams.MainClass = "Program";
  234.                 compilerParams.OutputAssembly = TargetFile;
  235.                 compilerParams.CompilerOptions = " /optimize";
  236.                 compilerParams.GenerateExecutable = true;
  237.                 compilerParams.IncludeDebugInformation = false;
  238.                 compilerParams.ReferencedAssemblies.Add("mscorlib.dll");
  239.                 compilerParams.ReferencedAssemblies.Add("System.dll");
  240.  
  241.                 CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParams, new string[] { SourceCode });
  242.  
  243.                 if (results.Errors.Count > 0)
  244.                 {
  245.                     Console.ForegroundColor = ConsoleColor.Red;
  246.                     foreach (CompilerError E in results.Errors)
  247.                     {
  248.                         Console.ForegroundColor = E.IsWarning ? ConsoleColor.Yellow : ConsoleColor.Red;
  249.                         Console.WriteLine("<{0}:{1}> [{2}]: {3}", E.Line, E.Column, E.ErrorNumber, E.ErrorText);
  250.                     }
  251.                 }
  252.                 return results.Errors.Count > 0;
  253.             }
  254.         }
  255.     }
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement