/JsonVisualizer/Internal/IncludeMicroParser.Json.cs
C# | 3485 lines | 2662 code | 521 blank | 302 comment | 174 complexity | 8d37ca31b129a7bc9d59f00c4aac4129 MD5 | raw file
Large files files are truncated, but you can click here to view the full 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 errorMe…
Large files files are truncated, but you can click here to view the full file