Beispiel #1
0
        public virtual MatchResult <TInput, TResult> GetMatch(
            MatchState <TInput, TResult> state,
            Action <MatchState <TInput, TResult>, int, IEnumerable <MatchItem <TInput, TResult> > > production,
            int index)
        {
            if (state == null)
            {
                throw new ArgumentNullException("state");
            }
            if (production == null)
            {
                throw new ArgumentNullException("production");
            }

            MatchItem <TInput, TResult> result = null;

            if (BeforeMatch != null)
            {
                BeforeMatch(state, state.InputList, production);
            }

            try
            {
                if (Terminals == null)
                {
                    Terminals = new HashSet <string>();
                }

                result = _MemoCall(state, production.Method.Name, index, production, null);
            }
            catch (MatcherException me)
            {
                state.ClearErrors();
                state.AddError(me.Index, me.Message);
            }
            catch (Exception e)
            {
                state.ClearErrors();
                state.AddError(0, e.Message
#if DEBUG
                               + "\n" + e.StackTrace
#endif
                               );
            }

            state.ClearMemoTable(); // allow memo tables to be gc'd

            string GetLastError() => state.LastError;

            var match_result = result != null
                ? new MatchResult <TInput, TResult>(this, state, true, result.StartIndex, result.NextIndex, result.Results, GetLastError, state.LastErrorIndex)
                : new MatchResult <TInput, TResult>(this, state, false, -1, -1, null, GetLastError, state.LastErrorIndex);

            if (AfterMatch != null)
            {
                AfterMatch(match_result);
            }

            return(match_result);
        }
Beispiel #2
0
#pragma warning disable 0219
        /// <summary>
        /// Matches any input.
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="index">Index.</param>
        protected MatchItem <TInput, TResult> _ParseAny(MatchState <TInput, TResult> memo, ref int index)
        {
            if (!(memo.InputString != null && index >= memo.InputString.Length))
            {
                try
                {
                    var _temp  = memo.InputList != null ? memo.InputList[index] : memo.InputEnumerable.ElementAt(index);
                    var result = new MatchItem <TInput, TResult>
                    {
                        StartIndex      = index,
                        NextIndex       = index + 1,
                        InputEnumerable = memo.InputEnumerable,
                    };

                    ++index;
                    memo.Results.Push(result);
                    return(result);
                }
                catch { }
            }

            memo.Results.Push(null);
            memo.AddError(index, () => "unexpected end of file");
            return(null);
        }
Beispiel #3
0
        /// <summary>
        /// Matches a set of characters.  Only used for matchers over <c>char</c> enumerables.
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="index">Index.</param>
        /// <param name="chars">Characters to match.</param>
        protected MatchItem <TInput, TResult> _ParseInputClass(MatchState <TInput, TResult> memo, ref int index, params char[] chars)
        {
            if (!(memo.InputString != null && index >= memo.InputString.Length))
            {
                try
                {
                    TInput input = memo.InputList != null ? memo.InputList[index] : memo.InputEnumerable.ElementAt(index);
                    if (Array.IndexOf(chars, input) != -1)
                    {
                        var result = new MatchItem <TInput, TResult>
                        {
                            StartIndex      = index,
                            NextIndex       = index + 1,
                            InputEnumerable = memo.InputEnumerable,
                        };

                        ++index;
                        memo.Results.Push(result);
                        return(result);
                    }
                }
                catch { }
            }

            memo.Results.Push(null);
            //memo.AddError(index, () => "expected one of [" + Regex.Escape(new string(chars)) + "]");
            return(null);
        }
Beispiel #4
0
        /// <summary>
        /// Matches a literal char (only used with matchers on a <c>char</c> enumerable).
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="index">Index.</param>
        /// <param name="ch">Character to match.</param>
        protected MatchItem <TInput, TResult> _ParseLiteralChar(MatchState <TInput, TResult> memo, ref int index, char ch)
        {
            if (!(memo.InputString != null && index >= memo.InputString.Length))
            {
                try
                {
                    char cur_ch = memo.InputString != null ? memo.InputString[index] : (char)(object)memo.InputEnumerable.ElementAt(index);
                    if (cur_ch == ch)
                    {
                        var result = new MatchItem <TInput, TResult>
                        {
                            StartIndex      = index,
                            NextIndex       = index + 1,
                            InputEnumerable = memo.InputEnumerable,
                        };

                        ++index;
                        memo.Results.Push(result);
                        return(result);
                    }
                }
                catch { }
            }

            memo.Results.Push(null);
            //memo.AddError(index, () => string.Format("expected '{0}'", Regex.Escape(new string(ch, 1))));
            return(null);
        }
