static List <TextElement> ParseCommand(string text) { var elems = new List <TextElement>(); var element = new TextElement { Speed = 1 }; var state = ParseState.PlainText; var cmdName = new StringBuilder(); var cmdArgs = new StringBuilder(); for (int i = 0; i < text.Length; i++) { var c = text[i]; var nc = i < text.Length - 1 ? text[i + 1] : default(char); switch (state) { case ParseState.PlainText: // コマンドはじまりか? if (c == '$') { // エスケープか? if (nc == '$') { // そのまま出力して1個飛ばす i++; } else { // コマンドをはじめる state = ParseState.Name; cmdName.Clear(); cmdArgs.Clear(); continue; } } element.Text = c.ToString(); elems.Add(element); element.Nod = false; element.WaitTime = 0; break; case ParseState.Name: if (c == '=') { // 引数開始 state = ParseState.Argument; continue; } if (c == ';') { // コマンド終了 state = ParseState.PlainText; DoCommand(ref elems, ref element, cmdName.ToString(), cmdArgs.ToString()); continue; } cmdName.Append(c); break; case ParseState.Argument: if (c == ';') { // コマンド終了 state = ParseState.PlainText; DoCommand(ref elems, ref element, cmdName.ToString(), cmdArgs.ToString()); continue; } cmdArgs.Append(c); break; default: throw new InvalidOperationException("Invalid parse state"); } } return(elems); }
static void DoCommand(ref List <TextElement> list, ref TextElement elem, string name, string args) { switch (name.ToLower()) { case "b": case "bold": elem.Bold = true; break; case "i": case "italic": elem.Italic = true; break; case "c": case "col": case "color": elem.Color = args; break; case "v": case "voice": elem.Voice = args; break; case "!b": case "!bold": elem.Bold = false; break; case "!i": case "!italic": elem.Italic = false; break; case "!c": case "!col": case "!color": elem.Color = null; break; case "!sz": case "!size": elem.Size = 0; break; case "!spd": case "!speed": elem.Speed = 1; break; case "sz": case "size": int size; if (!int.TryParse(args.Trim(), out size)) { throw new FormatException("サイズには整数値のみ指定できます"); } elem.Size = size; break; case "r": case "rest": elem.Bold = false; elem.Italic = false; elem.Color = null; elem.Nod = false; elem.Speed = 1; elem.WaitTime = 0; elem.Size = 0; elem.Voice = null; break; case "w": case "wait": float wait; if (!float.TryParse(args.Trim(), out wait)) { throw new FormatException("待機時間には実数値のみ指定できます"); } elem.WaitTime = wait; break; case "nod": elem.Nod = true; break; case "spd": case "speed": float spd; if (!float.TryParse(args.Trim(), out spd)) { throw new FormatException("文字送り速度には実数値のみ指定できます"); } elem.Speed = spd; break; case "var": case "variable": foreach (var c in GetVariable(args)) { elem.Text = c.ToString(); list.Add(elem); elem.Nod = false; elem.WaitTime = 0; } break; default: var raw = new StringBuilder().Append('$').Append(name); if (!string.IsNullOrEmpty(args)) { raw.Append('=').Append(args); } raw.Append(';'); foreach (var c in raw.ToString()) { elem.Text = c.ToString(); list.Add(elem); elem.Nod = false; elem.WaitTime = 0; } break; } }