/SimpleBrainFuck.Core/Core/SimpleCoder.cs
C# | 106 lines | 66 code | 17 blank | 23 comment | 17 complexity | d40e96a34af49a7c03b9689f3fac8a39 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
-
- namespace ZackFlame.SimpleBrainFuck.Core
- {
- /// <summary>
- /// Представляет транслятор SimpleBrainFuck-программы в BrainFuck-код.
- /// </summary>
- public sealed class SimpleCoder
- {
- static readonly SimpleParser parser = new SimpleParser();
- static readonly SimpleTranslator translator = new SimpleTranslator();
-
- readonly Regex trimEmptyLines = new Regex(@"\n\n+");
- readonly Regex multiCycles = new Regex(@"\[\[([^]]+)\]\]");
- readonly Regex multiZero = new Regex(@"(?:\[(?:\+|-)\]){2,}");
- readonly Regex zeroAfterCycle = new Regex(@"\]\[(?:\+|-)\]");
-
- /// <summary>
- /// Транслирует SimpleBrainFuck-программу в неоптимизированный BrainFuck-код.
- /// </summary>
- /// <param name="simpleCode">SimpleBrainFuck-программа.</param>
- /// <returns>BrainFuck-код.</returns>
- public string Translate(string simpleCode)
- {
- if (simpleCode == null)
- throw new ArgumentNullException("simpleCode");
-
- var tree = parser.BuildSemanticTree(simpleCode);
-
- string brainCode = trimEmptyLines.Replace(
- translator.RenderBrainFuck(tree), "\n");
-
- return brainCode.Trim('\n').Replace("\n", Environment.NewLine);
- }
-
- /// <summary>
- /// Оптимизирует BrainFuck-код.
- /// </summary>
- /// <param name="brainFuckCode">Неоптимизированный BrainFuck-код.</param>
- /// <returns>Оптимизированный BrainFuck-код.</returns>
- /// <remarks>
- /// Основные оптимизации - удаление бессмысленных переходов, вроде <<>>,
- /// а также сложений/вычитаний, например, ++--.
- /// </remarks>
- public string Optimize(string brainFuckCode)
- {
- if (brainFuckCode == null)
- throw new ArgumentNullException("brainFuckCode");
-
- if (brainFuckCode.Length <= 1)
- return brainFuckCode;
-
- string code = brainFuckCode;
-
- while (code.IndexOf("<>") != -1 || code.IndexOf("><") != -1 ||
- code.IndexOf("+-") != -1 || code.IndexOf("-+") != -1)
- {
- code = code
- .Replace("<>", string.Empty)
- .Replace("><", string.Empty)
- .Replace("+-", string.Empty)
- .Replace("-+", string.Empty);
- }
-
- code = multiZero.Replace(code, SystemFunctions.Zero());
- code = zeroAfterCycle.Replace(code, "]");
-
- while (multiCycles.IsMatch(code))
- {
- code = multiCycles.Replace(code,
- match => "[" + match.Groups[1] + "]");
- }
-
- return code;
- }
-
- /// <summary>
- /// Разбивает код на строки заданной длины (за исключением последней).
- /// </summary>
- /// <param name="brainFuckCode">Код для разбиения на строки.</param>
- /// <param name="lineLength">Длина строк результирующего кода.</param>
- /// <returns>Код, разбитый на строки заданной длины.</returns>
- public string SetLineLength(string brainFuckCode, int lineLength)
- {
- if (brainFuckCode == null)
- throw new ArgumentNullException("brainFuckCode");
- if (lineLength <= 0)
- throw new ArgumentOutOfRangeException("lineLength", "lineLength must be >= 0.");
-
- StringBuilder result = new StringBuilder(brainFuckCode);
- result.Replace(Environment.NewLine, string.Empty);
-
- int newLineLength = lineLength + Environment.NewLine.Length;
- for (int i = lineLength; i < result.Length; i += newLineLength)
- {
- result.Insert(i, Environment.NewLine);
- }
-
- return result.ToString();
- }
- }
- }