Esempio n. 1
0
        /// <summary>
        /// Constructs a parser that will fail if the given parser succeeds,
        /// and will succeed if the given parser fails. In any case, it won't
        /// consume any input. It's like a negative look-ahead in regex.
        /// </summary>
        /// <typeparam name="T">The result type of the given parser</typeparam>
        /// <param name="parser">The parser to wrap</param>
        /// <returns>A parser that is the opposite of the given parser.</returns>
        public static Parser <object> Not <T>(this Parser <T> parser)
        {
            if (parser == null)
            {
                throw new ArgumentNullException(nameof(parser));
            }

            return(i =>
            {
                var result = parser(i);

                if (result.WasSuccessful)
                {
                    var msg = $"`{StringExtensions.Join(", ", result.Expectations)}' was not expected";
                    return Result.Failure <object>(i, msg, new string[0]);
                }
                return Result.Success <object>(null, i);
            });
        }
Esempio n. 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="parser"></param>
        /// <param name="minimumCount"></param>
        /// <param name="maximumCount"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static Parser <IEnumerable <T> > Repeat <T>(this Parser <T> parser, int minimumCount, int maximumCount)
        {
            if (parser == null)
            {
                throw new ArgumentNullException(nameof(parser));
            }

            return(i =>
            {
                var remainder = i;
                var result = new List <T>();

                for (var n = 0; n < maximumCount; ++n)
                {
                    var r = parser(remainder);

                    if (!r.WasSuccessful && n < minimumCount)
                    {
                        var what = r.Remainder.AtEnd
                                                        ? "end of input"
                                                        : r.Remainder.Current.ToString();

                        var msg = $"Unexpected '{what}'";
                        var exp = $"'{StringExtensions.Join(", ", r.Expectations)}' between {minimumCount} and {maximumCount} times, but found {n}";

                        return Result.Failure <IEnumerable <T> >(i, msg, new[] { exp });
                    }

                    if (!ReferenceEquals(remainder, r.Remainder))
                    {
                        result.Add(r.Value);
                    }

                    remainder = r.Remainder;
                }

                return Result.Success <IEnumerable <T> >(result, remainder);
            });
        }
Esempio n. 3
0
        /// <summary>
        /// Parses a single character except for those in the given parameters
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static Parser <char> CharExcept(IEnumerable <char> c)
        {
            var chars = c as char[] ?? c.ToArray();

            return(CharExcept(chars.Contains, StringExtensions.Join("|", chars)));
        }
Esempio n. 4
0
 /// <summary>
 /// Parses a single character except for those in c
 /// </summary>
 /// <param name="c"></param>
 /// <returns></returns>
 public static Parser <char> CharExcept(string c)
 {
     return(CharExcept(c.ToEnumerable().Contains, StringExtensions.Join("|", c.ToEnumerable())));
 }
Esempio n. 5
0
 /// <summary>
 /// Parse a single character of any in c
 /// </summary>
 /// <param name="c"></param>
 /// <returns></returns>
 public static Parser <char> Chars(params char[] c)
 {
     return(Char(c.Contains, StringExtensions.Join("|", c)));
 }