/IronBrainFuck/Parser/BrainParser.cs
C# | 118 lines | 99 code | 9 blank | 10 comment | 16 complexity | fff2b4611a62213dcf2419c646ac7fb2 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
-
- namespace ZackFlame.IronBrainFuck.Parser
- {
- /// <summary>
- /// Предоставляет методы для парсинга BrainFuck программы.
- /// </summary>
- public static class BrainParser
- {
- const string AllowedChars = "+-><[].,#@";
-
- internal static readonly BrainOperation[] SingleOperations =
- new BrainOperation[]
- {
- BrainOperation.CycleOpen,
- BrainOperation.CycleClose,
- BrainOperation.Write,
- BrainOperation.Read,
- BrainOperation.SpecialWrite,
- BrainOperation.SpecialRead,
- };
-
- /// <summary>
- /// Преобразует BrainFuck программу в массив экземпляров BrainAction.
- /// </summary>
- /// <param name="brainFuckProgram">BrainFuck программа.</param>
- /// <returns>Разобранная BrainFuck программа.</returns>
- public static BrainAction[] Parse(string brainFuckProgram)
- {
- // Удаляем лишние символы
- StringBuilder programBuilder = new StringBuilder();
- for (int i = 0; i < brainFuckProgram.Length; i++)
- {
- if (AllowedChars.IndexOf(brainFuckProgram[i]) != -1)
- programBuilder.Append(brainFuckProgram[i]);
- }
- string program = programBuilder.ToString();
-
- // Парсим
- List<BrainAction> actions = new List<BrainAction>();
- BrainOperation previous = BrainOperation.None;
- BrainOperation operation = BrainOperation.None;
- uint count = 0;
-
- for (int i = 0; i < program.Length; i++)
- {
- previous = operation;
-
- switch (program[i])
- {
- case '+':
- operation = BrainOperation.Add;
- break;
- case '-':
- operation = BrainOperation.Sub;
- break;
- case '>':
- operation = BrainOperation.Right;
- break;
- case '<':
- operation = BrainOperation.Left;
- break;
- case '[':
- if (i < program.Length - 2 && program[i + 2] == ']' &&
- (program[i + 1] == '-' || program[i] == '+'))
- {
- operation = BrainOperation.Zero;
- i += 2;
- }
- else
- {
- operation = BrainOperation.CycleOpen;
- }
- break;
- case ']':
- operation = BrainOperation.CycleClose;
- break;
- case '.':
- operation = BrainOperation.Write;
- break;
- case ',':
- operation = BrainOperation.Read;
- break;
- case '#':
- operation = BrainOperation.SpecialWrite;
- break;
- case '@':
- operation = BrainOperation.SpecialRead;
- break;
- default:
- operation = BrainOperation.None;
- break;
- }
-
- if (operation != previous)
- {
- actions.Add(new BrainAction(previous, count));
- count = 1;
- }
- else
- {
- if (SingleOperations.Contains(previous))
- actions.Add(new BrainAction(previous, 1));
- else
- count++;
- }
- }
-
- if (operation != BrainOperation.None)
- actions.Add(new BrainAction(operation, count));
-
- return actions.ToArray();
- }
- }
- }