PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/SimpleBrainFuck.Core/Core/SimpleCoder.cs

http://ironbrainfuck.codeplex.com
C# | 106 lines | 66 code | 17 blank | 23 comment | 17 complexity | d40e96a34af49a7c03b9689f3fac8a39 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. namespace ZackFlame.SimpleBrainFuck.Core
  7. {
  8. /// <summary>
  9. /// Представляет транслятор SimpleBrainFuck-программы в BrainFuck-код.
  10. /// </summary>
  11. public sealed class SimpleCoder
  12. {
  13. static readonly SimpleParser parser = new SimpleParser();
  14. static readonly SimpleTranslator translator = new SimpleTranslator();
  15. readonly Regex trimEmptyLines = new Regex(@"\n\n+");
  16. readonly Regex multiCycles = new Regex(@"\[\[([^]]+)\]\]");
  17. readonly Regex multiZero = new Regex(@"(?:\[(?:\+|-)\]){2,}");
  18. readonly Regex zeroAfterCycle = new Regex(@"\]\[(?:\+|-)\]");
  19. /// <summary>
  20. /// Транслирует SimpleBrainFuck-программу в неоптимизированный BrainFuck-код.
  21. /// </summary>
  22. /// <param name="simpleCode">SimpleBrainFuck-программа.</param>
  23. /// <returns>BrainFuck-код.</returns>
  24. public string Translate(string simpleCode)
  25. {
  26. if (simpleCode == null)
  27. throw new ArgumentNullException("simpleCode");
  28. var tree = parser.BuildSemanticTree(simpleCode);
  29. string brainCode = trimEmptyLines.Replace(
  30. translator.RenderBrainFuck(tree), "\n");
  31. return brainCode.Trim('\n').Replace("\n", Environment.NewLine);
  32. }
  33. /// <summary>
  34. /// Оптимизирует BrainFuck-код.
  35. /// </summary>
  36. /// <param name="brainFuckCode">Неоптимизированный BrainFuck-код.</param>
  37. /// <returns>Оптимизированный BrainFuck-код.</returns>
  38. /// <remarks>
  39. /// Основные оптимизации - удаление бессмысленных переходов, вроде &lt;&lt;&gt;&gt;,
  40. /// а также сложений/вычитаний, например, ++--.
  41. /// </remarks>
  42. public string Optimize(string brainFuckCode)
  43. {
  44. if (brainFuckCode == null)
  45. throw new ArgumentNullException("brainFuckCode");
  46. if (brainFuckCode.Length <= 1)
  47. return brainFuckCode;
  48. string code = brainFuckCode;
  49. while (code.IndexOf("<>") != -1 || code.IndexOf("><") != -1 ||
  50. code.IndexOf("+-") != -1 || code.IndexOf("-+") != -1)
  51. {
  52. code = code
  53. .Replace("<>", string.Empty)
  54. .Replace("><", string.Empty)
  55. .Replace("+-", string.Empty)
  56. .Replace("-+", string.Empty);
  57. }
  58. code = multiZero.Replace(code, SystemFunctions.Zero());
  59. code = zeroAfterCycle.Replace(code, "]");
  60. while (multiCycles.IsMatch(code))
  61. {
  62. code = multiCycles.Replace(code,
  63. match => "[" + match.Groups[1] + "]");
  64. }
  65. return code;
  66. }
  67. /// <summary>
  68. /// Разбивает код на строки заданной длины (за исключением последней).
  69. /// </summary>
  70. /// <param name="brainFuckCode">Код для разбиения на строки.</param>
  71. /// <param name="lineLength">Длина строк результирующего кода.</param>
  72. /// <returns>Код, разбитый на строки заданной длины.</returns>
  73. public string SetLineLength(string brainFuckCode, int lineLength)
  74. {
  75. if (brainFuckCode == null)
  76. throw new ArgumentNullException("brainFuckCode");
  77. if (lineLength <= 0)
  78. throw new ArgumentOutOfRangeException("lineLength", "lineLength must be >= 0.");
  79. StringBuilder result = new StringBuilder(brainFuckCode);
  80. result.Replace(Environment.NewLine, string.Empty);
  81. int newLineLength = lineLength + Environment.NewLine.Length;
  82. for (int i = lineLength; i < result.Length; i += newLineLength)
  83. {
  84. result.Insert(i, Environment.NewLine);
  85. }
  86. return result.ToString();
  87. }
  88. }
  89. }