Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Text;
- using System.CodeDom.Compiler;
- using Microsoft.CSharp;
- using System.IO;
- using System;
- namespace BrainfuckCompiler
- {
- /// <summary>
- /// Brainfuck compiler and transpiler
- /// </summary>
- public class Brainfuck
- {
- /// <summary>
- /// Main frame for the output
- /// </summary>
- public const string MAIN = @"using System;
- static class Program
- {
- static int Main(string[] Args)
- {
- int Index=0;
- char[] Values=new char[/*MEMSIZE*/];
- /*COMPILED*/
- return (int)Values[Index];
- }
- static void Put(char C)
- {
- Console.Write(C);
- }
- static char Get()
- {
- Put('>');
- char C=Console.ReadKey(true).KeyChar;
- return C==27?'\0':C;
- }
- }
- ";
- /// <summary>
- /// Memory size in bytes
- /// </summary>
- public const int MEMSIZE = 32000;
- //no changes needed below
- public const string REPLACE = "/*COMPILED*/";
- public const string CODE = "/*SOURCE*/";
- public const string MEM = "/*MEMSIZE*/";
- private const string VALUE = "VAL";
- private Dictionary<char, string> Commands;
- private Dictionary<char, string> MultiCommands;
- /// <summary>
- /// Creates a new Brainfuck instance
- /// </summary>
- public Brainfuck()
- {
- Init();
- }
- /// <summary>
- /// Resets all codes
- /// </summary>
- private void Init()
- {
- Commands = new Dictionary<char, string>();
- MultiCommands = new Dictionary<char, string>();
- //add strings
- Commands.Add('>', "++Index;\r\n");
- Commands.Add('<', "--Index;\r\n");
- Commands.Add('+', "++Values[Index];\r\n");
- Commands.Add('-', "--Values[Index];\r\n");
- Commands.Add('[', "while(Values[Index]!=0)\r\n{\r\n");
- Commands.Add(']', "}\r\n");
- Commands.Add('.', "Put(Values[Index]);\r\n");
- Commands.Add(',', "Values[Index]=Get();\r\n");
- //add multi-commands
- MultiCommands.Add('>', "Index+=VAL;\r\n");
- MultiCommands.Add('<', "Index-=VAL;\r\n");
- MultiCommands.Add('+', "Values[Index]+=(char)VAL;\r\n");
- MultiCommands.Add('-', "Values[Index]-=(char)VAL;\r\n");
- }
- /// <summary>
- /// Removes all non-code data
- /// </summary>
- /// <param name="Source">Source code</param>
- /// <returns>Cleaned brainfuck</returns>
- public string Filter(string SourceCode)
- {
- Init();
- StringBuilder SB = new StringBuilder();
- foreach (char C in SourceCode)
- {
- if (Commands.ContainsKey(C))
- {
- SB.Append(C);
- }
- }
- return SB.ToString();
- }
- /// <summary>
- /// Parses a brainfuck file and returns optimized C# code
- /// </summary>
- /// <param name="SourceCode">Source code</param>
- /// <returns>C# code</returns>
- public string Parse(string SourceCode)
- {
- return Parse(SourceCode, true);
- }
- /// <summary>
- /// Parses a brainfuck file and returns C# code
- /// </summary>
- /// <param name="SourceCode">Source code</param>
- /// <param name="optimize">true, to optimize commands</param>
- /// <returns>C# code</returns>
- public string Parse(string SourceCode, bool optimize)
- {
- Init();
- //CurrentIndent = 2;
- List<string> Parts = new List<string>();
- //add dummy item
- Parts.Add("YAY");
- SourceCode = Filter(SourceCode);
- //add optimizations here
- if (optimize)
- {
- //[-] sets the current value to 0 ([+] does too)
- Commands.Add('!', "Values[Index]='\\0';\r\n");
- SourceCode = SourceCode
- .Replace("[-]", "!")
- .Replace("[+]", "!");
- }
- foreach (char c in SourceCode)
- {
- if (Commands.ContainsKey(c))
- {
- if (optimize && Parts[Parts.Count - 1][0] == c)
- {
- Parts[Parts.Count - 1] += c;
- }
- else
- {
- Parts.Add(c.ToString());
- }
- }
- }
- //remove dummy item
- Parts.RemoveAt(0);
- StringBuilder SB = new StringBuilder();
- foreach (string s in Parts)
- {
- SB.Append(MultiCommand(s));
- }
- return MAIN
- .Replace(REPLACE, SB.ToString())
- .Replace(CODE, SourceCode)
- .Replace(MEM, MEMSIZE.ToString());
- }
- /// <summary>
- /// Compresses code using simple Replacements (still valid C#)
- /// </summary>
- /// <param name="Code">Code</param>
- /// <returns>Compressed code</returns>
- public string Compress(string SourceCode)
- {
- return SourceCode
- .Replace("Put", "W")
- .Replace("Get", "R")
- //.Replace("32000", "1<<15") //not actually shorter, just obfuscated
- .Replace("Values", "V")
- .Replace("Index", "I")
- .Replace('\t', '\n')
- .Replace('\r', '\n')
- .Replace("\n", "");
- }
- /// <summary>
- /// gets the shortest version of a multicommand
- /// </summary>
- /// <param name="Command">Command</param>
- /// <returns>multicommand</returns>
- private string MultiCommand(string Command)
- {
- return MultiCommand(Command[0], Command.Length);
- }
- /// <summary>
- /// gets the shortest version of a multicommand
- /// </summary>
- /// <param name="Command">Command</param>
- /// <param name="Count">How often it is repeated</param>
- /// <returns>multicommand</returns>
- public string MultiCommand(char Command, int Count)
- {
- if (Count == 1)
- {
- return Commands[Command];
- }
- if (MultiCommands.ContainsKey(Command))
- {
- return MultiCommands[Command].Replace(VALUE, Count.ToString());
- }
- else
- {
- StringBuilder SB = new StringBuilder(Commands[Command].Length * Count);
- for (int i = 0; i < Count; i++)
- {
- SB.Append(Commands[Command]);
- }
- return SB.ToString();
- }
- }
- /// <summary>
- /// Compiles C# source code
- /// </summary>
- /// <param name="SourceCode">Source code (not the file name)</param>
- /// <param name="TargetFile">Target file</param>
- /// <returns>true, if successful</returns>
- public bool Compile(string SourceCode,string TargetFile)
- {
- using (CodeDomProvider codeProvider = new CSharpCodeProvider())
- {
- CompilerParameters compilerParams = new CompilerParameters();
- compilerParams.MainClass = "Program";
- compilerParams.OutputAssembly = TargetFile;
- compilerParams.CompilerOptions = " /optimize";
- compilerParams.GenerateExecutable = true;
- compilerParams.IncludeDebugInformation = false;
- compilerParams.ReferencedAssemblies.Add("mscorlib.dll");
- compilerParams.ReferencedAssemblies.Add("System.dll");
- CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParams, new string[] { SourceCode });
- if (results.Errors.Count > 0)
- {
- Console.ForegroundColor = ConsoleColor.Red;
- foreach (CompilerError E in results.Errors)
- {
- Console.ForegroundColor = E.IsWarning ? ConsoleColor.Yellow : ConsoleColor.Red;
- Console.WriteLine("<{0}:{1}> [{2}]: {3}", E.Line, E.Column, E.ErrorNumber, E.ErrorText);
- }
- }
- return results.Errors.Count > 0;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement