Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Call a grammar production, using memoization and handling left-recursion.
        /// </summary>
        /// <param name="memo">The memo for the current match.</param>
        /// <param name="ruleName">The name of the production.</param>
        /// <param name="index">The current index in the input stream.</param>
        /// <param name="production">The production itself.</param>
        /// <param name="args">Arguments to the production (can be null).</param>
        /// <returns>The result of the production at the given input index.</returns>
        protected MatchItem <TInput, TResult> _MemoCall
        (
            MatchState <TInput, TResult> memo,
            string ruleName,
            int index,
            Action <MatchState <TInput, TResult>, int, IEnumerable <MatchItem <TInput, TResult> > > production,
            IEnumerable <MatchItem <TInput, TResult> > args
        )
        {
            MatchItem <TInput, TResult> result;

            var expansion = new Expansion
            {
                Name = args == null ? ruleName : ruleName + string.Join(", ", args.Select(arg => arg.ToString()).ToArray()),
                Num  = 0
            };

            // if we have a memo record, use that
            if (memo.TryGetMemo(expansion, index, out result))
            {
                memo.Results.Push(result);
                return(result);
            }

            // if we are not handling left recursion, just call the production directly.
            if (!HandleLeftRecursion || Terminals.Contains(ruleName))
            {
                production(memo, index, args);
                result = memo.Results.Peek();

                memo.Memoize(expansion, index, result);

                if (result == null)
                {
                    memo.AddError(index, () => "expected " + ruleName);
                }

                return(result);
            }

            // check for left-recursion
            LRRecord <MatchItem <TInput, TResult> > record;

            if (memo.TryGetLRRecord(expansion, index, out record))
            {
                record.LRDetected = true;

                var involved = memo.CallStack
                               .TakeWhile(rec => rec.CurrentExpansion.Name != expansion.Name)
                               .Select(rec => rec.CurrentExpansion.Name);

                if (record.InvolvedRules != null)
                {
                    record.InvolvedRules.UnionWith(involved);
                }
                else
                {
                    record.InvolvedRules = new HashSet <string>(involved);
                }

                if (!memo.TryGetMemo(record.CurrentExpansion, index, out result))
                {
                    throw new MatcherException(index, "Problem with expansion " + record.CurrentExpansion);
                }
                memo.Results.Push(result);
            }
            // no lr information
            else
            {
                record                  = new LRRecord <MatchItem <TInput, TResult> >();
                record.LRDetected       = false;
                record.NumExpansions    = 1;
                record.CurrentExpansion = new Expansion {
                    Name = expansion.Name, Num = record.NumExpansions
                };
                record.CurrentNextIndex = -1;

                memo.Memoize(record.CurrentExpansion, index, null);
                memo.StartLRRecord(expansion, index, record);

                memo.CallStack.Push(record);

                while (true)
                {
                    production(memo, index, args);
                    result = memo.Results.Pop();

                    // do we need to keep trying the expansions?
                    if (record.LRDetected && result != null && result.NextIndex > record.CurrentNextIndex)
                    {
                        record.NumExpansions    = record.NumExpansions + 1;
                        record.CurrentExpansion = new Expansion {
                            Name = expansion.Name, Num = record.NumExpansions
                        };
                        record.CurrentNextIndex = result != null ? result.NextIndex : 0;
                        memo.Memoize(record.CurrentExpansion, index, result);

                        record.CurrentResult = result;
                    }
                    // we are done trying to expand
                    else
                    {
                        if (record.LRDetected)
                        {
                            result = record.CurrentResult;
                        }

                        memo.ForgetLRRecord(expansion, index);
                        memo.Results.Push(result);

                        // if we are not involved in any left-recursion expansions above us, memoize
                        memo.CallStack.Pop();

                        bool found_lr = memo.CallStack.Any(rec => rec.InvolvedRules != null && rec.InvolvedRules.Contains(expansion.Name));
                        if (!found_lr)
                        {
                            memo.Memoize(expansion, index, result);
                        }

                        if (result == null)
                        {
                            memo.AddError(index, () => "expected " + expansion.Name);
                        }
                        break;
                    }
                }
            }

            return(result);
        }