Esempio n. 1
0
        /// <summary>
        /// p1.Or(p2) tries p1, but if it fails without consuming input, runs p2 instead.
        /// </summary>
        /// <typeparam name="T">The type of result object generated.</typeparam>
        /// <param name="p1">The first parser to run.</param>
        /// <param name="p2">The second parser to run.</param>
        /// <returns>Returns the combined parser function.</returns>
        internal static P <TInput, TValue> Or <TInput, TValue>(this P <TInput, TValue> p1, P <TInput, TValue> p2)
            where TInput : IComparable
        {
            return(input =>
            {
                Consumed <TInput, TValue> consumed1 = p1(input);

                if (consumed1.ParseResult.Succeeded || consumed1.HasConsumedInput)
                {
                    return consumed1;
                }
                else
                {
                    Consumed <TInput, TValue> consumed2 = p2(input);

                    if (consumed2.HasConsumedInput)
                    {
                        return consumed2;
                    }

                    return new Consumed <TInput, TValue>(
                        consumed2.HasConsumedInput,
                        consumed2.ParseResult.MergeError(consumed1.ParseResult.ErrorInfo));
                }
            });
        }
Esempio n. 2
0
        /// <summary>
        /// This function runs parser p1 on the input.  If it fails, return
        /// an empty Consumed.  If it succeeds, run the provided function on the result
        /// of the initial function.
        /// </summary>
        /// <typeparam name="TValue1">The type of result object generated by the first function.</typeparam>
        /// <typeparam name="TValue2">The type of result object generated by the second function.</typeparam>
        /// <param name="p1">The initial parser to run.</param>
        /// <param name="f">The function defining the second parser to run.</param>
        /// <returns>Returns the completely constructed parser.</returns>
        internal static P <TInput, TValue2> Then <TInput, TValue1, TValue2>(
            this P <TInput, TValue1> p1, Func <TValue1, P <TInput, TValue2> > f)
            where TInput : IComparable
        {
            return(input =>
            {
                Consumed <TInput, TValue1> consumed1 = p1(input);

                if (consumed1.ParseResult.Succeeded)
                {
                    Consumed <TInput, TValue2> consumed2 =
                        f(consumed1.ParseResult.Result)(consumed1.ParseResult.RemainingInput);

                    return new Consumed <TInput, TValue2>(
                        consumed1.HasConsumedInput || consumed2.HasConsumedInput,
                        consumed2.HasConsumedInput
                               ? consumed2.ParseResult
                               : consumed2.ParseResult.MergeError(consumed1.ParseResult.ErrorInfo));
                }
                else
                {
                    return new Consumed <TInput, TValue2>(
                        consumed1.HasConsumedInput,
                        new ParseResult <TInput, TValue2>(consumed1.ParseResult.ErrorInfo));
                }
            });
        }
Esempio n. 3
0
        /// <summary>
        /// p1.Or(p2) tries p1, but if it fails without consuming input, runs p2 instead.
        /// </summary>
        /// <typeparam name="T">The type of result object generated.</typeparam>
        /// <param name="p1">The first parser to run.</param>
        /// <param name="p2">The second parser to run.</param>
        /// <returns>Returns the combined parser function.</returns>
        internal static P <TokenTuple, T> Or <T>(this P <TokenTuple, T> p1, P <TokenTuple, T> p2)
        {
            return(input =>
            {
                Consumed <TokenTuple, T> consumed1 = p1(input);

                if (consumed1.ParseResult.Succeeded || consumed1.HasConsumedInput)
                {
                    return consumed1;
                }
                else
                {
                    Consumed <TokenTuple, T> consumed2 = p2(input);

                    if (consumed2.HasConsumedInput)
                    {
                        return consumed2;
                    }

                    return new Consumed <TokenTuple, T>(
                        consumed2.HasConsumedInput,
                        consumed2.ParseResult.MergeError(consumed1.ParseResult.ErrorInfo));
                }
            });
        }
Esempio n. 4
0
        /// <summary>
        /// If the parse succeeded and consumed input, create a token that indicates
        /// the result and contains the text and position of the consumed input.
        /// If the parse was not successful, returns a default TokenTuple
        /// (TokenType=None).
        /// </summary>
        /// <param name="newState">The state after a successful parse.</param>
        /// <param name="startingState">The state before the parse began.</param>
        /// <returns>Returns a TokenTuple containing the token type, text and position.</returns>
        internal static TokenTuple CreateToken(this Consumed <string, TokenType> newState,
                                               ParserState <string> startingState)
        {
            TokenTuple tok = default(TokenTuple);

            if ((newState.HasConsumedInput) && (newState.ParseResult.Succeeded))
            {
                tok.TokenType = newState.ParseResult.Result;
                tok.Position  = startingState.Position;
                tok.Text      = ConstructString(newState.InputConsumedSince(startingState));
            }

            return(tok);
        }
Esempio n. 5
0
        /// <summary>
        /// Try(p) attempts to run parser p.  If it fails, it pretends
        /// that it hasn't consumed any input.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p"></param>
        /// <returns></returns>
        internal static P <TInput, TValue> Try_ <TInput, TValue>(this P <TInput, TValue> p)
        {
            return(input =>
            {
                Consumed <TInput, TValue> consumed = p(input);

                if (consumed.HasConsumedInput && !consumed.ParseResult.Succeeded)
                {
                    return new Consumed <TInput, TValue>(false, consumed.ParseResult);
                }
                else
                {
                    return consumed;
                }
            });
        }
Esempio n. 6
0
        /// <summary>
        /// This function runs parser p1 on the input.  If it fails, return
        /// null.  If it succeeds, run the provided function on the result
        /// of the initial function.
        /// </summary>
        /// <typeparam name="T">The type of result object generated by the first function.</typeparam>
        /// <typeparam name="U">The type of result object generated by the second function.</typeparam>
        /// <param name="p1">The initial parser to run.</param>
        /// <param name="f">The function defining the second parser to run.</param>
        /// <returns>Returns the completely constructed parser.</returns>
        internal static P <TokenTuple, U> Then <T, U>(this P <TokenTuple, T> p1, Func <T, P <TokenTuple, U> > f)
        {
            return(input =>
            {
                Consumed <TokenTuple, T> consumed1 = p1(input);

                if (consumed1.ParseResult.Succeeded)
                {
                    Consumed <TokenTuple, U> consumed2 = f(consumed1.ParseResult.Result)(consumed1.ParseResult.RemainingInput);
                    return new Consumed <TokenTuple, U>(
                        consumed1.HasConsumedInput || consumed2.HasConsumedInput,
                        consumed2.HasConsumedInput
                               ? consumed2.ParseResult
                               : consumed2.ParseResult.MergeError(consumed1.ParseResult.ErrorInfo));
                }
                else
                {
                    return new Consumed <TokenTuple, U>(
                        consumed1.HasConsumedInput,
                        new ParseResult <TokenTuple, U>(consumed1.ParseResult.ErrorInfo));
                }
            });
        }
Esempio n. 7
0
 internal List <TInput> InputConsumedSince(Consumed <TInput, TValue> previousConsumedResult)
 {
     return(this.ParseResult.ConsumedInputSince(previousConsumedResult.ParseResult));
 }