private YSection ParseInternal(IReadOnlyList <Token> tokens) { // 戻り値用変数の準備 var result = new YSection(); for (int i = 0; i < tokens.Count;) { switch (tokens[i].Type) { case TokenType.Name: // 名前なら // 名前を保持 string name = tokens[i].SourceText; // カウンタを進める ++i; // 等号じゃなかったらエラー if (tokens[i].Type != TokenType.Equal) { throw new InvalidSyntaxException(tokens[i]); } // カウンタを進める ++i; // 型指定子を使って型を特定する YNode node; switch (tokens[i].Type) { case TokenType.NullOrEmpty: // 空値なら // カウンタを進める ++i; // インスタンスの生成 node = new YNullOrEmpty(); break; case TokenType.CommentChar: // コメントなら // カウンタを進める ++i; // インスタンスの生成 var com = new YComment(); com.HasName = true; // 名前あり // コメント文字列があるなら if (tokens[i].Type == TokenType.CommentText) { com.SetValue(tokens[i].SourceText); ++i; } node = com; break; case TokenType.SectionStart: // セクションなら // カウンタを進める ++i; // 新しいリストにセクションの終わりまでの字句を追加する var list = new List <Token>(); int j = 1; while (j > 0) { if (tokens[i].Type == TokenType.SectionStart) { ++j; } if (tokens[i].Type == TokenType.SectionEnd) { --j; } // リストに追加する list.Add(tokens[i]); // カウンタを進める ++i; } // 終端の SectionEnd を削除 list.RemoveAt(list.Count - 1); // 右の処理は必要ない? //// カウンタを進める //++i; // インスタンスの生成 node = this.ParseInternal(list); break; case TokenType.String: // 文字列なら // インスタンスの生成 var str = new YString(); str.SetEscapedText(tokens[i].SourceText); // カウンタを進める ++i; node = str; break; case TokenType.Number: // 数値なら // インスタンスの生成 var num = new YNumber(); num.UInt64Value = ulong.Parse(tokens[i].SourceText); // カウンタを進める ++i; node = num; break; case TokenType.Boolean: // 論理値なら // インスタンスの生成 var flg = new YBoolean(); flg.Flag = tokens[i].SourceText == "T"; // カウンタを進める ++i; node = flg; break; default: // それ以外、例外を発生させる throw new InvalidSyntaxException(tokens[i]); } node.Name = name; result.Add(node); break; case TokenType.CommentChar: // コメントなら // カウンタを進める ++i; // インスタンスの生成 var obj = new YComment(); // プロパティの設定 obj.Name = Guid.NewGuid().ToString().Replace("{", "").Replace("}", "").Replace("-", "_"); obj.HasName = false; // もしコメント文字列があるなら設定 if (tokens[i].Type == TokenType.CommentText) { obj.SetValue(tokens[i].SourceText); ++i; } // 結果に追加 result.Add(obj); break; default: // それ以外、例外を発生させる throw new InvalidSyntaxException(tokens[i]); } } // 結果を返す return(result); }
private YSection ReadSection(BinaryReader br) { var result = new YSection(); // キーの数を取得 uint kc = br.ReadUInt32(); // キーの数だけ繰り返す for (uint i = 0; i < kc; ++i) { // 名前の文字列長を取得 ulong nmsz; switch (Header.KeyNameSize) { // 8ビット case KeyNameSize.HWord: nmsz = br.ReadByte(); break; // 16ビット case KeyNameSize.Word: nmsz = br.ReadUInt16(); break; // 32ビット case KeyNameSize.DWord: nmsz = br.ReadUInt32(); break; #if false // 64ビット case KeyNameSize.QWord: nmsz = br.ReadUInt64(); break; #endif default: // ここには来ない筈 nmsz = 0; break; } // 文字列値分のバイト配列を取得 byte[] bName = br.ReadBytes(unchecked ((int)(nmsz))); // バイト配列をデコードして名前に変換 string name = Header.GetEncoding().GetString(bName); // 型識別子の取得 byte t = br.ReadByte(); // 値の取得 YNode node; switch (t) { // セクション case 0x01: node = ReadSection(br); break; // 文字列 case 0x02: var str = new YString(); int sz = br.ReadInt32(); byte[] bStr = br.ReadBytes(sz); string val = Encoding.Unicode.GetString(bStr); str.SetEscapedText(val); node = str; break; // 整数値 case 0x03: node = new YNumber() { UInt64Value = br.ReadUInt64() }; break; // 真理値 case 0x04: node = new YBoolean() { Flag = true }; break; // 偽理値 case 0x05: node = new YBoolean() { Flag = false }; break; // NULL値 | 空値 default: // case 0x00: node = new YNullOrEmpty(); break; } // 名前を設定して現在のセクションに追加 node.Name = name; result.Add(node); } // 作成したセクションを呼び出し元に返す return(result); }