PageRenderTime 38ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/IronBrainFuck/Parser/BrainParser.cs

http://ironbrainfuck.codeplex.com
C# | 118 lines | 99 code | 9 blank | 10 comment | 16 complexity | fff2b4611a62213dcf2419c646ac7fb2 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace ZackFlame.IronBrainFuck.Parser
  6. {
  7. /// <summary>
  8. /// Предоставляет методы для парсинга BrainFuck программы.
  9. /// </summary>
  10. public static class BrainParser
  11. {
  12. const string AllowedChars = "+-><[].,#@";
  13. internal static readonly BrainOperation[] SingleOperations =
  14. new BrainOperation[]
  15. {
  16. BrainOperation.CycleOpen,
  17. BrainOperation.CycleClose,
  18. BrainOperation.Write,
  19. BrainOperation.Read,
  20. BrainOperation.SpecialWrite,
  21. BrainOperation.SpecialRead,
  22. };
  23. /// <summary>
  24. /// Преобразует BrainFuck программу в массив экземпляров BrainAction.
  25. /// </summary>
  26. /// <param name="brainFuckProgram">BrainFuck программа.</param>
  27. /// <returns>Разобранная BrainFuck программа.</returns>
  28. public static BrainAction[] Parse(string brainFuckProgram)
  29. {
  30. // Удаляем лишние символы
  31. StringBuilder programBuilder = new StringBuilder();
  32. for (int i = 0; i < brainFuckProgram.Length; i++)
  33. {
  34. if (AllowedChars.IndexOf(brainFuckProgram[i]) != -1)
  35. programBuilder.Append(brainFuckProgram[i]);
  36. }
  37. string program = programBuilder.ToString();
  38. // Парсим
  39. List<BrainAction> actions = new List<BrainAction>();
  40. BrainOperation previous = BrainOperation.None;
  41. BrainOperation operation = BrainOperation.None;
  42. uint count = 0;
  43. for (int i = 0; i < program.Length; i++)
  44. {
  45. previous = operation;
  46. switch (program[i])
  47. {
  48. case '+':
  49. operation = BrainOperation.Add;
  50. break;
  51. case '-':
  52. operation = BrainOperation.Sub;
  53. break;
  54. case '>':
  55. operation = BrainOperation.Right;
  56. break;
  57. case '<':
  58. operation = BrainOperation.Left;
  59. break;
  60. case '[':
  61. if (i < program.Length - 2 && program[i + 2] == ']' &&
  62. (program[i + 1] == '-' || program[i] == '+'))
  63. {
  64. operation = BrainOperation.Zero;
  65. i += 2;
  66. }
  67. else
  68. {
  69. operation = BrainOperation.CycleOpen;
  70. }
  71. break;
  72. case ']':
  73. operation = BrainOperation.CycleClose;
  74. break;
  75. case '.':
  76. operation = BrainOperation.Write;
  77. break;
  78. case ',':
  79. operation = BrainOperation.Read;
  80. break;
  81. case '#':
  82. operation = BrainOperation.SpecialWrite;
  83. break;
  84. case '@':
  85. operation = BrainOperation.SpecialRead;
  86. break;
  87. default:
  88. operation = BrainOperation.None;
  89. break;
  90. }
  91. if (operation != previous)
  92. {
  93. actions.Add(new BrainAction(previous, count));
  94. count = 1;
  95. }
  96. else
  97. {
  98. if (SingleOperations.Contains(previous))
  99. actions.Add(new BrainAction(previous, 1));
  100. else
  101. count++;
  102. }
  103. }
  104. if (operation != BrainOperation.None)
  105. actions.Add(new BrainAction(operation, count));
  106. return actions.ToArray();
  107. }
  108. }
  109. }