/// <summary> /// ContextStage を読み取ります。 /// </summary> /// <param name="p">読み取りを実行している ContextCompiler を指定します。</param> /// <param name="stage">読み取った stage を返します。</param> /// <returns>現在の Context 内の stage を全て読み終わってもう残りが無い時に false を返します。 /// それ以外の場合には stage を読み取って true を返します。</returns> public static bool Read(ContextCompiler p, out ContextStage stage) { stage = new ContextStage(); if (p.wreader.CurrentType == WordType.Invalid) { return(false); } stage.words = new System.Collections.Generic.List <ContextCondition>(); stage.cmds = new System.Collections.Generic.List <ContextCommand>(); // 分岐標 読み取り ContextCondition ctxword; while (p.wreader.CurrentType == WordType.Identifier) { if (!ContextCondition.Read(p, out ctxword)) { break; } stage.words.Add(ctxword); } if (p.wreader.CurrentType == WordType.Operator && p.wreader.CurrentWord == ":") { p.wreader.ReadNext(); } // 命令 読み取り ContextCommand ctxcmd; while (p.wreader.CurrentType == WordType.Identifier) { if (!ContextCommand.Read(p, out ctxcmd)) { break; } stage.cmds.Add(ctxcmd); } if (p.wreader.CurrentType == WordType.Operator && p.wreader.CurrentWord == ";") { p.wreader.ReadNext(); } // 結果判定 if (stage.cmds.Count == 0) { // 何も (命令も分岐標も) 読み取っていない時 if (stage.words.Count == 0) { return(false); } // 命令が一つもないのに分岐標がある時 p.wreader.LetterReader.SetError("対応する命令列が存在しません。", 0, null); stage.cmds.Add(new ContextCommand("ret", "")); } return(true); }
public static bool Read(ContextCompiler cc, out ContextCommand contextcmd) { contextcmd = new ContextCommand(); AbstractWordReader wreader = cc.wreader; start: if (wreader.CurrentType == WordType.Invalid) { return(false); } string word = wreader.CurrentWord; if (wreader.CurrentType != WordType.Identifier) { if (word == ";" || word == "}") { return(false); } throw new System.ApplicationException("Fatal: ここに制御は来る筈ない。ContextWordReader の実装が怪しい"); } // argument があればそれを読み取り。 wreader.LetterReader.CopyPosition(0, contextcmd); // 後でエラーが発生した時等の為。 wreader.LetterReader.CopyPosition(0, 1); // * wreader.LetterReader.StoreCurrentPos(2); // * if (wreader.ReadNext()) { if (wreader.CurrentType == WordType.Suffix) { contextcmd.argument = wreader.CurrentWord; wreader.LetterReader.StoreCurrentPos(2); // * wreader.ReadNext(); // 二重引数を跳ばし読み if (wreader.CurrentType == WordType.Suffix) { wreader.LetterReader.SetError("二重に引数を指定する事は出来ません。", 0, null); } while (wreader.CurrentType == WordType.Suffix) { wreader.ReadNext(); } } } // command が処理可能な物かどうかを確認。 if (!cc.cmdreg.ContainsKey(word)) { cc.wreader.LetterReader.SetError(word + " という種類の命令は定義されていません", 1, 2); // * goto start; // 読み直し } contextcmd.command = word; return(true); }
/// <summary> /// 空行を除去し、無駄なインデントを除きます。 /// </summary> /// <param name="source">空行などを含んでいる可能性のあるソースを指定します。</param> /// <returns>整形した後の文字列を返します。</returns> public static string FormatSource(string source) { string[] strs = source.Split(new char[] { '\r', '\n' }); int[] lens = new int[strs.Length]; int i, j; int minlen = 0x100; for (i = 0, j = 0; i < strs.Length; i++) { if (strs[i].Trim().Length == 0) { continue; } string str = strs[i]; // インデントの長さ int len = 0; while (str.Length > 0) { if (str[0] == '\t') { len += 4; } else if (str[0] == ' ') { len += 1; } else { break; } str = str.Substring(1); } // 最小インデント if (len < minlen) { minlen = len; } // 空行を跳ばして格納 lens[j] = len; strs[j++] = str; } System.Text.StringBuilder build = new System.Text.StringBuilder(); for (i = 0; i < j; i++) { int indent = lens[i] - minlen; build.Append(indent % 4 == 0?new string('\t', indent / 4):new string(' ', indent)); build.AppendLine(strs[i]); } return(ContextCommand.ResolveReferenceWord(build.ToString())); }
public StringCommand(string content, bool requirelast) { this.islast = requirelast; this.content = ContextCommand.ResolveReferenceWord(content); this.hasargument = content.IndexOf("$$") >= 0; }