Beispiel #5
0
        /// <summary>
        /// Find the memo of a given rule call.
        /// </summary>
        /// <param name="expansion">The production expansion.</param>
        /// <param name="index">The input position.</param>
        /// <param name="item">The result.</param>
        /// <returns>True if there is a memo record for the rule at the index.</returns>
        public bool TryGetMemo(Expansion expansion, int index, out MatchItem <TInput, TResult> item)
        {
            Dictionary <int, Dictionary <int, MatchItem <TInput, TResult> > > expansion_dict;
            Dictionary <int, MatchItem <TInput, TResult> > rule_dict;

            if (memo_table.TryGetValue(expansion.Name, out expansion_dict) &&
                expansion_dict.TryGetValue(expansion.Num, out rule_dict) &&
                rule_dict.TryGetValue(index, out item))
            {
                return(true);
            }

            item = default(MatchItem <TInput, TResult>);
            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Matches a literal string (only used with matchers on a <c>char</c> enumerable).
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="index">Index.</param>
        /// <param name="str">String to match.</param>
        protected MatchItem <TInput, TResult> _ParseLiteralString(MatchState <TInput, TResult> memo, ref int index, string str)
        {
            int  cur_index = index;
            bool failed    = false;

            try
            {
                foreach (var ch in str)
                {
                    if (memo.InputString != null && cur_index >= memo.InputString.Length)
                    {
                        failed = true;
                        break;
                    }

                    char cur_ch = memo.InputString != null ? memo.InputString[cur_index] : (char)(object)memo.InputEnumerable.ElementAt(cur_index);
                    ++cur_index;

                    if (cur_ch != ch)
                    {
                        failed = true;
                        break;
                    }
                }
            }
            catch
            {
                failed = true;
            }

            if (!failed)
            {
                var result = new MatchItem <TInput, TResult>
                {
                    StartIndex      = index,
                    NextIndex       = cur_index,
                    InputEnumerable = memo.InputEnumerable
                };
                index = cur_index;
                memo.Results.Push(result);
                return(result);
            }

            memo.Results.Push(null);
            //memo.AddError(index, () => "expected \"" + Regex.Escape(str) + "\"");
            return(null);
        }
Beispiel #7
0
        /// <summary>
        /// Try to match the input.
        /// </summary>
        /// <param name="input">The input to be matched.</param>
        /// <param name="production">The top-level grammar production (rule) of the generated parser class to use.</param>
        /// <returns>The result of the match.</returns>
        public virtual MatchResult <TInput, TResult> GetMatch(IEnumerable <TInput> input, Action <Memo <TInput, TResult>, int, IEnumerable <MatchItem <TInput, TResult> > > production)
        {
            var memo = new Memo <TInput, TResult>(input);
            MatchItem <TInput, TResult> result = null;

            if (BeforeMatch != null)
            {
                BeforeMatch(memo, input, production);
            }

            try
            {
                if (Terminals == null)
                {
                    Terminals = new HashSet <string>();
                }

                result = _MemoCall(memo, production.Method.Name, 0, production, null);
            }
            catch (MatcherException me)
            {
                memo.ClearErrors();
                memo.AddError(me.Index, me.Message);
            }
            catch (Exception e)
            {
                memo.ClearErrors();
                memo.AddError(0, e.Message
#if DEBUG
                              + "\n" + e.StackTrace
#endif
                              );
            }

            memo.ClearMemoTable(); // allow memo tables to be gc'd

            var match_result = result != null
                ? new MatchResult <TInput, TResult>(this, memo, true, result.StartIndex, result.NextIndex, result.Results, memo.LastError, memo.LastErrorIndex)
                : new MatchResult <TInput, TResult>(this, memo, false, -1, -1, null, memo.LastError, memo.LastErrorIndex);

            if (AfterMatch != null)
            {
                AfterMatch(match_result);
            }

            return(match_result);
        }
Beispiel #8
0
        /// <summary>
        /// Matches a set of characters in an argument stream.
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="item_index">Item index.</param>
        /// <param name="input_index">Input index.</param>
        /// <param name="args">Argument stream.</param>
        /// <param name="chars">Characters to match.</param>
        protected MatchItem <TInput, TResult> _ParseInputClassArgs(MatchState <TInput, TResult> memo, ref int item_index, ref int input_index, IEnumerable <MatchItem <TInput, TResult> > args, params char[] chars)
        {
            try
            {
                int cur_item_index  = item_index;
                int cur_input_index = input_index;

                var    cur_item  = args.ElementAt(cur_item_index);
                TInput cur_input = cur_item.Inputs.ElementAt(cur_input_index);

                if (Array.IndexOf(chars, cur_input) != -1)
                {
                    if (cur_input_index + 1 >= cur_item.Inputs.Count())
                    {
                        ++cur_item_index;
                        cur_input_index = 0;
                    }
                    else
                    {
                        ++cur_input_index;
                    }

                    var result = new MatchItem <TInput, TResult>
                    {
                        StartIndex = item_index,
                        NextIndex  = cur_item_index,
                        Inputs     = new List <TInput> {
                            cur_input
                        },
                    };

                    item_index  = cur_item_index;
                    input_index = cur_input_index;

                    memo.ArgResults.Push(result);
                    return(result);
                }
            }
            catch { }

            memo.ArgResults.Push(null);
            //memo.AddError(input_index, () => "expected " + args);
            return(null);
        }
Beispiel #9
0
        /// <summary>
        /// Memoize the result of a production at a given index.
        /// </summary>
        /// <param name="expansion">The production expansion.</param>
        /// <param name="index">The input position.</param>
        /// <param name="item">The result of the parse.</param>
        public void Memoize(Expansion expansion, int index, MatchItem <TInput, TResult> item)
        {
            Dictionary <int, Dictionary <int, MatchItem <TInput, TResult> > > expansion_dict;

            if (!memo_table.TryGetValue(expansion.Name, out expansion_dict))
            {
                expansion_dict = new Dictionary <int, Dictionary <int, MatchItem <TInput, TResult> > >();
                memo_table.Add(expansion.Name, expansion_dict);
            }

            Dictionary <int, MatchItem <TInput, TResult> > rule_dict;

            if (!expansion_dict.TryGetValue(expansion.Num, out rule_dict))
            {
                rule_dict = new Dictionary <int, MatchItem <TInput, TResult> >();
                expansion_dict.Add(expansion.Num, rule_dict);
            }

            rule_dict[index] = item;
        }
Beispiel #10
0
        protected MatchItem <TInput, TResult> _ParseRegexp(MatchState <TInput, TResult> memo, ref int index, Verophyle.Regexp.StringRegexp re)
        {
            int cur_index  = index;
            int succ_index = -1;

            try
            {
                re.Reset();
                do
                {
                    re.ProcessInput(memo.InputString[cur_index]);
                    if (re.Succeeded)
                    {
                        succ_index = cur_index;
                    }
                }while (++cur_index < memo.InputString.Length && !re.Failed);
            }
            catch
            {
                succ_index = -1;
            }

            if (succ_index >= 0)
            {
                var result = new MatchItem <TInput, TResult>
                {
                    StartIndex      = index,
                    NextIndex       = succ_index + 1,
                    InputEnumerable = memo.InputEnumerable
                };
                index = succ_index + 1;
                memo.Results.Push(result);
                return(result);
            }
            else
            {
                memo.Results.Push(null);
                return(null);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Matches a literal object in an argument stream.
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="item_index">Item index.</param>
        /// <param name="input_index">Input index.</param>
        /// <param name="obj">Object to match.</param>
        /// <param name="args">Argument stream.</param>
        protected MatchItem <TInput, TResult> _ParseLiteralArgs(MatchState <TInput, TResult> memo, ref int item_index, ref int input_index, object obj, IEnumerable <MatchItem <TInput, TResult> > args)
        {
            if (args != null)
            {
                try
                {
                    if (obj is IEnumerable <TInput> )
                    {
                        int old_item_index  = item_index;
                        int cur_item_index  = item_index;
                        int cur_input_index = input_index;

                        var input_list = new List <TInput>();

                        foreach (TInput input in ((IEnumerable <TInput>)obj))
                        {
                            var    cur_item  = args.ElementAt(cur_item_index);
                            TInput cur_input = cur_item.Inputs.ElementAt(cur_input_index);

                            if (ObjectEquals(input, cur_input))
                            {
                                input_list.Add(cur_input);

                                if (cur_input_index + 1 >= cur_item.Inputs.Count())
                                {
                                    ++cur_item_index;
                                    cur_input_index = 0;
                                }
                                else
                                {
                                    ++input_index;
                                }
                            }
                            else
                            {
                            }
                        }

                        //
                        item_index  = cur_item_index;
                        input_index = cur_input_index;

                        var result = new MatchItem <TInput, TResult>
                        {
                            StartIndex = old_item_index,
                            NextIndex  = item_index,
                            Inputs     = input_list,
                        };

                        memo.ArgResults.Push(result);
                        return(result);
                    }
                    else
                    {
                        int old_item_index = item_index;

                        var    cur_item  = args.ElementAt(item_index);
                        TInput cur_input = cur_item.Inputs.ElementAt(input_index);

                        if (ObjectEquals(obj, cur_input))
                        {
                            // increment
                            if (input_index + 1 >= cur_item.Inputs.Count())
                            {
                                ++item_index;
                                input_index = 0;
                            }
                            else
                            {
                                ++input_index;
                            }

                            //
                            var result = new MatchItem <TInput, TResult>
                            {
                                StartIndex = old_item_index,
                                NextIndex  = item_index,
                                Inputs     = new List <TInput> {
                                    cur_input
                                },
                            };

                            memo.ArgResults.Push(result);
                            return(result);
                        }
                    }
                }
                catch { }
            }

            memo.ArgResults.Push(null);
            //memo.AddError(input_index, () => "expected " + obj);
            return(null);
        }
Beispiel #12
0
        /// <summary>
        /// Matches a literal object.
        /// </summary>
        /// <param name="memo">Memo.</param>
        /// <param name="index">Index.</param>
        /// <param name="obj">Object to match.</param>
        protected MatchItem <TInput, TResult> _ParseLiteralObj(MatchState <TInput, TResult> memo, ref int index, object obj)
        {
            if (obj is IEnumerable <TInput> )
            {
                int  cur_index = index;
                bool failed    = false;

                try
                {
                    foreach (var input in (IEnumerable <TInput>)obj)
                    {
                        TInput cur_input = memo.InputList != null ? memo.InputList[cur_index] : memo.InputEnumerable.ElementAt(cur_index);
                        ++cur_index;

                        if (!ObjectEquals(input, cur_input))
                        {
                            failed = true;
                            break;
                        }
                    }
                }
                catch
                {
                    failed = true;
                }

                if (!failed)
                {
                    var result = new MatchItem <TInput, TResult>
                    {
                        StartIndex      = index,
                        NextIndex       = cur_index,
                        InputEnumerable = memo.InputEnumerable,
                    };

                    memo.Results.Push(result);
                    index = cur_index;

                    return(result);
                }
            }
            else
            {
                try
                {
                    TInput cur_input = memo.InputList != null ? memo.InputList[index] : memo.InputEnumerable.ElementAt(index);

                    if (ObjectEquals(obj, cur_input))
                    {
                        var result = new MatchItem <TInput, TResult>
                        {
                            StartIndex      = index,
                            NextIndex       = index + 1,
                            InputEnumerable = memo.InputEnumerable,
                        };

                        memo.Results.Push(result);
                        ++index;

                        return(result);
                    }
                }
                catch { }
            }

            memo.Results.Push(null);
            //memo.AddError(index, () => "expected " + obj);
            return(null);
        }
Beispiel #13
0
 /// <summary>
 /// Utility function for getting the input that matched from a variable.
 /// </summary>
 /// <param name="item">Variable that matched.</param>
 /// <returns>The input that matched the variable, with whitspace trimmed.</returns>
 protected static string Trimmed(MatchItem <char, TResult> item)
 {
     return(new string(item.Inputs.ToArray()).Trim());
 }