/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