public SpellburstCompileError PreProcess() { string[] sa = Code.Replace(Environment.NewLine, "\n").Split('\n'); //行数過多 if (sa.Length >= 8) { return(new SpellburstCompileError(ErrorType.TooManyNewLine)); } //禁止ワード if (ContainsFWords(Code)) { return(new SpellburstCompileError(ErrorType.FWord)); } //解釈処理 Code = string.Join("", sa); var iter = new SpellburstIterator(Code); var queue = new Queue <SpellCode>(); var i = new[] { SpellCode.None }; while ((i = iter.NextCode()) != null) { queue.EnqueueRange(i); } Interpreter.Codes = new List <SpellCode>(queue); //Console.WriteLine(queue.Select(e => e.ToString()).Aggregate(",", (s, e) => s += e + ",")); var mode = ReadMode.WaitIMP; var IMP = new SpellburstIMP(); var Command = new SpellburstCommand(); var Number = new SpellburstNumber(); var Label = new SpellburstLabel(); var ProgramCounter = 0; var SubroutineCall = 0; var SubroutineEnd = 0; var LabelTemp = 0; var labelDict = new Dictionary <string, int>(); var labelJumpDict = new List <string>(); Action reset = () => { IMP.Reset(); Command.Reset(); Number.Reset(); Label.Reset(); }; while (queue.Count != 0) { var first = queue.Dequeue(); switch (mode) { case ReadMode.WaitIMP: IMP.AddIMP(first); if (IMP.IsEqualTo("S")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("N")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("TS")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("TN")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("TT")) { mode = ReadMode.WaitCommand; } break; case ReadMode.WaitCommand: Command.AddCommand(first); //楽なのを先に処理 if (IMP.IsEqualTo("TT")) { if (Command.IsEqualTo("S")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("T")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("N")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } } //ここから本題 if (IMP.IsEqualTo("S")) { if (Command.IsEqualTo("S")) { mode = ReadMode.InputInteger; } if (Command.IsEqualTo("NS")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("NT")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("NN")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("T")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } } if (IMP.IsEqualTo("TS")) { if (Command.IsEqualTo("SS")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("ST")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("SN")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("TS")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("TT")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("TN")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } if (Command.IsEqualTo("N")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } } if (IMP.IsEqualTo("N")) { if (Command.IsEqualTo("SS")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } if (Command.IsEqualTo("ST")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } if (Command.IsEqualTo("SN")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } if (Command.IsEqualTo("TS")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } if (Command.IsEqualTo("TT")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } if (Command.IsEqualTo("TN")) { mode = ReadMode.WaitIMP; SubroutineEnd++; reset(); } if (Command.IsEqualTo("NN")) { mode = ReadMode.Finish; } if (Command.IsEqualTo("NS")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } if (Command.IsEqualTo("NT")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } //labelJumpDict } if (IMP.IsEqualTo("TN")) { if (Command.IsEqualTo("SS")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("ST")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("TS")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("TN")) { mode = ReadMode.WaitIMP; reset(); } if (Command.IsEqualTo("SN")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } if (Command.IsEqualTo("TT")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } if (Command.IsEqualTo("N")) { return(new SpellburstCompileError(ErrorType.CommandNotFound, ProgramCounter)); } } break; case ReadMode.InputInteger: if (first.Equals(SpellCode.NewLine)) { //スタックに数値をpushする(preprocessなのでしない) mode = ReadMode.WaitIMP; reset(); break; } Number.AddNumber(first); break; case ReadMode.InputLabel: if (first.Equals(SpellCode.NewLine)) { //ラベル定義 if (Command.IsEqualTo("SS")) { if (labelDict.ContainsKey(Label.Result)) { return(new SpellburstCompileError(ErrorType.LabelIsAlreadyDefined)); } labelDict.Add(Label.Result, LabelTemp); } //サブルーチン呼び出し if (Command.IsEqualTo("ST")) { labelJumpDict.Add(Label.Result); SubroutineCall++; } //無条件ジャンプ if (Command.IsEqualTo("SN")) { labelJumpDict.Add(Label.Result); } //ゼロならジャンプ if (Command.IsEqualTo("TS")) { labelJumpDict.Add(Label.Result); } //負ならジャンプ if (Command.IsEqualTo("TT")) { labelJumpDict.Add(Label.Result); } mode = ReadMode.WaitIMP; reset(); } Label.Add(first); break; case ReadMode.Finish: queue.Clear(); break; } ProgramCounter++; } foreach (var l in labelJumpDict) { if (!labelDict.ContainsKey(l)) { return(new SpellburstCompileError(ErrorType.InvalidLabelJump)); } } Interpreter.LabelDict = new Dictionary <string, int>(labelDict); return(new SpellburstCompileError(ErrorType.Success)); }
public SpellburstRuntimeError Run() { var mode = ReadMode.WaitIMP; var IMP = new SpellburstIMP(); var Command = new SpellburstCommand(); var Number = new SpellburstNumber(); var Label = new SpellburstLabel(); var ProgramCounter = 0; var RoutineMaxDepth = 31; var RoutineNowDepth = 0; var LabelTemp = 0; Action reset = () => { IMP.Reset(); Command.Reset(); Number.Reset(); Label.Reset(); mode = ReadMode.WaitIMP; }; while (Codes.Count != 0) { if (ProgramCounter >= Codes.Count) { break; } var first = Codes[ProgramCounter]; switch (mode) { case ReadMode.WaitIMP: IMP.AddIMP(first); if (IMP.IsEqualTo("S")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("N")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("TS")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("TN")) { mode = ReadMode.WaitCommand; } if (IMP.IsEqualTo("TT")) { mode = ReadMode.WaitCommand; } break; case ReadMode.WaitCommand: Command.AddCommand(first); //楽なのを先に処理 if (IMP.IsEqualTo("TT")) { //スタックの値をアドレスに格納 if (Command.IsEqualTo("S")) { if (CheckStackEmpty()) { return(new SpellburstRuntimeError(ErrorType.StackIsEmpty)); } Heap = IntegerStack.Peek(); reset(); } //アドレスの値をスタックに積む if (Command.IsEqualTo("T")) { IntegerStack.Push(Heap); reset(); } } //ここから本題 //スタック操作 if (IMP.IsEqualTo("S")) { //数値をスタックにプッシュ(ReadMode.InputIntegerの方で処理は行う) if (Command.IsEqualTo("S")) { mode = ReadMode.InputInteger; } //スタックトップを複製 if (Command.IsEqualTo("NS")) { IntegerStack.Push(IntegerStack.Peek()); reset(); } //スタックの1番目と2番目を交換 if (Command.IsEqualTo("NT")) { var e1 = IntegerStack.Pop(); var e2 = IntegerStack.Pop(); IntegerStack.Push(e1); IntegerStack.Push(e2); reset(); } //スタックトップを破棄 if (Command.IsEqualTo("NN")) { IntegerStack.Pop(); reset(); } } //四則演算+余 if (IMP.IsEqualTo("TS")) { //加減乗除余 if (Command.IsEqualTo("SS")) { Calc((e1, e2) => e1 + e2); reset(); } if (Command.IsEqualTo("ST")) { Calc((e1, e2) => e1 - e2); reset(); } if (Command.IsEqualTo("SN")) { Calc((e1, e2) => e1 * e2); reset(); } if (Command.IsEqualTo("TS")) { Calc((e1, e2) => e1 / e2); reset(); } if (Command.IsEqualTo("TT")) { Calc((e1, e2) => e1 % e2); reset(); } } //ラベル if (IMP.IsEqualTo("N")) { //ラベル定義 if (Command.IsEqualTo("SS")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } //サブルーチン呼び出し if (Command.IsEqualTo("ST")) { //階層チェック if (++RoutineNowDepth > RoutineMaxDepth) { return(new SpellburstRuntimeError(ErrorType.SubRoutineLevelTooDeep)); } mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } //無条件ジャンプ if (Command.IsEqualTo("SN")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } //スタックトップがゼロならジャンプ if (Command.IsEqualTo("TS")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } //スタックトップが負ならジャンプ if (Command.IsEqualTo("TT")) { mode = ReadMode.InputLabel; LabelTemp = ProgramCounter; } //サブルーチン終了 if (Command.IsEqualTo("TN")) { //階層チェック if (--RoutineNowDepth < 0) { return(new SpellburstRuntimeError(ErrorType.ReturnInNonSubroutine)); } ProgramCounter = CallFrom.Pop(); reset(); } //プログラム終了 if (Command.IsEqualTo("NN")) { mode = ReadMode.Finish; } } //入出力 if (IMP.IsEqualTo("TN")) { //スタックトップの文字を出力 if (Command.IsEqualTo("SS")) { var e = IntegerStack.Peek(); Console.Write(Convert.ToChar(e)); reset(); } //スタックトップの数値を出力 if (Command.IsEqualTo("ST")) { var e = IntegerStack.Peek(); Console.Write(e); reset(); } //文字を読み込みアドレスに格納 if (Command.IsEqualTo("TS")) { Heap = Console.Read(); reset(); } //数値を読み込みアドレスに格納 if (Command.IsEqualTo("TN")) { Heap = int.Parse(Console.ReadLine()); reset(); } } break; case ReadMode.InputInteger: if (first.Equals(SpellCode.NewLine)) { //スタックに数値をpushする(preprocessなのでしない) IntegerStack.Push(Number.Result); reset(); } Number.AddNumber(first); break; case ReadMode.InputLabel: if (first.Equals(SpellCode.NewLine)) { //ラベル定義 if (Command.IsEqualTo("SS")) { //何もしない } //サブルーチン呼び出し if (Command.IsEqualTo("ST")) { var row = LabelDict[Label.Result] - 1; CallFrom.Push(ProgramCounter); ProgramCounter = row; } //無条件ジャンプ if (Command.IsEqualTo("SN")) { ProgramCounter = LabelDict[Label.Result] - 1; } //ゼロならジャンプ if (Command.IsEqualTo("TS")) { if (IntegerStack.Peek() == 0) { ProgramCounter = LabelDict[Label.Result] - 1; } } //負ならジャンプ if (Command.IsEqualTo("TT")) { if (IntegerStack.Peek() < 0) { ProgramCounter = LabelDict[Label.Result] - 1; } } reset(); } Label.Add(first); break; case ReadMode.Finish: Codes.Clear(); break; } ProgramCounter++; } return(new SpellburstRuntimeError(ErrorType.Success)); }