Ejemplo n.º 1
0
        /// <summary>
        /// Refer to another parser indirectly. This allows circular compile-time dependency between parsers.
        /// </summary>
        /// <typeparam name="TToken"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="reference"></param>
        /// <returns></returns>
        public static Parser <TToken, T> Ref <TToken, T>(Func <Parser <TToken, T> > reference)
        {
            if (reference == null)
            {
                throw new ArgumentNullException(nameof(reference));
            }

            Parser <TToken, T> p = null;

            return(i =>
            {
                if (p == null)
                {
                    p = reference();
                }

                if (i.Memos.ContainsKey(p))
                {
                    throw new ParsingException(i.Memos[p].ToString());
                }

                i.Memos[p] = ParserResult <TToken, T> .Failure(i,
                                                               new string[0],
                                                               "Left recursion in the grammar."
                                                               );

                var result = p(i);
                i.Memos[p] = result;
                return result;
            });
        }
Ejemplo n.º 2
0
        public ParserResult <TToken, U> IfSuccess <U>(Func <ParserResult <TToken, TValue>, ParserResult <TToken, U> > next)
        {
            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            if (this.IsSuccess)
            {
                return(next(this));
            }

            return(ParserResult <TToken, U> .Failure(this.Rest, this.Expected, this.Description));
        }
Ejemplo n.º 3
0
        public static Parser <TToken, T> End <TToken, T>(this Parser <TToken, T> parser)
        {
            if (parser == null)
            {
                throw new ArgumentNullException(nameof(parser));
            }

            return(i => parser(i).IfSuccess(s =>
                                            s.Rest.AtEnd ? s : ParserResult <TToken, T> .Failure(
                                                s.Rest,
                                                new[] { "end of input" },
                                                string.Format("unexpected '{0}'", s.Rest.GetCurrent())
                                                )
                                            ));
        }
        public static Parser <ScriptToken, ScriptToken> ScriptToken(Func <int, bool> predicate, string expected)
        {
            return(i =>
            {
                if (i.AtEnd)
                {
                    return ParserResult <ScriptToken, ScriptToken> .Failure(i, new [] { expected }, "Unexpected end of input");
                }

                if (predicate(i.GetCurrent().Tag))
                {
                    return ParserResult <ScriptToken, ScriptToken> .Success(i.Advance(), i.GetCurrent());
                }
                return ParserResult <ScriptToken, ScriptToken> .Failure(i, $"Unexpected {i.GetCurrent()}");
            });
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Succeed if the parsed value matches predicate.
        /// </summary>
        /// <typeparam name="TToken"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="parser"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static Parser <TToken, T> Where <TToken, T>(this Parser <TToken, T> parser, Func <T, bool> predicate)
        {
            if (parser == null)
            {
                throw new ArgumentNullException(nameof(parser));
            }
            if (predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            return(i => parser(i).IfSuccess(s =>
                                            predicate(s.Value) ? s : ParserResult <TToken, T> .Failure(i,
                                                                                                       new string[0],
                                                                                                       string.Format("Unexpected {0}.", s.Value)
                                                                                                       )
                                            ));
        }
Ejemplo n.º 6
0
        public static ParserResult <TToken, T> DetermineBestError <TToken, T>(
            ParserResult <TToken, T> firstF,
            ParserResult <TToken, T> secondF
            )
        {
            if (secondF.Rest.Position > firstF.Rest.Position)
            {
                return(secondF);
            }

            if (secondF.Rest.Position == firstF.Rest.Position)
            {
                return(ParserResult <TToken, T> .Failure(
                           firstF.Rest,
                           firstF.Expected.Union(secondF.Expected),
                           firstF.Description
                           ));
            }

            return(firstF);
        }
Ejemplo n.º 7
0
        public static Parser <char, char> Char(Func <char, bool> predicate, string expected)
        {
            if (predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            return(i =>
            {
                if (i.AtEnd)
                {
                    return ParserResult <char, char> .Failure(i, new [] { expected }, "Unexpected end of input");
                }

                if (predicate(i.GetCurrent()))
                {
                    return ParserResult <char, char> .Success(i.Advance(), i.GetCurrent());
                }

                return ParserResult <char, char> .Failure(i, new [] { expected }, $"Unexpected '{i.GetCurrent()}'");
            });
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Attempt parsing only if the <paramref name="except"/> parser fails.
        /// </summary>
        /// <typeparam name="TToken"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="parser"></param>
        /// <param name="except"></param>
        /// <returns></returns>
        public static Parser <TToken, T> Except <TToken, T, U>(this Parser <TToken, T> parser, Parser <TToken, U> except)
        {
            if (parser == null)
            {
                throw new ArgumentNullException(nameof(parser));
            }
            if (except == null)
            {
                throw new ArgumentNullException(nameof(except));
            }

            // Could be more like: except.Then(s => s.Fail("..")).XOr(parser)
            return(i =>
            {
                var r = except(i);
                if (r.IsSuccess)
                {
                    return ParserResult <TToken, T> .Failure(i, new[] { "other than the excepted input" }, "Excepted parser succeeded.");
                }
                return parser(i);
            });
        }
Ejemplo n.º 9
0
        internal static ParserResult <ScriptToken, T> TryParse <T>(this Parser <ScriptToken, T> parser, Script input)
        {
            if (parser == null)
            {
                throw new System.ArgumentNullException(nameof(parser));
            }

            if (input == null)
            {
                throw new System.ArgumentNullException(nameof(input));
            }

            try
            {
                return(parser(new ScriptInput(input)));
            }
            // Catching exception here is bit ugly, but converting `Script` to `ScriptToken` is itself unsafe
            // so this is good for assuring purity of this method.
            catch (ParsingException e)
            {
                return(ParserResult <ScriptToken, T> .Failure(new ScriptInput(new ScriptToken[] {}), e.Message));
            }
        }