PageRenderTime 85ms CodeModel.GetById 11ms app.highlight 54ms RepoModel.GetById 0ms app.codeStats 1ms

/JsonVisualizer/Internal/IncludeMicroParser.Json.cs

#
C# | 3485 lines | 2662 code | 521 blank | 302 comment | 174 complexity | 8d37ca31b129a7bc9d59f00c4aac4129 MD5 | raw file
   1
   2#define MICRO_PARSER_NET35
   3#define MICRO_PARSER_JSON_NET35
   4
   5
   6
   7// ----------------------------------------------------------------------------
   8// Included defines (C# requires #define to in the first part of a code file)
   9// ----------------------------------------------------------------------------
  10#define MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
  11#define MICRO_PARSER_SUPPRESS_CHAR_PARSER_MANY_CHAR_SATISFY_2
  12#define MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_NEW_LINE
  13#define MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_NONE_OF
  14#define MICRO_PARSER_SUPPRESS_CHAR_SATISFY_COMPOSITES
  15#define MICRO_PARSER_SUPPRESS_EXTENSIONS_EXCEPT
  16#define MICRO_PARSER_SUPPRESS_EXTENSIONS_OR
  17#define MICRO_PARSER_SUPPRESS_PARSER_CHAIN
  18#define MICRO_PARSER_SUPPRESS_PARSER_COMBINE
  19#define MICRO_PARSER_SUPPRESS_PARSER_EXCEPT
  20#define MICRO_PARSER_SUPPRESS_PARSER_FAIL
  21#define MICRO_PARSER_SUPPRESS_PARSER_FAIL_WITH_EXPECTED
  22// ----------------------------------------------------------------------------
  23
  24// ----------------------------------------------------------------------------
  25// Included code
  26// ----------------------------------------------------------------------------
  27
  28
  29// #define MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
  30
  31// #define MICRO_PARSER_SUPPRESS_PARSER_CHAIN
  32// #define MICRO_PARSER_SUPPRESS_PARSER_COMBINE
  33// #define MICRO_PARSER_SUPPRESS_PARSER_EXCEPT
  34// #define MICRO_PARSER_SUPPRESS_PARSER_FAIL
  35// #define MICRO_PARSER_SUPPRESS_PARSER_FAIL_WITH_EXPECTED
  36
  37// #define MICRO_PARSER_SUPPRESS_CHAR_PARSER_MANY_CHAR_SATISFY_2
  38// #define MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_NEW_LINE
  39// #define MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_NONE_OF
  40
  41// #define MICRO_PARSER_SUPPRESS_CHAR_SATISFY_COMPOSITES
  42
  43// #define MICRO_PARSER_SUPPRESS_EXTENSIONS_EXCEPT
  44// #define MICRO_PARSER_SUPPRESS_EXTENSIONS_OR
  45
  46
  47
  48
  49// ----------------------------------------------------------------------------
  50// Included code
  51// ----------------------------------------------------------------------------
  52
  53namespace Include
  54{
  55// ----------------------------------------------------------------------------------------------
  56// Copyright (c) Mårten Rånge.
  57// ----------------------------------------------------------------------------------------------
  58// This source code is subject to terms and conditions of the Microsoft Public License. A 
  59// copy of the license can be found in the License.html file at the root of this distribution. 
  60// If you cannot locate the  Microsoft Public License, please send an email to 
  61// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  62//  by the terms of the Microsoft Public License.
  63// ----------------------------------------------------------------------------------------------
  64// You must not remove this notice, or any other, from this software.
  65// ----------------------------------------------------------------------------------------------
  66namespace MicroParser
  67{
  68   using System;
  69   using System.Linq;
  70   using Internal;
  71
  72   static partial class CharParser
  73   {
  74#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_CHAR
  75      public static Parser<Empty> SkipChar (char toSkip)
  76      {
  77         return SkipString (new string (toSkip, 1));
  78      }
  79#endif
  80
  81#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_STRING
  82      public static Parser<Empty> SkipString (string toSkip)
  83      {
  84         if (toSkip.IsNullOrEmpty ())
  85         {
  86            throw new ArgumentNullException ("toSkip");
  87         }
  88
  89         CharSatisfy.Function satisfy = (c, i) => c == toSkip[i];
  90         var parserErrorMessage = new ParserErrorMessage_Expected (Strings.CharSatisfy.FormatChar_1.FormatWith (toSkip));
  91
  92         return SkipSatisfy (
  93            new CharSatisfy (parserErrorMessage, satisfy),
  94            toSkip.Length,
  95            toSkip.Length);
  96      }
  97#endif
  98
  99#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_ANY_OF
 100      public static Parser<Empty> SkipAnyOf (string skipAnyOfThese)
 101      {
 102         var sat = CharSatisfy.CreateSatisfyForAnyOf (skipAnyOfThese);
 103         return SkipSatisfy (
 104            sat,
 105            maxCount:1
 106            );
 107      }
 108#endif
 109
 110#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_NONE_OF
 111      public static Parser<Empty> SkipNoneOf (string skipNoneOfThese)
 112      {
 113         var sat = CharSatisfy.CreateSatisfyForNoneOf (skipNoneOfThese);
 114         return SkipSatisfy (
 115            sat,
 116            maxCount: 1
 117            );
 118      }
 119#endif
 120
 121#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_SATISFY
 122      public static Parser<Empty> SkipSatisfy (
 123         CharSatisfy charSatisfy,
 124         int minCount = 0,
 125         int maxCount = int.MaxValue
 126         )
 127      {
 128         Parser.VerifyMinAndMaxCount (minCount, maxCount);
 129
 130         Parser<Empty>.Function function = state =>
 131         {
 132            var advanceResult = state.SkipAdvance (charSatisfy.Satisfy, minCount, maxCount);
 133            return ParserReply.Create (advanceResult, state, charSatisfy.ErrorMessage, Empty.Value);
 134         };
 135         return function;
 136      }
 137#endif
 138
 139#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_WHITE_SPACE
 140      public static Parser<Empty> SkipWhiteSpace (
 141         int minCount = 0,
 142         int maxCount = int.MaxValue
 143         )
 144      {
 145         return SkipSatisfy (CharSatisfy.WhiteSpace, minCount, maxCount);
 146      }
 147#endif
 148
 149#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_SKIP_NEW_LINE
 150      public static Parser<Empty> SkipNewLine (
 151         )
 152      {
 153         return SkipChar ('\r').Opt ()
 154            .KeepRight (SkipChar ('\n'));
 155      }
 156#endif
 157
 158#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_ANY_OF
 159      public static Parser<SubString> AnyOf (
 160         string match,
 161         int minCount = 0,
 162         int maxCount = int.MaxValue
 163         )
 164      {
 165         var satisfy = CharSatisfy.CreateSatisfyForAnyOf (match);
 166
 167         return ManyCharSatisfy (satisfy, minCount, maxCount);
 168      }
 169#endif
 170
 171#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_NONE_OF
 172      public static Parser<SubString> NoneOf (
 173         string match,
 174         int minCount = 0,
 175         int maxCount = int.MaxValue
 176         )
 177      {
 178         var satisfy = CharSatisfy.CreateSatisfyForNoneOf (match);
 179
 180         return ManyCharSatisfy (satisfy, minCount, maxCount);
 181      }
 182#endif
 183
 184#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_MANY_CHAR_SATISFY
 185      public static Parser<SubString> ManyCharSatisfy (
 186         CharSatisfy satisfy,
 187         int minCount = 0,
 188         int maxCount = int.MaxValue
 189         )
 190      {
 191         Parser.VerifyMinAndMaxCount (minCount, maxCount);
 192
 193         Parser<SubString>.Function function = state =>
 194         {
 195            var subString = new SubString ();
 196            var advanceResult = state.Advance (ref subString, satisfy.Satisfy, minCount, maxCount);
 197
 198            return ParserReply.Create (
 199               advanceResult,
 200               state,
 201               satisfy.ErrorMessage,
 202               subString
 203               );
 204         };
 205         return function;
 206      }
 207#endif
 208
 209#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_MANY_CHAR_SATISFY_2
 210      public static Parser<SubString> ManyCharSatisfy2 (
 211         CharSatisfy satisfyFirst,
 212         CharSatisfy satisfyRest,
 213         int minCount = 0,
 214         int maxCount = int.MaxValue
 215         )
 216      {
 217         Parser.VerifyMinAndMaxCount (minCount, maxCount);
 218
 219         var first = satisfyFirst.Satisfy;
 220         var rest = satisfyRest.Satisfy;
 221
 222         CharSatisfy.Function satisfy = (c, i) => i == 0 ? first (c, i) : rest (c, i);
 223
 224         Parser<SubString>.Function function = state =>
 225         {
 226            var subString = new SubString ();
 227
 228            var advanceResult = state.Advance (ref subString, satisfy, minCount, maxCount);
 229
 230            var expected =
 231               (advanceResult == ParserState.AdvanceResult.Error_EndOfStream_PostionChanged || advanceResult == ParserState.AdvanceResult.Error_SatisfyFailed_PositionChanged)
 232               ? satisfyRest.ErrorMessage
 233               : satisfyFirst.ErrorMessage;
 234
 235            return ParserReply.Create (
 236               advanceResult,
 237               state,
 238               expected,
 239               subString
 240               );
 241         };
 242         return function;
 243      }
 244#endif
 245
 246      partial struct UIntResult
 247      {
 248         public uint Value;
 249         public int ConsumedCharacters;
 250      }
 251
 252      static Parser<UIntResult> UIntImpl (
 253         int minCount = 1,
 254         int maxCount = 10
 255         )
 256      {
 257         Parser.VerifyMinAndMaxCount (minCount, maxCount);
 258
 259         CharSatisfy.Function satisfy = (c, i) => char.IsDigit (c);
 260
 261         Parser<UIntResult>.Function function = state =>
 262         {
 263            var subString = new SubString ();
 264
 265            var oldPos = state.Position;
 266
 267            var advanceResult = state.Advance (ref subString, satisfy, minCount, maxCount);
 268
 269            var newPos = state.Position;
 270
 271            return ParserReply.Create (
 272               advanceResult,
 273               state,
 274               ParserErrorMessages.Expected_Digit,
 275               () =>
 276                  {
 277                     var accumulated = 0u;
 278                     var length = subString.Length;
 279                     const uint c0 = (uint) '0';
 280                     for (var iter = 0; iter < length; ++iter)
 281                     {
 282                        var c = subString[iter];
 283                        accumulated = accumulated*10 + (c - c0);
 284                     }
 285
 286                     return new UIntResult
 287                               {
 288                                  Value = accumulated,
 289                                  ConsumedCharacters = newPos.Position - oldPos.Position,
 290                               };
 291                  }
 292               );
 293         };
 294         return function;
 295      }
 296
 297#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_HEX
 298      static uint? CharToHex (char ch)
 299      {
 300         if ('0' <= ch && ch <= '9')
 301         {
 302            return (uint?) (ch - '0');
 303         }
 304         else if ('A' <= ch && ch <= 'F')
 305         {
 306            return (uint?) (ch - 'A' + 0xA);
 307         }
 308         else if ('a' <= ch && ch <= 'f')
 309         {
 310            return (uint?)(ch - 'a' + 0xA);            
 311         }
 312         else
 313         {
 314            return null;
 315         }
 316      }
 317
 318      [CLSCompliant (false)]
 319      public static Parser<uint> Hex (
 320         int minCount = 1,
 321         int maxCount = 10
 322         )
 323      {
 324         Parser.VerifyMinAndMaxCount (minCount, maxCount);
 325
 326         CharSatisfy.Function satisfy = (c, i) => CharToHex (c) != null;
 327
 328         Parser<uint>.Function function = state =>
 329         {
 330            var subString = new SubString ();
 331
 332            var advanceResult = state.Advance (ref subString, satisfy, minCount, maxCount);
 333
 334            return ParserReply.Create (
 335               advanceResult,
 336               state,
 337               ParserErrorMessages.Expected_HexDigit,
 338               () =>
 339               {
 340                  var accumulated = 0u;
 341                  var length = subString.Length;
 342                  for (var iter = 0; iter < length; ++iter)
 343                  {
 344                     var c = subString[iter];
 345                     accumulated = accumulated * 0x10U + CharToHex (c).Value;
 346                  }
 347
 348                  return accumulated;
 349               }
 350               );
 351         };
 352         return function;
 353      }
 354#endif
 355
 356#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_UINT
 357      [CLSCompliant (false)]
 358      public static Parser<uint> UInt (
 359         int minCount = 1,
 360         int maxCount = 10
 361         )
 362      {
 363         var uintParser = UIntImpl (minCount, maxCount);
 364
 365         Parser<uint>.Function function = state =>
 366         {
 367            var uintResult = uintParser.Execute (state);
 368
 369            if (uintResult.State.HasError ())
 370            {
 371               return uintResult.Failure<uint> ();
 372            }
 373
 374            return uintResult.Success (uintResult.Value.Value);
 375         };
 376         return function;
 377      }
 378#endif
 379
 380#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_INT
 381      public static Parser<int> Int (
 382         )
 383      {
 384         var intParser = Parser.Group (
 385            SkipChar ('-').Opt (),
 386            UInt ()
 387            );
 388
 389         Parser<int>.Function function = state =>
 390         {
 391            var intResult = intParser.Execute (state);
 392
 393            if (intResult.State.HasError ())
 394            {
 395               return intResult.Failure<int> ();
 396            }
 397
 398            var intValue = (int)intResult.Value.Item2;
 399
 400            return intResult.Success (intResult.Value.Item1.HasValue ? -intValue : intValue);
 401         };
 402         return function;
 403      }
 404#endif
 405
 406#if !MICRO_PARSER_SUPPRESS_CHAR_PARSER_DOUBLE
 407      public static Parser<double> Double ()
 408      {
 409         var intParser = Int ();
 410         var fracParser = SkipChar ('.').KeepRight (UIntImpl ());
 411         var expParser = SkipAnyOf ("eE").KeepRight (Parser.Group (AnyOf ("+-", maxCount:1), UInt ()));
 412
 413         var doubleParser = Parser.Group (
 414            intParser,
 415            fracParser.Opt (),
 416            expParser.Opt ()
 417            );
 418
 419         Parser<double>.Function function = state =>
 420         {
 421            var doubleResult = doubleParser.Execute (state);
 422
 423            if (doubleResult.State.HasError ())
 424            {
 425               return doubleResult.Failure<double> ();
 426            }
 427
 428            var value = doubleResult.Value;
 429
 430            var intValue = value.Item1;
 431
 432            double doubleValue;
 433
 434            if (value.Item2.HasValue)
 435            {
 436               var uIntResult = value.Item2.Value;
 437
 438               var multiplier = intValue >= 0 ? 1 : -1;
 439
 440               doubleValue = intValue + multiplier * uIntResult.Value * (Math.Pow (0.1, uIntResult.ConsumedCharacters));
 441            }
 442            else
 443            {
 444               doubleValue = intValue;
 445            }
 446
 447            if (value.Item3.HasValue)
 448            {
 449               var modifier = value.Item3.Value.Item1;
 450
 451               var multiplier = 
 452                  modifier[0] == '-'
 453                  ?  -1.0
 454                  :  1.0
 455                  ;
 456
 457               doubleValue *= Math.Pow (10.0, multiplier*value.Item3.Value.Item2);
 458            }
 459
 460            return doubleResult.Success (doubleValue);
 461         };
 462         return function;
 463      }
 464#endif
 465   }
 466}
 467}
 468namespace Include
 469{
 470// ----------------------------------------------------------------------------------------------
 471// Copyright (c) Mårten Rånge.
 472// ----------------------------------------------------------------------------------------------
 473// This source code is subject to terms and conditions of the Microsoft Public License. A 
 474// copy of the license can be found in the License.html file at the root of this distribution. 
 475// If you cannot locate the  Microsoft Public License, please send an email to 
 476// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 477//  by the terms of the Microsoft Public License.
 478// ----------------------------------------------------------------------------------------------
 479// You must not remove this notice, or any other, from this software.
 480// ----------------------------------------------------------------------------------------------
 481namespace MicroParser
 482{
 483   using System;
 484   using System.Collections.Generic;
 485   using System.Linq;
 486   using System.Linq.Expressions;
 487   using Internal;
 488
 489   sealed partial class CharSatisfy
 490   {
 491      public delegate bool Function (char ch, int index);
 492
 493      public readonly IParserErrorMessage ErrorMessage;
 494      public readonly Function Satisfy;
 495
 496      public static implicit operator CharSatisfy (char ch)
 497      {
 498         return new CharSatisfy (
 499            new ParserErrorMessage_Expected (Strings.CharSatisfy.FormatChar_1.FormatWith (ch)), 
 500            (c, i) => ch == c
 501            );
 502      }
 503
 504      public CharSatisfy (IParserErrorMessage errorMessage, Function satisfy)
 505      {
 506         ErrorMessage = errorMessage;
 507         Satisfy = satisfy;
 508      }
 509
 510#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
 511      public override string ToString ()
 512      {
 513         return new
 514                   {
 515                      ErrorMessage,
 516                   }.ToString ();
 517      }
 518#endif
 519
 520      class SatisfyFunctions
 521      {
 522         // ReSharper disable MemberHidesStaticFromOuterClass
 523         // ReSharper disable MemberCanBeMadeStatic.Local
 524
 525         // These methods should be kept non static as that reduces delegate overhead
 526
 527         public bool AnyChar (char ch, int index)
 528         {
 529            return true;
 530         }
 531
 532         public bool WhiteSpace (char ch, int index)
 533         {
 534            return char.IsWhiteSpace (ch);
 535         }
 536
 537         public bool Digit (char ch, int index)
 538         {
 539            return char.IsDigit (ch);
 540         }
 541
 542         public bool Letter (char ch, int index)
 543         {
 544            return char.IsLetter (ch);
 545         }
 546         // ReSharper restore MemberCanBeMadeStatic.Local
 547         // ReSharper restore MemberHidesStaticFromOuterClass
 548      }
 549
 550      static readonly SatisfyFunctions s_satisfyFunctions   = new SatisfyFunctions ();
 551
 552      public static readonly CharSatisfy AnyChar      = new CharSatisfy (ParserErrorMessages.Expected_Any         , s_satisfyFunctions.AnyChar     );
 553      public static readonly CharSatisfy WhiteSpace   = new CharSatisfy (ParserErrorMessages.Expected_WhiteSpace  , s_satisfyFunctions.WhiteSpace  );
 554      public static readonly CharSatisfy Digit        = new CharSatisfy (ParserErrorMessages.Expected_Digit       , s_satisfyFunctions.Digit       );
 555      public static readonly CharSatisfy Letter       = new CharSatisfy (ParserErrorMessages.Expected_Letter      , s_satisfyFunctions.Letter      );
 556
 557      public static readonly CharSatisfy LineBreak    = new CharSatisfy (ParserErrorMessages.Expected_LineBreak   , CreateSatisfyFunctionForAnyOfOrNoneOf ("\r\n", true));
 558
 559#if !MICRO_PARSER_SUPPRESS_CHAR_SATISFY_COMPOSITES
 560      public static readonly CharSatisfy LineBreakOrWhiteSpace  = LineBreak.Or (WhiteSpace);
 561      public static readonly CharSatisfy LetterOrDigit          = Letter.Or (Digit);
 562#endif
 563
 564#if MICRO_PARSER_NET35
 565      static Function CreateSatisfyFunctionForAnyOfOrNoneOf (
 566         string match,
 567         bool matchResult
 568         )
 569      {
 570         if (!match.Any (ch => ch > 255))
 571         {
 572            var boolMap = Enumerable.Repeat (!matchResult, 256).ToArray ();
 573            foreach (var c in match)
 574            {
 575               boolMap[c] = matchResult;
 576            }
 577
 578            return (c, i) => ((c & 0xFF00) == 0) && boolMap[c & 0xFF];
 579         }
 580
 581#if WINDOWS_PHONE
 582         // Windows Phone is basically .NET35 but lacks the HashSet class.
 583         // Approximate with Dictionary<>
 584         var dictionary = match.ToDictionary (v => v, v => true);
 585         return (c, i) => dictionary.ContainsKey (c) ? matchResult : !matchResult;
 586#else
 587         var hashSet = new HashSet<char> (match);
 588         return (c, i) => hashSet.Contains (c) ? matchResult : !matchResult;
 589#endif
 590      }
 591#else
 592      static Function CreateSatisfyFunctionForAnyOfOrNoneOf (
 593         string match,
 594         bool matchResult
 595         )
 596      {
 597         // For input string "Test" this generates the equivalent code to
 598         // Func<char, int> d = (ch, index) => 
 599         // {
 600         //    bool result;
 601         //    switch (ch)
 602         //    {
 603         //       case 'T':
 604         //       case 'e':
 605         //       case 's':
 606         //       case 't':
 607         //          result = matchResult;
 608         //          break;
 609         //       default:
 610         //          result = !matchResult;
 611         //          break;
 612         //    }
 613         //    return result;
 614         // }
 615
 616         var parameter0 = Expression.Parameter (typeof (char), "ch");
 617         var parameter1 = Expression.Parameter (typeof (int), "index");
 618
 619         var resultVariable = Expression.Variable (typeof (bool), "result");
 620
 621         var switchStatement = Expression.Switch (
 622            parameter0,
 623            Expression.Assign (resultVariable, Expression.Constant (!matchResult)),
 624            Expression.SwitchCase (
 625               Expression.Assign (resultVariable, Expression.Constant (matchResult)),
 626               match.Select (ch => Expression.Constant (ch)).ToArray ()
 627               ));
 628
 629         var body = Expression.Block (
 630            new[] { resultVariable },
 631            switchStatement,
 632            resultVariable
 633            );
 634
 635         var lambda = Expression.Lambda<Function>(
 636            body,
 637            parameter0,
 638            parameter1
 639            );
 640
 641         return lambda.Compile ();
 642      }
 643#endif
 644
 645      static CharSatisfy CreateSatisfyForAnyOfOrNoneOf (
 646         string match,
 647         Func<char, IParserErrorMessage> action,
 648         bool matchResult
 649         )
 650      {
 651         if (match.IsNullOrEmpty ())
 652         {
 653            throw new ArgumentNullException ("match");
 654         }
 655
 656         var errorMessages = match
 657            .Select (action)
 658            .ToArray ()
 659            ;
 660
 661         return new CharSatisfy (
 662            new ParserErrorMessage_Group (errorMessages),
 663            CreateSatisfyFunctionForAnyOfOrNoneOf (match, matchResult)
 664            );
 665      }
 666
 667      public static CharSatisfy CreateSatisfyForAnyOf (string match)
 668      {
 669         return CreateSatisfyForAnyOfOrNoneOf (
 670            match,
 671            x => new ParserErrorMessage_Expected (Strings.CharSatisfy.FormatChar_1.FormatWith (x)),
 672            true
 673            );
 674      }
 675
 676      public static CharSatisfy CreateSatisfyForNoneOf (string match)
 677      {
 678         return CreateSatisfyForAnyOfOrNoneOf (
 679            match,
 680            x => new ParserErrorMessage_Unexpected (Strings.CharSatisfy.FormatChar_1.FormatWith (x)),
 681            false
 682            );
 683      }
 684   }
 685}
 686}
 687namespace Include
 688{
 689// ----------------------------------------------------------------------------------------------
 690// Copyright (c) Mårten Rånge.
 691// ----------------------------------------------------------------------------------------------
 692// This source code is subject to terms and conditions of the Microsoft Public License. A 
 693// copy of the license can be found in the License.html file at the root of this distribution. 
 694// If you cannot locate the  Microsoft Public License, please send an email to 
 695// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 696//  by the terms of the Microsoft Public License.
 697// ----------------------------------------------------------------------------------------------
 698// You must not remove this notice, or any other, from this software.
 699// ----------------------------------------------------------------------------------------------
 700namespace MicroParser
 701{
 702   partial struct Empty
 703   {
 704      public static Empty Value;
 705
 706      public override string  ToString ()
 707      {
 708         return Strings.Empty;
 709      }
 710   }
 711
 712}
 713}
 714namespace Include
 715{
 716// ----------------------------------------------------------------------------------------------
 717// Copyright (c) Mårten Rånge.
 718// ----------------------------------------------------------------------------------------------
 719// This source code is subject to terms and conditions of the Microsoft Public License. A 
 720// copy of the license can be found in the License.html file at the root of this distribution. 
 721// If you cannot locate the  Microsoft Public License, please send an email to 
 722// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 723//  by the terms of the Microsoft Public License.
 724// ----------------------------------------------------------------------------------------------
 725// You must not remove this notice, or any other, from this software.
 726// ----------------------------------------------------------------------------------------------
 727namespace MicroParser
 728{
 729   using System.Collections.Generic;
 730   using System.Linq;
 731
 732   static partial class Extensions
 733   {
 734      // ParserReply.State
 735
 736      public static bool IsSuccessful (this ParserReply.State state)
 737      {
 738         return state == ParserReply.State.Successful;
 739      }
 740
 741      public static bool HasConsistentState (this ParserReply.State state)
 742      {
 743         return
 744            (state & ParserReply.State.FatalError_StateIsNotRestored)
 745               == 0;
 746      }
 747
 748      public static bool HasFatalError (this ParserReply.State state)
 749      {
 750         return state >= ParserReply.State.FatalError;
 751      }
 752
 753      public static bool HasError (this ParserReply.State state)
 754      {
 755         return state >= ParserReply.State.Error;
 756      }
 757
 758      public static bool HasNonFatalError (this ParserReply.State state)
 759      {
 760         return state >= ParserReply.State.Error && state < ParserReply.State.FatalError;
 761      }
 762
 763      // IParserErrorMessage
 764
 765      public static IEnumerable<IParserErrorMessage> DeepTraverse (this IParserErrorMessage value)
 766      {
 767         if (value == null)
 768         {
 769            yield break;
 770         }
 771
 772         var stack = new Stack<IParserErrorMessage> ();
 773         stack.Push (value);
 774
 775
 776         while (stack.Count > 0)
 777         {
 778            var pop = stack.Pop ();
 779
 780            var parserErrorMessageGroup = pop as ParserErrorMessage_Group;
 781
 782            if (parserErrorMessageGroup != null && parserErrorMessageGroup.Group != null)
 783            {
 784               foreach (var parserErrorMessage in parserErrorMessageGroup.Group)
 785               {
 786                  stack.Push (parserErrorMessage);
 787               }
 788            }
 789            else if (pop != null)
 790            {
 791               yield return pop;
 792            }
 793         }
 794
 795      }
 796
 797      public static IParserErrorMessage Append (this IParserErrorMessage left, IParserErrorMessage right)
 798      {
 799         return new ParserErrorMessage_Group (
 800            left.DeepTraverse ().Concat (right.DeepTraverse ()).ToArray ()
 801            );
 802      }
 803
 804      // CharSatisfy
 805
 806#if !MICRO_PARSER_SUPPRESS_EXTENSIONS_OR
 807      public static CharSatisfy Or (this CharSatisfy first, CharSatisfy second)
 808      {
 809         return new CharSatisfy (
 810            first.ErrorMessage.Append (second.ErrorMessage),
 811            (c, i) => first.Satisfy (c, i) || second.Satisfy (c, i)
 812            );
 813      }
 814#endif
 815
 816#if !MICRO_PARSER_SUPPRESS_EXTENSIONS_EXCEPT
 817      static IParserErrorMessage ExpectedToUnexpected (
 818         IParserErrorMessage parserErrorMessage
 819         )
 820      {
 821         var parserErrorMessageExpected = parserErrorMessage as ParserErrorMessage_Expected;
 822         return parserErrorMessageExpected != null
 823            ? new ParserErrorMessage_Unexpected (parserErrorMessageExpected.Expected)
 824            : parserErrorMessage
 825            ;
 826      }
 827
 828      public static CharSatisfy Except (this CharSatisfy first, CharSatisfy second)
 829      {
 830         return new CharSatisfy (
 831            first.ErrorMessage.Append (ExpectedToUnexpected (second.ErrorMessage)),
 832            (c, i) => first.Satisfy (c, i) && !second.Satisfy (c, i)
 833            );
 834      }
 835#endif
 836   }
 837}
 838}
 839namespace Include
 840{
 841// ----------------------------------------------------------------------------------------------
 842// Copyright (c) Mårten Rånge.
 843// ----------------------------------------------------------------------------------------------
 844// This source code is subject to terms and conditions of the Microsoft Public License. A 
 845// copy of the license can be found in the License.html file at the root of this distribution. 
 846// If you cannot locate the  Microsoft Public License, please send an email to 
 847// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 848//  by the terms of the Microsoft Public License.
 849// ----------------------------------------------------------------------------------------------
 850// You must not remove this notice, or any other, from this software.
 851// ----------------------------------------------------------------------------------------------
 852namespace MicroParser.Internal
 853{
 854   using System;
 855   using System.Collections.Generic;
 856   using System.Globalization;
 857   using System.Text;
 858
 859   static partial class Extensions
 860   {
 861
 862      // System.String
 863
 864      public static string FormatWith (this string format, params object[] args)
 865      {
 866         return string.Format (CultureInfo.InvariantCulture, format, args);
 867      }
 868
 869      public static bool IsNullOrEmpty (this string str)
 870      {
 871         return string.IsNullOrEmpty (str);
 872      }
 873
 874      // IEnumerable<string>
 875
 876      public static string Concatenate (
 877         this IEnumerable<string> strings,
 878         string delimiter = null,
 879         string prepend = null,
 880         string append = null
 881         )
 882      {
 883         var first = true;
 884
 885         var sb = new StringBuilder (prepend ?? String.Empty);
 886
 887         var del = delimiter ?? String.Empty;
 888
 889         foreach (var value in strings)
 890         {
 891            if (first)
 892            {
 893               first = false;
 894            }
 895            else
 896            {
 897               sb.Append (del);
 898            }
 899            sb.Append (value);
 900         }
 901
 902         sb.Append (append ?? String.Empty);
 903         return sb.ToString ();
 904      }
 905   }
 906}
 907}
 908namespace Include
 909{
 910// ----------------------------------------------------------------------------------------------
 911// Copyright (c) Mårten Rånge.
 912// ----------------------------------------------------------------------------------------------
 913// This source code is subject to terms and conditions of the Microsoft Public License. A 
 914// copy of the license can be found in the License.html file at the root of this distribution. 
 915// If you cannot locate the  Microsoft Public License, please send an email to 
 916// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 917//  by the terms of the Microsoft Public License.
 918// ----------------------------------------------------------------------------------------------
 919// You must not remove this notice, or any other, from this software.
 920// ----------------------------------------------------------------------------------------------
 921
 922namespace MicroParser
 923{
 924#if MICRO_PARSER_MAKE_PUBLIC
 925   public partial class CharParser
 926   {
 927
 928   }
 929
 930   public partial class CharSatisfy
 931   {
 932
 933   }
 934
 935   public partial interface IParserErrorMessage
 936   {
 937
 938   }
 939
 940   public partial struct Empty
 941   {
 942      
 943   }
 944
 945   public partial class Extensions
 946   {
 947      
 948   }
 949
 950   public partial class Optional
 951   {
 952
 953   }
 954
 955   public partial struct Optional<TValue>
 956   {
 957      
 958   }
 959
 960   public partial class Parser<TValue>
 961   {
 962
 963   }
 964
 965   public partial class Parser
 966   {
 967      
 968   }
 969
 970   public partial class ParserFunctionRedirect<TValue>
 971   {
 972
 973   }
 974
 975   public partial class ParserReply
 976   {
 977
 978   }
 979
 980   public partial struct ParserReply<TValue>
 981   {
 982
 983   }
 984
 985   public partial class BaseParserResult
 986   {
 987
 988   }
 989
 990   public partial class ParserResult<TValue>
 991   {
 992
 993   }
 994
 995   public partial class ParserState
 996   {
 997
 998   }
 999
1000   public partial struct ParserStatePosition
1001   {
1002
1003   }
1004
1005   public partial struct SubString
1006   {
1007
1008   }
1009
1010#if MICRO_PARSER_NET35
1011   public partial class Tuple
1012   {
1013
1014   }
1015
1016   public partial struct Tuple<TValue1, TValue2>
1017   {
1018
1019   }
1020
1021   public partial struct Tuple<TValue1, TValue2, TValue3>
1022   {
1023
1024   }
1025#endif
1026
1027#endif
1028}
1029}
1030namespace Include
1031{
1032// ----------------------------------------------------------------------------------------------
1033// Copyright (c) Mårten Rånge.
1034// ----------------------------------------------------------------------------------------------
1035// This source code is subject to terms and conditions of the Microsoft Public License. A 
1036// copy of the license can be found in the License.html file at the root of this distribution. 
1037// If you cannot locate the  Microsoft Public License, please send an email to 
1038// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
1039//  by the terms of the Microsoft Public License.
1040// ----------------------------------------------------------------------------------------------
1041// You must not remove this notice, or any other, from this software.
1042// ----------------------------------------------------------------------------------------------
1043namespace MicroParser
1044{
1045   static partial class Optional
1046   {
1047      public static Optional<TValue> Create<TValue> (TValue value)
1048      {
1049         return new Optional<TValue> (value);
1050      }
1051
1052      public static Optional<TValue> Create<TValue> ()
1053      {
1054         return new Optional<TValue> ();
1055      }
1056   }
1057
1058   partial struct Optional<TValue>
1059   {
1060      public readonly bool HasValue;
1061      public readonly TValue Value;
1062
1063      public Optional (TValue value)
1064      {
1065         HasValue = true;
1066         Value = value;
1067      }
1068
1069#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
1070      public override string ToString ()
1071      {
1072         return new
1073                   {
1074                      HasValue,
1075                      Value = HasValue ? Value : default (TValue),
1076                   }.ToString ();
1077      }
1078#endif
1079   }
1080}
1081}
1082namespace Include
1083{
1084// ----------------------------------------------------------------------------------------------
1085// Copyright (c) Mårten Rånge.
1086// ----------------------------------------------------------------------------------------------
1087// This source code is subject to terms and conditions of the Microsoft Public License. A 
1088// copy of the license can be found in the License.html file at the root of this distribution. 
1089// If you cannot locate the  Microsoft Public License, please send an email to 
1090// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
1091//  by the terms of the Microsoft Public License.
1092// ----------------------------------------------------------------------------------------------
1093// You must not remove this notice, or any other, from this software.
1094// ----------------------------------------------------------------------------------------------
1095
1096namespace MicroParser
1097{
1098   using System;
1099   using System.Collections.Generic;
1100   using System.Diagnostics;
1101   using System.Linq;
1102   using Internal;
1103
1104   sealed partial class Parser<TValue>
1105   {
1106      // ParserState is basically a string with a position
1107      // ParserReply contains the updated state and the result of the parser
1108      // operation depending on if the operation was successful
1109      public delegate ParserReply<TValue> Function (ParserState state);
1110
1111      public readonly Function Execute;
1112
1113      public Parser (Function function)
1114      {
1115         if (function == null)
1116         {
1117            throw new ArgumentNullException ("function");
1118         }
1119
1120         Execute = function;
1121      }
1122
1123      public static implicit operator Parser<TValue> (Function function)
1124      {
1125         return new Parser<TValue> (function);
1126      }
1127   }
1128
1129   static partial class Parser
1130   {
1131      public static ParserResult<TValue> Parse<TValue> (Parser<TValue> parserFunction, string text)
1132      {
1133         var parseResult = parserFunction.Execute (
1134            ParserState.Create (
1135               text ?? Strings.Empty,
1136               suppressParserErrorMessageOperations:true
1137               ));
1138
1139         if (!parseResult.State.IsSuccessful ())
1140         {
1141            var parseResultWithErrorInfo = parserFunction.Execute (
1142               ParserState.Create (
1143                  text ?? Strings.Empty
1144                  ));
1145
1146            var errorResult = parseResultWithErrorInfo
1147               .ParserErrorMessage
1148               .DeepTraverse ()
1149               .GroupBy (msg => msg.Description)
1150               .OrderBy (group => group.Key)
1151               .Select (group =>
1152                        Strings.Parser.ErrorMessage_2.FormatWith (
1153                           group.Key,
1154                           group.Select (message => message.Value.ToString ()).Distinct ().OrderBy (v => v).Concatenate (", ")
1155                           ))
1156               .Concatenate (", ");
1157
1158            var subString = new SubString ( 
1159                     text,
1160                     parseResultWithErrorInfo.ParserState.InternalPosition
1161                  );
1162
1163            var completeErrorResult =
1164               "Pos: {0} ('{1}') - {2}".FormatWith (
1165                  subString.Position,
1166                  subString[0],
1167                  errorResult
1168                  );
1169
1170            return new ParserResult<TValue> (
1171               false,
1172               subString,
1173               completeErrorResult,
1174               default (TValue)
1175               );
1176         }
1177
1178         return new ParserResult<TValue> (
1179            true,
1180            new SubString ( 
1181                  text,
1182                  parseResult.ParserState.InternalPosition
1183               ),
1184            Strings.Empty,
1185            parseResult.Value
1186            );
1187      }
1188
1189#if !MICRO_PARSER_SUPPRESS_PARSER_REDIRECT
1190      public static ParserFunctionRedirect<TValue> Redirect<TValue> ()
1191      {
1192         return new ParserFunctionRedirect<TValue> ();
1193      }
1194#endif
1195
1196#if !MICRO_PARSER_SUPPRESS_PARSER_RETURN
1197      public static Parser<TValue> Return<TValue> (TValue value)
1198      {
1199         Parser<TValue>.Function function = state => ParserReply<TValue>.Success (state, value);
1200         return function;
1201      }
1202#endif
1203
1204#if !MICRO_PARSER_SUPPRESS_PARSER_FAIL
1205      public static Parser<TValue> Fail<TValue>(string message)
1206      {
1207         var parserErrorMessageMessage = new ParserErrorMessage_Message (message);
1208         Parser<TValue>.Function function = state => ParserReply<TValue>.Failure (ParserReply.State.Error, state, parserErrorMessageMessage);
1209         return function;
1210      }
1211#endif
1212
1213#if !MICRO_PARSER_SUPPRESS_PARSER_FAIL_WITH_EXPECTED
1214      public static Parser<TValue> FailWithExpected<TValue>(this Parser<TValue> parser, string message)
1215      {
1216         var parserErrorMessageMessage = new ParserErrorMessage_Expected (message);
1217         Parser<TValue>.Function function = 
1218            state => 
1219               {
1220                  var reply = parser.Execute (state);
1221                  if (reply.State.HasError ())
1222                  {
1223                     return ParserReply<TValue>.Failure(
1224                        ParserReply.State.Error_Expected | reply.State & ParserReply.State.FatalError_Mask, 
1225                        state, 
1226                        parserErrorMessageMessage
1227                        );
1228                  }
1229                  return reply;
1230                  
1231               };
1232         return function;
1233      }
1234#endif
1235
1236#if !MICRO_PARSER_SUPPRESS_PARSER_DEBUG_BREAK
1237      public static Parser<TValue> DebugBreak<TValue> (this Parser<TValue> parser)
1238      {
1239         Parser<TValue>.Function function =
1240            state =>
1241               {
1242                  Debug.Assert (false);
1243                  return parser.Execute (state);
1244               };
1245         return function;
1246      }
1247#endif
1248
1249#if !MICRO_PARSER_SUPPRESS_PARSER_END_OF_STREAM
1250      public static Parser<Empty> EndOfStream ()
1251      {
1252         Parser<Empty>.Function function = state =>
1253                state.EndOfStream
1254                   ? ParserReply<Empty>.Success (state, Empty.Value)
1255                   : ParserReply<Empty>.Failure (
1256                      ParserReply.State.Error_Expected,
1257                      state,
1258                      ParserErrorMessages.Expected_EndOfStream
1259                      );
1260         return function;
1261      }
1262#endif
1263
1264#if !MICRO_PARSER_SUPPRESS_PARSER_COMBINE
1265      public static Parser<TValue2> Combine<TValue, TValue2>(this Parser<TValue> firstParser, Func<TValue, Parser<TValue2>> second)
1266      {
1267         Parser<TValue2>.Function function = state =>
1268                   {
1269                      var firstResult = firstParser.Execute (state);
1270                      if (firstResult.State.HasError ())
1271                      {
1272                         return firstResult.Failure<TValue2> ();
1273                      }
1274
1275                      var secondParser = second (firstResult.Value);
1276                      var secondResult = secondParser.Execute (state);
1277                      return secondResult;
1278                   };
1279         return function;
1280      }
1281#endif
1282
1283#if !MICRO_PARSER_SUPPRESS_PARSER_MAP
1284      public static Parser<TValue2> Map<TValue1, TValue2> (this Parser<TValue1> firstParser, Func<TValue1, TValue2> mapper)
1285      {
1286         Parser<TValue2>.Function function = state =>
1287         {
1288            var firstResult = firstParser.Execute (state);
1289
1290            if (firstResult.State.HasError ())
1291            {
1292               return firstResult.Failure<TValue2> ();
1293            }
1294
1295            return firstResult.Success (mapper (firstResult.Value));
1296         };
1297         return function;
1298      }
1299
1300      public static Parser<TValue2> Map<TValue1, TValue2> (this Parser<TValue1> firstParser, TValue2 value2)
1301      {
1302         return firstParser.Map (ignore => value2);
1303      }
1304#endif
1305
1306#if !MICRO_PARSER_SUPPRESS_PARSER_CHAIN
1307      public static Parser<TValue1> Chain<TValue1, TValue2>(
1308         this Parser<TValue1> parser,
1309         Parser<TValue2> separator,
1310         Func<TValue1, TValue2, TValue1, TValue1> combiner
1311         )
1312      {
1313         Parser<TValue1>.Function function = state =>
1314            {
1315               var result = parser.Execute (state);
1316               if (result.State.HasError ())
1317               {
1318                  return result;
1319               }
1320
1321               var accu = result.Value;
1322
1323               ParserReply<TValue2> separatorResult;
1324
1325               while ((separatorResult = separator.Execute (state)).State.IsSuccessful ())
1326               {
1327                  var trailingResult = parser.Execute (state);
1328
1329                  if (trailingResult.State.HasError ())
1330                  {
1331                     return trailingResult;
1332                  }
1333
1334                  accu = combiner (accu, separatorResult.Value, trailingResult.Value);
1335               }
1336
1337               if (separatorResult.State.HasFatalError ())
1338               {
1339                  return separatorResult.Failure<TValue1> ();
1340               }
1341
1342               return ParserReply<TValue1>.Success (state, accu);
1343            };
1344         return function;
1345      }
1346#endif
1347
1348#if !MICRO_PARSER_SUPPRESS_PARSER_ARRAY
1349      public static Parser<TValue[]> Array<TValue> (
1350         this Parser<TValue> parser,
1351         Parser<Empty> separator,
1352         bool allowTrailingSeparator = false,
1353         int minCount = 0,
1354         int maxCount = int.MaxValue
1355         )
1356      {
1357         VerifyMinAndMaxCount (minCount, maxCount);
1358
1359         Parser<TValue[]>.Function function = state =>
1360         {
1361            var initialPosition = state.Position;
1362
1363            var result = new List<TValue> (Math.Max (minCount, 16));
1364
1365            // Collect required
1366
1367            for (var iter = 0; iter < minCount; ++iter)
1368            {
1369               if (result.Count > 0)
1370               {
1371                  var separatorResult = separator.Execute (state);
1372
1373                  if (separatorResult.State.HasError ())
1374                  {
1375                     return separatorResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1376                  }
1377               }
1378
1379               var parserResult = parser.Execute (state);
1380
1381               if (parserResult.State.HasError ())
1382               {
1383                  return parserResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1384               }
1385
1386               result.Add (parserResult.Value);
1387            }
1388
1389            // Collect optional
1390
1391            for (var iter = minCount; iter < maxCount; ++iter)
1392            {
1393               if (result.Count > 0)
1394               {
1395                  var separatorResult = separator.Execute (state);
1396
1397                  if (separatorResult.State.HasFatalError ())
1398                  {
1399                     return separatorResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1400                  }
1401                  else if (separatorResult.State.HasError ())
1402                  {
1403                     break;
1404                  }
1405
1406               }               
1407
1408               var parserResult = parser.Execute (state);
1409
1410               if (!allowTrailingSeparator && result.Count > 0)
1411               {
1412                  // If a separator has been consumed we need to fail on failures
1413                  if (parserResult.State.HasError())
1414                  {
1415                     return parserResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1416                  }
1417               }
1418               else
1419               {
1420                  // If a separator has not been consumed we only need to fail on fatal errors
1421                  if (parserResult.State.HasFatalError ())
1422                  {
1423                     return parserResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1424                  }
1425                  else if (parserResult.State.HasError ())
1426                  {
1427                     break;
1428                  }
1429               }
1430
1431                result.Add (parserResult.Value);
1432            }
1433
1434            return ParserReply<TValue[]>.Success (state, result.ToArray ());
1435         };
1436         return function;
1437      }
1438#endif
1439
1440#if !MICRO_PARSER_SUPPRESS_PARSER_MANY
1441      public static Parser<TValue[]> Many<TValue> (
1442         this Parser<TValue> parser, 
1443         int minCount = 0, 
1444         int maxCount = int.MaxValue
1445         )
1446      {
1447         VerifyMinAndMaxCount (minCount, maxCount);
1448
1449         Parser<TValue[]>.Function function = state =>
1450         {
1451            var initialPosition = state.Position;
1452
1453            var result = new List<TValue> (Math.Max (minCount, 16));
1454
1455            // Collect required
1456
1457            for (var iter = 0; iter < minCount; ++iter)
1458            {
1459               var parserResult = parser.Execute (state);
1460
1461               if (parserResult.State.HasError ())
1462               {
1463                  return parserResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1464               }
1465
1466               result.Add (parserResult.Value);
1467            }
1468
1469            // Collect optional
1470
1471            for (var iter = minCount; iter < maxCount; ++iter)
1472            {
1473               var parserResult = parser.Execute (state);
1474
1475               if (parserResult.State.HasFatalError ())
1476               {
1477                  return parserResult.Failure<TValue[]> ().VerifyConsistency (initialPosition);
1478               }
1479               else if (parserResult.State.HasError ())
1480               {
1481                  break;
1482               }
1483
1484               result.Add (parserResult.Value);
1485            }
1486
1487            return ParserReply<TValue[]>.Success (state, result.ToArray ());
1488         };
1489         return function;
1490      }
1491#endif
1492
1493#if !MICRO_PARSER_SUPPRESS_PARSER_SWITCH
1494      public enum SwitchCharacterBehavior
1495      {
1496         Consume  ,
1497         Leave    ,
1498      }
1499
1500      public struct SwitchCase<TValue>
1501      {
1502         public readonly string           Case;  
1503         public readonly Parser<TValue>   Parser;
1504         public readonly string           Expected;
1505
1506         public SwitchCase (string @case, Parser<TValue> parser, string expected) : this()
1507         {
1508            Case     = @case     ?? "";
1509            Parser   = parser    ;
1510            Expected = expected  ?? "";
1511         }
1512      }
1513      
1514      public static SwitchCase<TValue> Case<TValue> (
1515         string @case,
1516         Parser<TValue> parser,
1517         string expected = null
1518         )
1519      {
1520         return new SwitchCase<TValue>(@case, parser, expected);
1521      }
1522
1523      public static Parser<TValue> Switch<TValue> (
1524         SwitchCharacterBehavior switchCharacterBehavior,
1525         params SwitchCase<TValue>[] cases
1526         )
1527      {
1528         if (cases == null)
1529         {
1530            throw new ArgumentNullException ("cases");
1531         }
1532
1533         if (cases.Length == 0)
1534         {
1535            throw new ArgumentOutOfRangeException ("cases", Strings.Parser.Verify_AtLeastOneParserFunctions);
1536         }
1537
1538         var caseDictionary = cases
1539            .SelectMany ((@case, i) => @case.Case.Select (c => Tuple.Create (c, i)))
1540            .ToDictionary (kv => kv.Item1, kv => kv.Item2);
1541
1542         var errorMessages = cases
1543            .SelectMany(
1544               (@case, i) => @case.Expected.IsNullOrEmpty()
1545                                ? @case
1546                                     .Case
1547                                     .Select(ch => Strings.CharSatisfy.FormatChar_1.FormatWith(ch))
1548                                : new[] { @case.Expected })
1549            .Distinct ()
1550            .Select (message => new ParserErrorMessage_Expected (message))            
1551            .ToArray();
1552
1553         var errorMessage = new ParserErrorMessage_Group (
1554            errorMessages
1555            );
1556
1557         Parser<TValue>.Function function = state =>
1558                  {
1559                     var initialPosition = state.Position;
1560
1561                     var peeked = state.PeekChar ();
1562
1563                     if (peeked == null)
1564                     {
1565                        return ParserReply<TValue>.Failure (
1566                           ParserReply.State.Error_Unexpected,
1567                           state,
1568                           ParserErrorMessages.Unexpected_Eos
1569                           );
1570                     }
1571
1572                     var peekedValue = peeked.Value;
1573
1574                     int index;
1575                     if (!caseDictionary.TryGetValue (peekedValue, out index))
1576                     {
1577                        return ParserReply<TValue>.Failure (
1578                           ParserReply.State.Error_Expected,
1579                           state,
1580                           errorMessage
1581                           );                        
1582                     }
1583
1584                     if (switchCharacterBehavior == SwitchCharacterBehavior.Consume)
1585                     {
1586                        // Intentionally ignores result as SkipAdvance can't fail 
1587                        // in this situation (we know ParserState has at least one character left)
1588                        state.SkipAdvance (1);
1589                     }
1590
1591                     return cases[index].Parser.Execute(
1592                        state
1593                        )
1594                        .VerifyConsistency(initialPosition);
1595
1596                  };
1597
1598         return function;
1599      }
1600#endif
1601
1602#if !MICRO_PARSER_SUPPRESS_PARSER_CHOICE
1603      public static Parser<TValue> Choice<TValue> (
1604         params Parser<TValue>[] parserFunctions
1605         )
1606      {
1607         if (parserFunctions == null)
1608         {
1609            throw new ArgumentNullException ("parserFunctions");
1610         }
1611
1612         if (parserFunctions.Length == 0)
1613         {
1614            throw new ArgumentOutOfRangeException ("parserFunctions", Strings.Parser.Verify_AtLeastOneParserFunctions);
1615         }
1616
1617         Parser<TValue>.Function function = state =>
1618                   {
1619                      var suppressParserErrorMessageOperations = state.SuppressParserErrorMessageOperations;
1620
1621                      var potentialErrors =
1622                         !suppressParserErrorMessageOperations
1623                           ?  new List<IParserErrorMessage> (parserFunctions.Length)
1624                           :  null
1625                           ;
1626
1627                      foreach (var parserFunction in parserFunctions)
1628                      {
1629                         var result = parserFunction.Execute (state);
1630
1631                         if (result.State.IsSuccessful ())
1632                         {
1633                            return result;
1634                         }
1635                         else if (result.State.HasFatalError ())
1636                         {
1637                            return result;
1638                         }
1639                         else if (!suppressParserErrorMessageOperations)
1640                         {
1641                            potentialErrors.Add (result.ParserErrorMessage);
1642                         }
1643                      }
1644
1645                      if (!suppressParserErrorMessageOperations)
1646                      {
1647                         var topGroup = new ParserErrorMessage_Group (potentialErrors.ToArray ());
1648                         return ParserReply<TValue>.Failure (ParserReply.State.Error_Group, state, topGroup);
1649                      }
1650
1651                      return ParserReply<TValue>.Failure (ParserReply.State.Error_Expected, state, ParserErrorMessages.Expected_Choice);
1652                   };
1653         return function;
1654      }
1655#endif
1656
1657#if !MICRO_PARSER_SUPPRESS_PARSER_KEEP_LEFT
1658      public static Parser<TValue1> KeepLeft<TValue1, TValue2> (
1659         this Parser<TValue1> firstParser, 
1660         Parser<TValue2> secondParser
1661         )
1662      {
1663         Parser<TValue1>.Function function = state =>
1664                   {
1665                      var initialPosition = state.Position;
1666
1667                      var firstResult = firstParser.Execute (state);
1668
1669                      if (firstResult.State.HasError ())
1670                      {
1671                         return firstResult;
1672                      }
1673
1674                      var secondResult = secondParser.Execute (state);
1675
1676                      if (secondResult.State.HasError ())
1677                      {
1678                         return secondResult.Failure<TValue1> ().VerifyConsistency (initialPosition);
1679                      }
1680
1681                      return firstResult.Success (secondResult.ParserState);
1682                   };
1683         return function;
1684      }
1685#endif
1686
1687#if !MICRO_PARSER_SUPPRESS_PARSER_KEEP_RIGHT
1688      public static Parser<TValue2> KeepRight<TValue1, TValue2> (
1689         this Parser<TValue1> firstParser, 
1690         Parser<TValue2> secondParser
1691         )
1692      {
1693         Parser<TValue2>.Function function = state =>
1694                   {
1695                      var firstResult = firstParser.Execute (state);
1696
1697                      if (firstResult.State.HasError ())
1698                      {
1699                         return firstResult.Failure<TValue2> ();
1700                      }
1701
1702                      return secondParser.Execute (state);
1703                   };
1704         return function;
1705      }
1706#endif
1707
1708#if !MICRO_PARSER_SUPPRESS_PARSER_ATTEMPT
1709      public static Parser<TValue> Attempt<TValue>(
1710         this Parser<TValue> firstParser
1711         )
1712      {
1713         Parser<TValue>.Function function = state =>
1714                   {
1715                      var backupPosition = state.InternalPosition;
1716
1717                      var firstResult = firstParser.Execute (state);
1718
1719                      if (!firstResult.State.HasConsistentState ())
1720                      {
1721                         ParserState.RestorePosition (state, backupPosition);
1722
1723                         return ParserReply<TValue>.Failure (
1724                            ParserReply.State.Error_StateIsRestored, 
1725                            state, 
1726                            firstResult.ParserErrorMessage
1727                            );
1728                      }
1729#if DEBUG
1730                      else
1731                      {
1732                         Debug.Assert (backupPosition == state.InternalPosition);
1733                      }
1734#endif
1735
1736                      return firstResult;
1737                   };
1738         return function;
1739      }
1740#endif
1741
1742#if !MICRO_PARSER_SUPPRESS_PARSER_OPT
1743      public static Parser<Optional<TValue>> Opt<TValue> (
1744         this Parser<TValue> firstParser
1745         )
1746      {
1747         Parser<Optional<TValue>>.Function function = state =>
1748         {
1749            var firstResult = firstParser.Execute (state);
1750
1751            if (firstResult.State.IsSuccessful ())
1752            {
1753               return firstResult.Success (Optional.Create (firstResult.Value));
1754            }
1755
1756            if (firstResult.State.HasNonFatalError ())
1757            {
1758               return firstResult.Success (Optional.Create<TValue> ());
1759            }
1760
1761            return firstResult.Failure<Optional<TValue>> ();
1762         };
1763         return function;
1764      }
1765#endif
1766
1767#if !MICRO_PARSER_SUPPRESS_PARSER_BETWEEN
1768      public static Parser<TValue> Between<TValue> (
1769         this Parser<TValue> middleParser,
1770         Parser<Empty> preludeParser,
1771         Parser<Empty> epilogueParser
1772         )
1773      {
1774         Parser<TValue>.Function function = state =>
1775                   {
1776                      var initialPosition = state.Position;
1777
1778                      var preludeResult = preludeParser.Execute (state);
1779                      if (preludeResult.State.HasError ())
1780                      {
1781                         return preludeResult.Failure<TValue> ();
1782                      }
1783
1784                      var middleResult = middleParser.Execute (state);
1785                      if (middleResult.State.HasError ())
1786                      {
1787                         return middleResult.VerifyConsistency (initialPosition);
1788                      }
1789
1790                      var epilogueResult = epilogueParser.Execute (state);
1791                      if (epilogueResult.State.HasError ())
1792                      {
1793                         return epilogueResult.Failure<TValue> ().VerifyConsistency (initialPosition);
1794                      }
1795
1796                      return middleResult.Success (epilogueResult.ParserState);
1797                   };
1798         return function;
1799      }
1800#endif
1801
1802#if !MICRO_PARSER_SUPPRESS_PARSER_EXCEPT
1803      public static Parser<TValue> Except<TValue> (
1804         this Parser<TValue> parser,
1805         Parser<Empty> exceptParser
1806         )
1807      {
1808         Parser<TValue>.Function function = state =>
1809                   {
1810                      var exceptResult = exceptParser.Execute (state);
1811
1812                      if (exceptResult.State.IsSuccessful ())
1813                      {
1814                         return ParserReply<TValue>.Failure (
1815                            ParserReply.State.Error_Unexpected, 
1816                            exceptResult.ParserState, 
1817                            ParserErrorMessages.Message_TODO
1818                            );
1819                      }
1820                      else if (exceptResult.State.HasFatalError ())
1821                      {
1822                         return exceptResult.Failure<TValue> ();
1823                      }
1824
1825                      return parser.Execute (state);
1826                   };
1827         return function;
1828      }
1829#endif
1830
1831      internal static void VerifyMinAndMaxCount (int minCount, int maxCount)
1832      {
1833         if (minCount > maxCount)
1834         {
1835            throw new ArgumentOutOfRangeException ("minCount", Strings.Parser.Verify_MinCountAndMaxCount);
1836         }
1837      }
1838   }
1839}
1840}
1841namespace Include
1842{
1843// ----------------------------------------------------------------------------------------------
1844// Copyright (c) M�rten R�nge.
1845// ----------------------------------------------------------------------------------------------
1846// This source code is subject to terms and conditions of the Microsoft Public License. A 
1847// copy of the license can be found in the License.html file at the root of this distribution. 
1848// If you cannot locate the  Microsoft Public License, please send an email to 
1849// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
1850//  by the terms of the Microsoft Public License.
1851// ----------------------------------------------------------------------------------------------
1852// You must not remove this notice, or any other, from this software.
1853// ----------------------------------------------------------------------------------------------
1854
1855// ReSharper disable InconsistentNaming
1856
1857namespace MicroParser
1858{
1859   using System;
1860   using System.Linq;
1861   using Internal;
1862
1863   partial interface IParserErrorMessage
1864   {
1865      string Description { get; }
1866      object Value { get; }
1867   }
1868
1869   abstract partial class ParserErrorMessage : IParserErrorMessage
1870   {
1871      public abstract string Description { get; }
1872      public abstract object Value { get; }
1873   }
1874
1875   static partial class ParserErrorMessages
1876   {
1877      [Obsolete]
1878      public readonly static IParserErrorMessage Message_TODO           = new ParserErrorMessage_Message (Strings.ParserErrorMessages.Todo);
1879      public readonly static IParserErrorMessage Message_Unknown        = new ParserErrorMessage_Message (Strings.ParserErrorMessages.Unknown);
1880
1881      public readonly static IParserErrorMessage Expected_EndOfStream   = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.Eos);
1882      public readonly static IParserErrorMessage Expected_Digit         = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.Digit);
1883      public readonly static IParserErrorMessage Expected_HexDigit      = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.HexDigit);
1884      public readonly static IParserErrorMessage Expected_WhiteSpace    = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.WhiteSpace);
1885      public readonly static IParserErrorMessage Expected_Choice        = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.Choice);
1886      public readonly static IParserErrorMessage Expected_Any           = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.Any);
1887      public readonly static IParserErrorMessage Expected_Letter        = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.Letter);
1888      public readonly static IParserErrorMessage Expected_LineBreak     = new ParserErrorMessage_Expected (Strings.ParserErrorMessages.LineBreak);
1889
1890      public readonly static IParserErrorMessage Unexpected_Eos         = new ParserErrorMessage_Unexpected (Strings.ParserErrorMessages.Eos);
1891   }
1892
1893
1894   sealed partial class ParserErrorMessage_Message : ParserErrorMessage
1895   {
1896      public readonly string Message;
1897
1898      public ParserErrorMessage_Message (string message)
1899      {
1900         Message = message;
1901      }
1902
1903      public override string ToString ()
1904      {
1905         return Strings.ParserErrorMessages.Message_1.FormatWith (Message);
1906      }
1907
1908      public override string Description
1909      {
1910         get { return Strings.ParserErrorMessages.Message; }
1911      }
1912
1913      public override object Value
1914      {
1915         get { return Message; }
1916      }
1917   }
1918
1919   sealed partial class ParserErrorMessage_Expected : ParserErrorMessage
1920   {
1921      public readonly string Expected;
1922
1923      public ParserErrorMessage_Expected (string expected)
1924      {
1925         Expected = expected;
1926      }
1927
1928      public override string ToString ()
1929      {
1930         return Strings.ParserErrorMessages.Expected_1.FormatWith (Expected);
1931      }
1932
1933      public override string Description
1934      {
1935         get { return Strings.ParserErrorMessages.Expected; }
1936      }
1937
1938      public override object Value
1939      {
1940         get { return Expected; }
1941      }
1942   }
1943
1944   sealed partial class ParserErrorMessage_Unexpected : ParserErrorMessage
1945   {
1946      public readonly string Unexpected;
1947
1948      public ParserErrorMessage_Unexpected (string unexpected)
1949      {
1950         Unexpected = unexpected;
1951      }
1952
1953      public override string ToString ()
1954      {
1955         return Strings.ParserErrorMessages.Unexpected_1.FormatWith (Unexpected);
1956      }
1957
1958      public override string Description
1959      {
1960         get { return Strings.ParserErrorMessages.Unexpected; }
1961      }
1962
1963      public override object Value
1964      {
1965         get { return Unexpected; }
1966      }
1967   }
1968
1969   sealed partial class ParserErrorMessage_Group : ParserErrorMessage
1970   {
1971      public readonly IParserErrorMessage[] Group;
1972
1973      public ParserErrorMessage_Group (IParserErrorMessage[] group)
1974      {
1975         Group = group;
1976      }
1977
1978      public override string ToString ()
1979      {
1980         return Strings.ParserErrorMessages.Group_1.FormatWith (Group.Select (message => message.ToString ()).Concatenate (Strings.CommaSeparator));
1981      }
1982
1983      public override string Description
1984      {
1985         get { return Strings.ParserErrorMessages.Group; }
1986      }
1987
1988      public override object Value
1989      {
1990         get { return Strings.ParserErrorMessages.Group; }
1991      }
1992   }
1993}
1994}
1995namespace Include
1996{
1997// ----------------------------------------------------------------------------------------------
1998// Copyright (c) Mårten Rånge.
1999// ----------------------------------------------------------------------------------------------
2000// This source code is subject to terms and conditions of the Microsoft Public License. A 
2001// copy of the license can be found in the License.html file at the root of this distribution. 
2002// If you cannot locate the  Microsoft Public License, please send an email to 
2003// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2004//  by the terms of the Microsoft Public License.
2005// ----------------------------------------------------------------------------------------------
2006// You must not remove this notice, or any other, from this software.
2007// ----------------------------------------------------------------------------------------------
2008namespace MicroParser
2009{
2010
2011   sealed partial class ParserFunctionRedirect<TValue>
2012   {
2013      public readonly Parser<TValue> Parser;
2014      public Parser<TValue> ParserRedirect;
2015
2016      public ParserFunctionRedirect ()
2017      {
2018         Parser<TValue> .Function function = state => ParserRedirect.Execute (state);
2019         Parser = function;
2020      }
2021      
2022   }
2023}
2024}
2025namespace Include
2026{
2027// ----------------------------------------------------------------------------------------------
2028// Copyright (c) Mårten Rånge.
2029// ----------------------------------------------------------------------------------------------
2030// This source code is subject to terms and conditions of the Microsoft Public License. A 
2031// copy of the license can be found in the License.html file at the root of this distribution. 
2032// If you cannot locate the  Microsoft Public License, please send an email to 
2033// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2034//  by the terms of the Microsoft Public License.
2035// ----------------------------------------------------------------------------------------------
2036// You must not remove this notice, or any other, from this software.
2037// ----------------------------------------------------------------------------------------------
2038
2039namespace MicroParser
2040{
2041   using System;
2042   using MicroParser.Internal;
2043	partial class Parser
2044	{
2045#if !MICRO_PARSER_SUPPRESS_PARSER_GROUP_2
2046      public static Parser<Tuple<TValue1, TValue2>> Group<TValue1, TValue2> (
2047            Parser<TValue1> parser1
2048         ,  Parser<TValue2> parser2
2049         )
2050      {
2051         Parser<Tuple<TValue1, TValue2>>.Function function = state =>
2052         {
2053            var initialPosition = state.Position;
2054
2055            var result1 = parser1.Execute (state);
2056
2057            if (result1.State.HasError ())
2058            {
2059               return result1.Failure<Tuple<TValue1, TValue2>>().VerifyConsistency (initialPosition);
2060            }
2061            var result2 = parser2.Execute (state);
2062
2063            if (result2.State.HasError ())
2064            {
2065               return result2.Failure<Tuple<TValue1, TValue2>>().VerifyConsistency (initialPosition);
2066            }
2067            return result2.Success (
2068               Tuple.Create (
2069                     result1.Value
2070                  ,  result2.Value
2071                  ));
2072         };
2073         return function;
2074      }
2075#endif
2076#if !MICRO_PARSER_SUPPRESS_PARSER_GROUP_3
2077      public static Parser<Tuple<TValue1, TValue2, TValue3>> Group<TValue1, TValue2, TValue3> (
2078            Parser<TValue1> parser1
2079         ,  Parser<TValue2> parser2
2080         ,  Parser<TValue3> parser3
2081         )
2082      {
2083         Parser<Tuple<TValue1, TValue2, TValue3>>.Function function = state =>
2084         {
2085            var initialPosition = state.Position;
2086
2087            var result1 = parser1.Execute (state);
2088
2089            if (result1.State.HasError ())
2090            {
2091               return result1.Failure<Tuple<TValue1, TValue2, TValue3>>().VerifyConsistency (initialPosition);
2092            }
2093            var result2 = parser2.Execute (state);
2094
2095            if (result2.State.HasError ())
2096            {
2097               return result2.Failure<Tuple<TValue1, TValue2, TValue3>>().VerifyConsistency (initialPosition);
2098            }
2099            var result3 = parser3.Execute (state);
2100
2101            if (result3.State.HasError ())
2102            {
2103               return result3.Failure<Tuple<TValue1, TValue2, TValue3>>().VerifyConsistency (initialPosition);
2104            }
2105            return result3.Success (
2106               Tuple.Create (
2107                     result1.Value
2108                  ,  result2.Value
2109                  ,  result3.Value
2110                  ));
2111         };
2112         return function;
2113      }
2114#endif
2115
2116
2117   }
2118}
2119}
2120namespace Include
2121{
2122// ----------------------------------------------------------------------------------------------
2123// Copyright (c) Mårten Rånge.
2124// ----------------------------------------------------------------------------------------------
2125// This source code is subject to terms and conditions of the Microsoft Public License. A 
2126// copy of the license can be found in the License.html file at the root of this distribution. 
2127// If you cannot locate the  Microsoft Public License, please send an email to 
2128// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2129//  by the terms of the Microsoft Public License.
2130// ----------------------------------------------------------------------------------------------
2131// You must not remove this notice, or any other, from this software.
2132// ----------------------------------------------------------------------------------------------
2133namespace MicroParser
2134{
2135   using Internal;
2136
2137   using System;
2138   using System.Diagnostics;
2139
2140   static partial class ParserReply
2141   {
2142      // ReSharper disable InconsistentNaming
2143      [Flags]
2144      public enum State
2145      {
2146         Successful                     = 00,
2147         Error                          = 10,
2148         Error_Message                  = 11,
2149         Error_Expected                 = 12,
2150         Error_Unexpected               = 13,
2151         Error_Group                    = 14,
2152         Error_StateIsRestored          = 15,
2153         Error_Mask                     = 0x0000FFFF,
2154         FatalError                     = 0x00010000,
2155         FatalError_Mask                = 0x7FFF0000,
2156         FatalError_Terminate           = 0x00010000,
2157         FatalError_StateIsNotRestored  = 0x00020000,
2158      }
2159      // ReSharper restore InconsistentNaming
2160
2161      static ParserReply<TValue> CreateParserReplyFailure<TValue>(ParserState.AdvanceResult advanceResult, ParserState state, IParserErrorMessage parserErrorMessage)
2162      {
2163         switch (advanceResult)
2164         {
2165            case ParserState.AdvanceResult.Error_EndOfStream:
2166               return ParserReply<TValue>.Failure (State.Error_Unexpected, state, ParserErrorMessages.Unexpected_Eos);
2167            case ParserState.AdvanceResult.Error_SatisfyFailed:
2168               return ParserReply<TValue>.Failure (State.Error, state, parserErrorMessage);
2169            case ParserState.AdvanceResult.Error_EndOfStream_PostionChanged:
2170               return ParserReply<TValue>.Failure (State.FatalError_StateIsNotRestored | State.Error_Unexpected, state, ParserErrorMessages.Unexpected_Eos);
2171            case ParserState.AdvanceResult.Error_SatisfyFailed_PositionChanged:
2172               return ParserReply<TValue>.Failure (State.FatalError_StateIsNotRestored | State.Error, state, parserErrorMessage);
2173            case ParserState.AdvanceResult.Error:
2174            default:
2175               return ParserReply<TValue>.Failure (State.Error, state, ParserErrorMessages.Message_Unknown);
2176         }
2177      }
2178
2179      public static ParserReply<TValue> Create<TValue>(
2180         ParserState.AdvanceResult advanceResult,
2181         ParserState state,
2182         IParserErrorMessage parserErrorMessage,
2183         TValue value
2184         )
2185      {
2186         return advanceResult == ParserState.AdvanceResult.Successful 
2187            ?  ParserReply<TValue>.Success (state, value) 
2188            :  CreateParserReplyFailure<TValue>(advanceResult, state, parserErrorMessage)
2189            ;
2190      }
2191
2192      public static ParserReply<TValue> Create<TValue>(
2193         ParserState.AdvanceResult advanceResult,
2194         ParserState state,
2195         IParserErrorMessage parserErrorMessage,
2196         Func<TValue> valueCreator
2197         )
2198      {
2199         return advanceResult == ParserState.AdvanceResult.Successful
2200            ?  ParserReply<TValue>.Success (state, valueCreator ())
2201            :  CreateParserReplyFailure<TValue>(advanceResult, state, parserErrorMessage)
2202            ;
2203      }      
2204   }
2205
2206   partial struct ParserReply<TValue>
2207   {
2208      public readonly ParserReply.State State;
2209      public readonly ParserState ParserState;
2210      public readonly IParserErrorMessage ParserErrorMessage;
2211
2212      public readonly TValue Value;
2213
2214      ParserReply (ParserReply.State state, ParserState parserState, TValue value, IParserErrorMessage parserErrorMessage)
2215      {
2216         State = state;
2217         ParserState = parserState;
2218         ParserErrorMessage = parserErrorMessage;
2219         Value = value;
2220      }
2221
2222      public static ParserReply<TValue> Success (
2223         ParserState parserState, 
2224         TValue value
2225         )
2226      {
2227         return new ParserReply<TValue>(
2228            ParserReply.State.Successful, 
2229            parserState, 
2230            value, 
2231            null
2232            );
2233      }
2234
2235      public static ParserReply<TValue> Failure (
2236         ParserReply.State state, 
2237         ParserState parserState, 
2238         IParserErrorMessage parserErrorMessage
2239         )
2240      {
2241         Debug.Assert (!state.IsSuccessful ());
2242         Debug.Assert (parserErrorMessage != null);
2243
2244         return new ParserReply<TValue>(
2245            state.IsSuccessful () ? ParserReply.State.Error : state, 
2246            parserState, 
2247            default (TValue), 
2248            parserErrorMessage
2249            );
2250      }
2251
2252      public ParserReply<TValueTo> Failure<TValueTo> ()
2253      {
2254         return ParserReply<TValueTo>.Failure (State, ParserState, ParserErrorMessage);
2255      }
2256
2257      public ParserReply<TValue> Success (ParserState parserState)
2258      {
2259         return Success (parserState, Value);
2260      }
2261
2262      public ParserReply<TValueTo> Success<TValueTo> (TValueTo valueTo)
2263      {
2264         return ParserReply<TValueTo>.Success (ParserState, valueTo);
2265      }
2266
2267      public ParserReply<TValue> Failure (ParserState parserState)
2268      {
2269         return Failure (
2270            State,
2271            parserState, 
2272            ParserErrorMessage
2273            );
2274      }
2275
2276      public ParserReply<TValue> VerifyConsistency (ParserStatePosition initialPosition)
2277      {
2278         if (
2279               State.HasError () 
2280            && ParserState.InternalPosition - initialPosition.Position > 0
2281            )
2282         {
2283            return new ParserReply<TValue>(
2284               ParserReply.State.FatalError_StateIsNotRestored | State,
2285               ParserState,
2286               default (TValue),
2287               ParserErrorMessage
2288               );
2289         }
2290
2291         return this;
2292      }
2293
2294#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
2295      public override string ToString ()
2296      {
2297         if (State == ParserReply.State.Successful)
2298         {
2299            return new
2300            {
2301               State,
2302               ParserState,
2303               Value,
2304            }.ToString ();
2305            
2306         }
2307         else
2308         {
2309            return new
2310            {
2311               State,
2312               ParserState,
2313               ParserErrorMessage,
2314            }.ToString ();
2315         }
2316      }      
2317#endif
2318
2319   }
2320}
2321}
2322namespace Include
2323{
2324// ----------------------------------------------------------------------------------------------
2325// Copyright (c) Mårten Rånge.
2326// ----------------------------------------------------------------------------------------------
2327// This source code is subject to terms and conditions of the Microsoft Public License. A 
2328// copy of the license can be found in the License.html file at the root of this distribution. 
2329// If you cannot locate the  Microsoft Public License, please send an email to 
2330// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2331//  by the terms of the Microsoft Public License.
2332// ----------------------------------------------------------------------------------------------
2333// You must not remove this notice, or any other, from this software.
2334// ----------------------------------------------------------------------------------------------
2335namespace MicroParser
2336{
2337   abstract partial class BaseParserResult
2338   {
2339      public readonly bool IsSuccessful;
2340      public readonly SubString Unconsumed;
2341      public readonly string ErrorMessage;
2342
2343      public bool EndOfStream
2344      {
2345         get
2346         {
2347            return !(Unconsumed.Begin < Unconsumed.End);
2348         }
2349      }
2350
2351      protected BaseParserResult (bool isSuccessful, SubString unconsumed, string errorMessage)
2352      {
2353         IsSuccessful = isSuccessful;
2354         Unconsumed = unconsumed;
2355         ErrorMessage = errorMessage ?? Strings.Empty;
2356      }
2357
2358#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
2359      public override string ToString ()
2360      {
2361         if (IsSuccessful)
2362         {
2363            return new
2364                      {
2365                         IsSuccessful,
2366                         Position = Unconsumed.Begin,
2367                         EndOfStream,
2368                         Current = !EndOfStream ? new string (Unconsumed[Unconsumed.Begin], 1) : Strings.ParserErrorMessages.Eos,
2369                         Value = GetValue (),
2370                      }.ToString ();
2371         }
2372         else
2373         {
2374
2375            return new
2376            {
2377               IsSuccessful,
2378               Position = Unconsumed.Begin,
2379               EndOfStream,
2380               Current = !EndOfStream ? new string (Unconsumed[Unconsumed.Begin], 1) : Strings.ParserErrorMessages.Eos,
2381               ErrorMessage,
2382            }.ToString ();
2383         }
2384      }
2385#endif
2386
2387      protected abstract object GetValue ();
2388   }
2389
2390   sealed partial class ParserResult<TValue> : BaseParserResult
2391   {
2392      public readonly TValue Value;
2393
2394      public ParserResult (bool isSuccessful, SubString subString, string errorMessage, TValue value)
2395         : base (isSuccessful, subString, errorMessage)
2396      {
2397         Value = value;
2398      }
2399
2400      protected override object GetValue ()
2401      {
2402         return Value;
2403      }
2404   }
2405}
2406}
2407namespace Include
2408{
2409// ----------------------------------------------------------------------------------------------
2410// Copyright (c) Mårten Rånge.
2411// ----------------------------------------------------------------------------------------------
2412// This source code is subject to terms and conditions of the Microsoft Public License. A 
2413// copy of the license can be found in the License.html file at the root of this distribution. 
2414// If you cannot locate the  Microsoft Public License, please send an email to 
2415// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2416//  by the terms of the Microsoft Public License.
2417// ----------------------------------------------------------------------------------------------
2418// You must not remove this notice, or any other, from this software.
2419// ----------------------------------------------------------------------------------------------
2420namespace MicroParser
2421{
2422   using System;
2423   using System.Diagnostics;
2424
2425   partial struct ParserStatePosition
2426   {
2427      public readonly int Position;
2428
2429      public ParserStatePosition (int position)
2430      {
2431         Position = position;
2432      }
2433
2434#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
2435      public override string ToString ()
2436      {
2437         return new
2438                   {
2439                      Position,
2440                   }.ToString ();
2441      }
2442#endif
2443
2444   }
2445
2446   sealed partial class ParserState
2447   {
2448      // ReSharper disable InconsistentNaming
2449      public enum AdvanceResult
2450      {
2451         Successful                             = 00,
2452         Error                                  = 10,
2453         Error_EndOfStream                      = 11,
2454         Error_SatisfyFailed                    = 12,
2455         Error_EndOfStream_PostionChanged       = 23,
2456         Error_SatisfyFailed_PositionChanged    = 24,
2457      }
2458      // ReSharper restore InconsistentNaming
2459
2460      readonly string m_text;
2461      int m_position;
2462
2463      public readonly bool SuppressParserErrorMessageOperations;
2464
2465      ParserState (int position, string text, bool suppressParserErrorMessageOperations)
2466      {
2467         m_position = Math.Max (position, 0);
2468         m_text = text ?? String.Empty;
2469         SuppressParserErrorMessageOperations = suppressParserErrorMessageOperations;
2470      }
2471
2472      internal int InternalPosition
2473      {
2474         get
2475         {
2476            return m_position;
2477         }
2478      }
2479
2480      public string Text
2481      {
2482         get
2483         {
2484            return m_text;
2485         }
2486      }
2487
2488      public ParserStatePosition Position
2489      {
2490         get
2491         {
2492            return new ParserStatePosition (m_position);
2493         }
2494      }
2495
2496      public bool EndOfStream
2497      {
2498         get
2499         {
2500            return !(m_position < m_text.Length);
2501         }
2502      }
2503
2504      public char? PeekChar ()
2505      {
2506         if (EndOfStream)
2507         {
2508            return null;
2509         }
2510
2511         return m_text[m_position];
2512      }
2513
2514      public AdvanceResult Advance (
2515         ref SubString subString,
2516         CharSatisfy.Function satisfy,
2517         int minCount = 1,
2518         int maxCount = int.MaxValue
2519         )
2520      {
2521         Debug.Assert (minCount <= maxCount);
2522
2523         var localSatisfy = satisfy ?? CharSatisfy.AnyChar.Satisfy;
2524
2525         subString.Value = m_text;
2526         subString.Position = m_position;
2527
2528         /*
2529          * This optimization is very tempting to do, but this will give the wrong error message
2530          * The optimization only saves time at the end of stream so it was removed
2531         if (m_position + minCount >= m_text.Length + 1)
2532         {
2533            return AdvanceResult.Error_EndOfStream;
2534         }
2535         */ 
2536
2537         var length = Math.Min (maxCount, m_text.Length - m_position);
2538         for (var iter = 0; iter < length; ++iter)
2539         {
2540            var c = m_text[m_position];
2541
2542            if (!localSatisfy (c, iter))
2543            {
2544               if (iter < minCount)
2545               {
2546                  return subString.Position == m_position
2547                            ? AdvanceResult.Error_SatisfyFailed
2548                            : AdvanceResult.Error_SatisfyFailed_PositionChanged
2549                     ;
2550               }
2551
2552               subString.Length = m_position - subString.Position;
2553
2554               return AdvanceResult.Successful;
2555            }
2556
2557            ++m_position;
2558         }
2559
2560         subString.Length = m_position - subString.Position;
2561
2562         if (length < minCount)
2563         {
2564            return subString.Position == m_position
2565                      ? AdvanceResult.Error_SatisfyFailed
2566                      : AdvanceResult.Error_SatisfyFailed_PositionChanged
2567               ;
2568         }
2569
2570         return AdvanceResult.Successful;
2571      }
2572
2573      public AdvanceResult SkipAdvance (int count)
2574      {
2575         if (m_position + count >= m_text.Length + 1)
2576         {
2577            return AdvanceResult.Error_EndOfStream;
2578         }
2579
2580         m_position += count;
2581
2582         return AdvanceResult.Successful;
2583      }
2584
2585      public AdvanceResult SkipAdvance (
2586         CharSatisfy.Function satisfy,
2587         int minCount = 1,
2588         int maxCount = int.MaxValue
2589         )
2590      {
2591         var subString = new SubString ();
2592         return Advance (ref subString, satisfy, minCount, maxCount);
2593      }
2594
2595#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
2596      public override string ToString ()
2597      {
2598         return new
2599                   {
2600                      Position = m_position,
2601                      SuppressParserErrorMessageOperations,
2602                      EndOfStream,
2603                      Current = !EndOfStream ? new string (m_text[m_position], 1) : Strings.ParserErrorMessages.Eos,
2604                   }.ToString ();
2605      }
2606#endif
2607
2608      public static ParserState Create (
2609         string text, 
2610         int position = 0, 
2611         bool suppressParserErrorMessageOperations = false
2612         )
2613      {
2614         return new ParserState (
2615            Math.Max (position, 0), 
2616            text ?? Strings.Empty,
2617            suppressParserErrorMessageOperations
2618            );
2619      }
2620
2621      public static ParserState Clone (ParserState parserState)
2622      {
2623         if (parserState == null)
2624         {
2625            return null;
2626         }
2627
2628         return new ParserState (
2629            parserState.m_position, 
2630            parserState.m_text, 
2631            parserState.SuppressParserErrorMessageOperations
2632            );
2633      }
2634
2635      public static void Restore (ParserState parserState, ParserState clone)
2636      {
2637         if (parserState == null)
2638         {
2639            return;
2640         }
2641
2642         if (clone == null)
2643         {
2644            return;
2645         }
2646
2647         parserState.m_position = clone.m_position;
2648      }
2649
2650       internal static void RestorePosition (ParserState parserState, int position)
2651      {
2652          if (parserState == null)
2653          {
2654              return;
2655          }
2656
2657          parserState.m_position = position;
2658      }
2659
2660   }
2661}
2662}
2663namespace Include
2664{
2665// ----------------------------------------------------------------------------------------------
2666// Copyright (c) Mårten Rånge.
2667// ----------------------------------------------------------------------------------------------
2668// This source code is subject to terms and conditions of the Microsoft Public License. A 
2669// copy of the license can be found in the License.html file at the root of this distribution. 
2670// If you cannot locate the  Microsoft Public License, please send an email to 
2671// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2672//  by the terms of the Microsoft Public License.
2673// ----------------------------------------------------------------------------------------------
2674// You must not remove this notice, or any other, from this software.
2675// ----------------------------------------------------------------------------------------------
2676
2677// ReSharper disable InconsistentNaming
2678
2679namespace MicroParser
2680{
2681   using System;
2682
2683   static partial class Strings
2684   {
2685      public const string CommaSeparator  = ", ";
2686      public const string Empty           = "";
2687
2688      public static class Parser
2689      {
2690         public const string ErrorMessage_2                    = "{0} : {1}";
2691         public const string Verify_AtLeastOneParserFunctions  = "cases should contain at least 1 item";
2692         public const string Verify_MinCountAndMaxCount        = "minCount need to be less or equal to maxCount";
2693      }
2694
2695      public static class CharSatisfy
2696      {
2697         public const string FormatChar_1 = "'{0}'";
2698      }
2699
2700      public static class ParserErrorMessages
2701      {
2702         public const string Message_1    = "Message:{0}";
2703         public const string Expected_1   = "Expected:{0}";
2704         public const string Unexpected_1 = "Unexpected:{0}";
2705         public const string Group_1      = "Group:{0}";
2706
2707         [Obsolete]
2708         public const string Todo         = "TODO:";
2709         public const string Unexpected   = "unexpected ";
2710         public const string Unknown      = "unknown error";
2711         public const string Eos          = "end of stream";
2712         public const string WhiteSpace   = "whitespace";
2713         public const string Digit        = "digit";
2714         public const string HexDigit     = "hexdigit";
2715         public const string Letter       = "letter";
2716         public const string Any          = "any";
2717         public const string LineBreak    = "linebreak";
2718
2719         public const string Choice       = "multiple choices";
2720         public const string Message      = "message";
2721         public const string Group        = "group";
2722         public const string Expected     = "expected";
2723
2724      }
2725
2726   }
2727}
2728}
2729namespace Include
2730{
2731// ----------------------------------------------------------------------------------------------
2732// Copyright (c) Mårten Rånge.
2733// ----------------------------------------------------------------------------------------------
2734// This source code is subject to terms and conditions of the Microsoft Public License. A 
2735// copy of the license can be found in the License.html file at the root of this distribution. 
2736// If you cannot locate the  Microsoft Public License, please send an email to 
2737// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2738//  by the terms of the Microsoft Public License.
2739// ----------------------------------------------------------------------------------------------
2740// You must not remove this notice, or any other, from this software.
2741// ----------------------------------------------------------------------------------------------
2742namespace MicroParser
2743{
2744   using System;
2745   using System.Diagnostics;
2746   using System.Text;
2747
2748   partial struct SubString : IEquatable<SubString>
2749   {
2750      public string Value;
2751      public int Position;
2752      public int Length;
2753
2754      public static implicit operator SubString (string s)
2755      {
2756         return new SubString (s);
2757      }
2758
2759      public SubString (string value, int position, int length)
2760      {
2761         Value = value;
2762         Position = position;
2763         Length = length;
2764      }
2765
2766      public SubString (string value, int position = 0)
2767         :  this (value, position, (value ?? Strings.Empty).Length - position)
2768      {
2769
2770      }
2771
2772      public int EffectiveLength
2773      {
2774         get
2775         {
2776            return End - Begin;
2777         }
2778      }
2779
2780      public int Begin
2781      {
2782         get
2783         {
2784            return Math.Max (Position, 0);
2785         }
2786      }
2787
2788      public int End
2789      {
2790         get
2791         {
2792            return Math.Min (Position + Length, SafeValue.Length);
2793         }
2794      }
2795
2796      string SafeValue
2797      {
2798         get
2799         {
2800            return Value ?? Strings.Empty;
2801         }
2802      }
2803
2804      public bool Equals (SubString other)
2805      {
2806
2807         var value = SafeValue;
2808         var otherValue = other.SafeValue;
2809
2810         var effectiveLength = EffectiveLength;
2811         var effectiveOtherLength = other.EffectiveLength;
2812
2813         if (effectiveLength != effectiveOtherLength)
2814         {
2815            return false;
2816         }
2817
2818         var begin = Begin;
2819         var otherBegin = other.Begin;
2820
2821         var end = End;
2822         var otherEnd = other.End;
2823
2824         var diff = otherBegin - begin;
2825 
2826         for (var iter = begin; iter < end; ++iter)
2827         {
2828            if (value[iter] != otherValue[iter + diff])
2829            {
2830               return false;
2831            }
2832         }
2833
2834         return true;
2835      }
2836
2837      public override string ToString ()
2838      {
2839         return SafeValue.Substring (Begin, EffectiveLength);
2840      }
2841
2842      public char this[int index]
2843      {
2844         get
2845         {
2846            var realIndex = Position + index;
2847            return realIndex > -1 && realIndex < Value.Length 
2848               ?  Value[Position + index] 
2849               :  ' '
2850               ;
2851         }
2852      }
2853
2854      public static bool operator == (SubString left, SubString right)
2855      {
2856         return left.Equals (right);
2857      }
2858
2859      public static bool operator != (SubString left, SubString right)
2860      {
2861         return !(left == right);
2862      }
2863
2864      public override bool Equals (object obj)
2865      {
2866         return obj is SubString && Equals ((SubString) obj);
2867      }
2868
2869      public override int GetHashCode ()
2870      {
2871         var result = 0x55555555;
2872
2873         var value = SafeValue;
2874
2875         var end = End;
2876
2877         for (var iter = Begin; iter < end; ++iter)
2878         {
2879            result = (result * 397) ^ value[iter];
2880         }
2881
2882         return result;
2883      }
2884   }
2885}
2886}
2887namespace Include
2888{
2889// ----------------------------------------------------------------------------------------------
2890// Copyright (c) Mårten Rånge.
2891// ----------------------------------------------------------------------------------------------
2892// This source code is subject to terms and conditions of the Microsoft Public License. A 
2893// copy of the license can be found in the License.html file at the root of this distribution. 
2894// If you cannot locate the  Microsoft Public License, please send an email to 
2895// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2896//  by the terms of the Microsoft Public License.
2897// ----------------------------------------------------------------------------------------------
2898// You must not remove this notice, or any other, from this software.
2899// ----------------------------------------------------------------------------------------------
2900namespace MicroParser
2901{
2902#if MICRO_PARSER_NET35
2903   static partial class Tuple
2904   {
2905      public static Tuple<TValue1, TValue2> Create<TValue1, TValue2> (
2906            TValue1 value1
2907         ,  TValue2 value2
2908         )
2909      {
2910         return new Tuple<TValue1, TValue2>
2911            {
2912               Item1 = value1 ,
2913               Item2 = value2 ,
2914            };
2915      }
2916      public static Tuple<TValue1, TValue2, TValue3> Create<TValue1, TValue2, TValue3> (
2917            TValue1 value1
2918         ,  TValue2 value2
2919         ,  TValue3 value3
2920         )
2921      {
2922         return new Tuple<TValue1, TValue2, TValue3>
2923            {
2924               Item1 = value1 ,
2925               Item2 = value2 ,
2926               Item3 = value3 ,
2927            };
2928      }
2929   }
2930   partial struct Tuple<TValue1, TValue2>
2931   {
2932      public TValue1 Item1;
2933      public TValue2 Item2;
2934
2935#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
2936      public override string ToString ()
2937      {
2938         return new 
2939         {
2940            Item1,
2941            Item2,
2942         }.ToString ();
2943      }
2944#endif
2945   }
2946   partial struct Tuple<TValue1, TValue2, TValue3>
2947   {
2948      public TValue1 Item1;
2949      public TValue2 Item2;
2950      public TValue3 Item3;
2951
2952#if !MICRO_PARSER_SUPPRESS_ANONYMOUS_TYPE
2953      public override string ToString ()
2954      {
2955         return new 
2956         {
2957            Item1,
2958            Item2,
2959            Item3,
2960         }.ToString ();
2961      }
2962#endif
2963   }
2964#endif
2965}
2966}
2967// ----------------------------------------------------------------------------------------------
2968// Copyright (c) Mårten Rånge.
2969// ----------------------------------------------------------------------------------------------
2970// This source code is subject to terms and conditions of the Microsoft Public License. A 
2971// copy of the license can be found in the License.html file at the root of this distribution. 
2972// If you cannot locate the  Microsoft Public License, please send an email to 
2973// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
2974//  by the terms of the Microsoft Public License.
2975// ----------------------------------------------------------------------------------------------
2976// You must not remove this notice, or any other, from this software.
2977// ----------------------------------------------------------------------------------------------
2978
2979namespace MicroParser.Json
2980{
2981    using System;
2982    using System.Collections;
2983    using System.Collections.Generic;
2984    using System.Diagnostics;
2985    using System.Globalization;
2986    using System.Linq;
2987    using System.Text;
2988    using Include.MicroParser;
2989
2990    public sealed partial class JsonUnserializeError
2991    {
2992        public readonly string ErrorMessage;
2993        public readonly int ErrorOffset;
2994
2995        public JsonUnserializeError (string errorMessage, int errorOffset)
2996        {
2997            ErrorMessage = errorMessage ?? "<NULL>";
2998            ErrorOffset = errorOffset;
2999        }
3000
3001        public override string ToString ()
3002        {
3003            return new
3004            {
3005                ErrorOffset,
3006                ErrorMessage
3007            }.ToString ();
3008        }
3009
3010    }
3011
3012    static partial class JsonSerializer
3013    {
3014       static partial void TransformObjects (object[] objects, ref object result);
3015       static partial void TransformObject (Tuple<string, object>[] properties, ref object result);
3016
3017#if MICRO_PARSER_JSON_NET35
3018        static IEnumerable<TZipped> Zip<T0, T1, TZipped>(
3019           this IEnumerable<T0> values0,
3020           IEnumerable<T1> values1,
3021           Func<T0, T1, TZipped> zipper
3022           )
3023        {
3024            if (zipper == null)
3025            {
3026                throw new ArgumentNullException ("zipper");
3027            }
3028            values0 = values0 ?? new T0[0];
3029            values1 = values1 ?? new T1[0];
3030
3031            using (var e0 = values0.GetEnumerator ())
3032            using (var e1 = values1.GetEnumerator ())
3033            {
3034                bool moveNext0;
3035                bool moveNext1;
3036                while ((moveNext0 = e0.MoveNext () & (moveNext1 = e1.MoveNext ())))
3037                {
3038                    yield return zipper (e0.Current, e1.Current);
3039                }
3040
3041                if (moveNext0 != moveNext1)
3042                {
3043                    throw new ArgumentException ("values0 and values1 must be of same length");
3044                }
3045            }
3046
3047        }
3048#endif
3049        static readonly Parser<object> s_parser;
3050
3051        struct StringPart
3052        {
3053            readonly int m_item1;
3054            readonly int m_item2;
3055
3056            public StringPart (int position, int length)
3057            {
3058                m_item1 = position;
3059                m_item2 = length;
3060            }
3061
3062            public StringPart (char ch)
3063            {
3064                m_item1 = ch;
3065                m_item2 = 0;
3066            }
3067
3068            public bool IsRange
3069            {
3070                get
3071                {
3072                    return m_item2 > 0;
3073                }
3074            }
3075
3076            public int Position
3077            {
3078                get
3079                {
3080                    Debug.Assert (IsRange);
3081                    return m_item1;
3082                }
3083            }
3084
3085            public int Length
3086            {
3087                get
3088                {
3089                    Debug.Assert (IsRange);
3090                    return m_item2;
3091                }
3092            }
3093
3094            public char Character
3095            {
3096                get
3097                {
3098                    unchecked
3099                    {
3100                        Debug.Assert (!IsRange);
3101                        return (char)(m_item1 & 0xFFFF);
3102                    }
3103                }
3104            }
3105        }
3106
3107        static Parser<string> CombineStringParts (
3108           this Parser<StringPart[]> parser
3109           )
3110        {
3111            Parser<string>.Function function =
3112               state =>
3113               {
3114                   var result = parser.Execute (state);
3115                   if (result.State.HasError ())
3116                   {
3117                       return result.Failure<string>();
3118                   }
3119
3120                   var text = state.Text;
3121                   var length = 0;
3122
3123                   foreach (var stringPart in result.Value)
3124                   {
3125                       if (stringPart.IsRange)
3126                       {
3127                           length += stringPart.Length;
3128                       }
3129                       else
3130                       {
3131                           ++length;
3132                       }
3133                   }
3134
3135                   var charArray = new char[length];
3136
3137                   var position = 0;
3138
3139                   foreach (var stringPart in result.Value)
3140                   {
3141                       if (stringPart.IsRange)
3142                       {
3143                           var begin = stringPart.Position;
3144                           var end = begin + stringPart.Length;
3145                           for (var iter = begin; iter < end; ++iter)
3146                           {
3147                               charArray[position++] = text[iter];
3148                           }
3149                       }
3150                       else
3151                       {
3152                           charArray[position++] = stringPart.Character;
3153                       }
3154                   }
3155
3156                   var stringValue = new string (charArray);
3157                   return result.Success (stringValue);
3158               };
3159            return function;
3160        }
3161
3162        static object TransformObjects (object[] objects)
3163        {
3164            object result = objects;
3165            TransformObjects (objects, ref result);
3166            return result;
3167        }
3168
3169        static object TransformObject (Tuple<string, object>[] properties)
3170        {
3171            object result = properties;
3172            TransformObject (properties, ref result);
3173            return result;
3174        }
3175
3176        static JsonSerializer ()
3177        {
3178            // Language spec at www.json.org
3179
3180            // ReSharper disable InconsistentNaming
3181            Func<char, Parser<Empty>> p_char = CharParser.SkipChar;
3182            Func<string, Parser<Empty>> p_str = CharParser.SkipString;
3183
3184            var p_spaces = CharParser.SkipWhiteSpace ();
3185
3186            const string expected_bool    = "bool"    ;
3187            const string expected_string  = "string"  ;
3188            const string expected_number  = "number"  ;
3189            const string expected_null    = "null"    ;
3190
3191            var p_null     = p_str ("null").Map (null as object);
3192            var p_true     = p_str ("true").Map (true as object);
3193            var p_false    = p_str ("false").Map (false as object);
3194            var p_number   = CharParser.Double ().Map (d => d as object);
3195
3196            const string simpleEscape = "\"\\/bfnrt";
3197            const string simpleEscapeMap = "\"\\/\b\f\n\r\t";
3198            Debug.Assert (simpleEscape.Length == simpleEscapeMap.Length);
3199
3200            var simpleSwitchCases = simpleEscape
3201               .Zip (
3202                  simpleEscapeMap,
3203                  (l, r) => Parser.Case (l.ToString (s_cultureInfo), Parser.Return (new StringPart (r)))
3204                  );
3205
3206            var otherSwitchCases =
3207               new[]
3208               {
3209                  Parser.Case (
3210                     "u",
3211                     CharParser
3212                        .Hex (minCount: 4, maxCount: 4)
3213                        .Map (ui => new StringPart ((char) ui)))
3214               };
3215
3216            var switchCases = simpleSwitchCases.Concat (otherSwitchCases).ToArray ();
3217
3218            var p_escape = Parser.Switch (
3219               Parser.SwitchCharacterBehavior.Consume,
3220               switchCases
3221               );
3222
3223            var p_string = Parser
3224               .Choice (
3225                  CharParser.NoneOf ("\\\"", minCount: 1).Map (ss => new StringPart (ss.Position, ss.Length)),
3226                  CharParser.SkipChar ('\\').KeepRight (p_escape))
3227               .Many ()
3228               .Between (
3229                  p_char ('"'),
3230                  p_char ('"')
3231                  )
3232               .CombineStringParts ();
3233
3234            var p_array_redirect = Parser.Redirect<object>();
3235            var p_object_redirect = Parser.Redirect<object>();
3236
3237            var p_array = p_array_redirect.Parser;
3238            var p_object = p_object_redirect.Parser;
3239
3240            // .Switch is used as we can tell by looking at the first character which parser to use
3241           var p_value = Parser
3242               .Switch (
3243                  Parser.SwitchCharacterBehavior.Leave,
3244                  Parser.Case ("\""             , p_string.Map (v => v as object), expected_string ),
3245                  Parser.Case ("-0123456789"    , p_number                       , expected_number ),
3246                  Parser.Case ("{"              , p_object                                         ),
3247                  Parser.Case ("["              , p_array                                          ),
3248                  Parser.Case ("t"              , p_true                         , expected_bool   ),
3249                  Parser.Case ("f"              , p_false                        , expected_bool   ),
3250                  Parser.Case ("n"              , p_null                         , expected_null   )
3251                  )
3252               .KeepLeft (p_spaces);
3253
3254            var p_elements = p_value
3255               .Array (p_char (',')
3256               .KeepLeft (p_spaces))
3257               .Map (TransformObjects);
3258
3259            p_array_redirect.ParserRedirect = p_elements
3260               .Between (
3261                  p_char ('[').KeepLeft (p_spaces),
3262                  p_char (']')
3263                  );
3264
3265            var p_member = Parser
3266               .Group (
3267                  p_string.KeepLeft (p_spaces),
3268                  p_char (':').KeepLeft (p_spaces).KeepRight (p_value)
3269                  );
3270
3271            var p_members = p_member
3272               .Array (p_char (',')
3273               .KeepLeft (p_spaces));
3274
3275            p_object_redirect.ParserRedirect = p_members
3276               .Between (
3277                  p_char ('{').KeepLeft (p_spaces),
3278                  p_char ('}')
3279                  )
3280               .Map (TransformObject);
3281
3282            var p_eos = Parser.EndOfStream ();
3283
3284            // .Switch is used as we can tell by looking at the first character which parser to use
3285            var p_root = Parser
3286               .Switch (
3287                  Parser.SwitchCharacterBehavior.Leave,
3288                  Parser.Case ("{", p_object),
3289                  Parser.Case ("[", p_array)
3290                  )
3291               .KeepLeft (p_spaces);
3292
3293            s_parser = p_spaces.KeepRight (p_root).KeepLeft (p_spaces).KeepLeft (p_eos);
3294
3295            // ReSharper restore InconsistentNaming
3296        }
3297
3298        public static object Unserialize (string str)
3299        {
3300            var result = Parser.Parse (s_parser, str);
3301
3302            return result.IsSuccessful ? result.Value : new JsonUnserializeError (result.ErrorMessage, result.Unconsumed.Begin);
3303        }
3304
3305        static readonly CultureInfo s_cultureInfo = CultureInfo.InvariantCulture;
3306
3307        static void SerializeImpl (StringBuilder stringBuilder, object dyn)
3308        {
3309            if (dyn is double)
3310            {
3311                stringBuilder.Append (((double)dyn).ToString (s_cultureInfo));
3312            }
3313            else if (dyn is int)
3314            {
3315                stringBuilder.Append (((int)dyn).ToString (s_cultureInfo));
3316            }
3317            else if (dyn is string)
3318            {
3319                SerializeStringValue (stringBuilder, (string)dyn);
3320            }
3321            else if (dyn is bool)
3322            {
3323                if ((bool)dyn)
3324                {
3325                    stringBuilder.Append ("true");
3326                }
3327                else
3328                {
3329                    stringBuilder.Append ("false");
3330                }
3331            }
3332            else if (dyn is IDictionary<string, object>)
3333            {
3334                var dictionary = dyn as IDictionary<string, object>;
3335
3336                stringBuilder.Append ('{');
3337
3338                var first = true;
3339
3340                foreach (var kv in dictionary)
3341                {
3342                    if (first)
3343                    {
3344                        first = false;
3345                    }
3346                    else
3347                    {
3348                        stringBuilder.Append (',');
3349                    }
3350
3351                    SerializeStringValue (stringBuilder, kv.Key);
3352                    stringBuilder.Append (':');
3353                    SerializeImpl (stringBuilder, kv.Value);
3354                }
3355
3356                stringBuilder.Append ('}');
3357            }
3358            else if (dyn is IEnumerable)
3359            {
3360                var enumerable = (IEnumerable)dyn;
3361
3362                stringBuilder.Append ('[');
3363
3364                var first = true;
3365
3366                foreach (var obj in enumerable)
3367                {
3368                    if (first)
3369                    {
3370                        first = false;
3371                    }
3372                    else
3373                    {
3374                        stringBuilder.Append (',');
3375                    }
3376
3377                    SerializeImpl (stringBuilder, obj);
3378                }
3379
3380                stringBuilder.Append (']');
3381            }
3382            else
3383            {
3384                stringBuilder.Append ("null");
3385            }
3386        }
3387
3388        static void SerializeStringValue (StringBuilder stringBuilder, string str)
3389        {
3390            stringBuilder.Append ('"');
3391            foreach (var ch in str)
3392            {
3393                switch (ch)
3394                {
3395                    case '\b':
3396                        stringBuilder.Append ("\\b");
3397                        break;
3398                    case '\f':
3399                        stringBuilder.Append ("\\f");
3400                        break;
3401                    case '\n':
3402                        stringBuilder.Append ("\\n");
3403                        break;
3404                    case '\r':
3405                        stringBuilder.Append ("\\r");
3406                        break;
3407                    case '\t':
3408                        stringBuilder.Append ("\\t");
3409                        break;
3410                    default:
3411                        stringBuilder.Append (ch);
3412                        break;
3413                }
3414            }
3415            stringBuilder.Append ('"');
3416        }
3417
3418        public static string Serialize (object dyn)
3419        {
3420            var sb = new StringBuilder (32);
3421
3422            SerializeImpl (sb, dyn);
3423
3424            return sb.ToString ();
3425        }
3426
3427    }
3428
3429}
3430// ----------------------------------------------------------------------------------------------
3431// Copyright (c) Mårten Rånge.
3432// ----------------------------------------------------------------------------------------------
3433// This source code is subject to terms and conditions of the Microsoft Public License. A 
3434// copy of the license can be found in the License.html file at the root of this distribution. 
3435// If you cannot locate the  Microsoft Public License, please send an email to 
3436// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
3437//  by the terms of the Microsoft Public License.
3438// ----------------------------------------------------------------------------------------------
3439// You must not remove this notice, or any other, from this software.
3440// ----------------------------------------------------------------------------------------------
3441#if MICRO_PARSER_JSON_MAKE_PUBLIC
3442namespace MicroParser.Json
3443{
3444   public partial class JsonUnserializeError
3445   {
3446
3447   }
3448
3449   public partial class JsonSerializer
3450   {
3451   }
3452}
3453#endif
3454// ----------------------------------------------------------------------------------------------
3455// Copyright (c) Mårten Rånge.
3456// ----------------------------------------------------------------------------------------------
3457// This source code is subject to terms and conditions of the Microsoft Public License. A 
3458// copy of the license can be found in the License.html file at the root of this distribution. 
3459// If you cannot locate the  Microsoft Public License, please send an email to 
3460// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
3461//  by the terms of the Microsoft Public License.
3462// ----------------------------------------------------------------------------------------------
3463// You must not remove this notice, or any other, from this software.
3464// ----------------------------------------------------------------------------------------------
3465#if MICRO_PARSER_JSON_EXPANDO_OBJECT
3466namespace MicroParser.Json
3467{
3468    using System;
3469    using System.Collections.Generic;
3470    using System.Dynamic;
3471
3472    partial class JsonSerializer
3473    {
3474        static partial void TransformObject (Tuple<string, object>[] properties, ref object result)
3475        {
3476            IDictionary<string, object> expando = new ExpandoObject ();
3477            foreach (var p in properties)
3478            {
3479                expando[p.Item1 ?? ""] = p.Item2;
3480            }
3481            result = expando;
3482        }
3483    }
3484}
3485#endif