using System; namespace Sprache { partial class Parse { /// /// Construct a parser that indicates that the given parser /// is optional. The returned parser will succeed on /// any input no matter whether the given parser /// succeeds or not. /// /// The result type of the given parser. /// The parser to wrap. /// An optional version of the given parser. public static Parser> Optional(this Parser parser) { if (parser == null) throw new ArgumentNullException(nameof(parser)); return i => { var pr = parser(i); if (pr.WasSuccessful) return Result.Success(new Some(pr.Value), pr.Remainder); return Result.Success(new None(), i); }; } /// /// Constructs the eXclusive version of the Optional{T} parser. /// /// The result type of the given parser /// The parser to wrap /// An eXclusive optional version of the given parser. /// public static Parser> XOptional(this Parser parser) { if (parser == null) throw new ArgumentNullException(nameof(parser)); return i => { var result = parser(i); if (result.WasSuccessful) return Result.Success(new Some(result.Value), result.Remainder); if (result.Remainder.Equals(i)) return Result.Success(new None(), i); return Result.Failure>(result.Remainder, result.Message, result.Expectations); }; } /// /// Construct a parser that indicates that the given parser is optional /// and non-consuming. The returned parser will succeed on /// any input no matter whether the given parser succeeds or not. /// In any case, it won't consume any input, like a positive look-ahead in regex. /// /// The result type of the given parser. /// The parser to wrap. /// A non-consuming version of the given parser. public static Parser> Preview(this Parser parser) { if (parser == null) throw new ArgumentNullException(nameof(parser)); return i => { var result = parser(i); if (result.WasSuccessful) return Result.Success(new Some(result.Value), i); return Result.Success(new None(), i); }; } } }