Пример #1
0
        private static IEnumerable <IEnumerable <SYMBOL_ENUM> > unAliasProductionRhs(SYMBOL_ENUM symbol,
                                                                                     SYMBOL_ENUM[] expansion,
                                                                                     Production <SYMBOL_ENUM, TREE_NODE> production,
                                                                                     SYMBOL_ENUM startSymbol,
                                                                                     SYMBOL_ENUM syntaxErrorSymbol,
                                                                                     ref UnAliasing change)
        {
            if (production.RhsSymbols.All(it => !it.Equals(symbol)))
            {
                return new[] { production.RhsSymbols }
            }
            ;

            // todo: remove this condition when recovery points will be improved
            if (expansion.Length > 1 &&
                (production.LhsNonTerminal.Equals(startSymbol) || production.RhsSymbols.Any(it => it.Equals(syntaxErrorSymbol))))
            {
                change = UnAliasing.Forbidden;

                return(new[] { production.RhsSymbols });
            }

            change = UnAliasing.Expansion;

            // a lot of memory allocation, but code is much simpler than otherwise

            // for aliased symbol use its expansions, for others -- just the given symbol
            SYMBOL_ENUM[][] replacements = production.RhsSymbols.Select(it => it.Equals(symbol) ? expansion : new[] { it }).ToArray();
            CycleCounter[]  counters     = replacements.Select(it => CycleCounter.Create(it.Length)).ToArray();

            var result = new List <IEnumerable <SYMBOL_ENUM> >();

            do
            {
                // has to pin down collection to avoid local capture
                result.Add(replacements.SyncZip(counters).Select(it => it.Item1[it.Item2.Value]).ToArray());
            }while (counters.Iterate());

            return(result);
        }
Пример #2
0
        private static IEnumerable <Production <SYMBOL_ENUM, TREE_NODE> > unfoldIdentityProductions(StringRep <SYMBOL_ENUM> symbolsRep,
                                                                                                    IEnumerable <Production <SYMBOL_ENUM, TREE_NODE> > productions,
                                                                                                    SYMBOL_ENUM eofSymbol, SYMBOL_ENUM syntaxErrorSymbol)
        {
            var used_aliases = new HashSet <SYMBOL_ENUM>();

            while (true)
            {
                var result = new Productions <SYMBOL_ENUM, TREE_NODE>(symbolsRep, productions, eofSymbol, syntaxErrorSymbol, s => {});
                List <Production <SYMBOL_ENUM, TREE_NODE> > new_productions = null;

                CoverSets <SYMBOL_ENUM> cover_sets = new BuilderCoverSets <SYMBOL_ENUM, TREE_NODE>(result, lookaheadWidth: 1).ComputeCoverSets();
                foreach (SYMBOL_ENUM non_term in result.NonTerminals)
                {
                    if (!used_aliases.Contains(non_term) &&
                        !cover_sets.IsRecursive(non_term) &&
                        result.isAlias(non_term))
                    {
                        used_aliases.Add(non_term);

                        // todo: this won't work for multi-param alias rules
                        SYMBOL_ENUM[] expansions = result.FilterByLhs(non_term).Select(it => it.RhsSymbols.Single()).ToArray();
                        new_productions = new List <Production <SYMBOL_ENUM, TREE_NODE> >();
                        UnAliasing change = UnAliasing.NoChange;
                        foreach (Production <SYMBOL_ENUM, TREE_NODE> p in productions.Where(it => !it.LhsNonTerminal.Equals(non_term)))
                        {
                            new_productions.AddRange(
                                unAliasProductionRhs(non_term, expansions, p, result.StartSymbol, syntaxErrorSymbol, ref change)
                                .Select(rhs => new Production <SYMBOL_ENUM, TREE_NODE>(
                                            symbolsRep,
                                            p.LhsNonTerminal,
                                            p.Recursive,
                                            rhs,
                                            p.UserAction,
                                            // todo: this won't work for multi-param alias rules
                                            p.IdentityOuterFunctionParamIndex)));

                            // we need to break right-away, otherwise "change" variable could be changed in next expansion to "expanded"
                            if (change == UnAliasing.Forbidden)
                            {
                                break;
                            }
                        }

                        if (change == UnAliasing.Expansion)
                        {
                            break;
                        }
                        else
                        {
                            new_productions = null;
                        }
                    }
                }


                // all non terminals checked or productions were expanded
                if (new_productions == null)
                {
                    break;
                }
                else
                {
                    productions = new_productions;
                }
            }

            return(productions);
        }