private bool Reduce(ActionParsingTableEntry entry)
        {
            SubProduction subProduction = null;

            if (entry.Items.Count > 1)
            {
                Item match = entry.Items.First(x => x.Lookahead.Any(x => x.TokenType == Current.Type));
                subProduction = match.SubProduction;
            }
            else
            {
                subProduction = entry.Items.First().SubProduction;
            }

            NonTerminalExpressionDefinition target = new NonTerminalExpressionDefinition {
                Identifier = subProduction.Production.Identifier
            };

            ParsingNode parsingNode = new ParsingNode()
            {
                Expression = new NonTerminalExpression
                {
                    Identifier = subProduction.Production.Identifier,
                },
                Parser        = this,
                SubProduction = subProduction
            };

            for (int y = subProduction.Count - 1; y >= 0; y--)
            {
                for (int i = ParsingNodes.Count - 1; i >= 0; i--)
                {
                    if (ParsingNodes[i].Parent != null)
                    {
                        continue;
                    }

                    if (ParsingNodes[i].Expression is NonTerminalExpression ne &&
                        subProduction[y] is NonTerminalExpressionDefinition ned)
                    {
                        if (ne.Identifier == ned.Identifier)
                        {
                            ParsingNodes[i].Expression.Key = ned.Key;
                            ParsingNodes[i].Parent         = parsingNode;
                            break;
                        }
                    }
                    if (ParsingNodes[i].Expression is TerminalExpression te &&
                        subProduction[y] is TerminalExpressionDefinition ted)
                    {
                        if (te.TokenType == ted.TokenType)
                        {
                            ParsingNodes[i].Parent = parsingNode;
                            break;
                        }
                    }
                }
            }

            ParsingNodes.Add(parsingNode);

            List <ExpressionDefinition> expressionDefinitionsToRemove = subProduction.Where(x => !(x is SemanticActionDefinition) && !(x is TerminalExpressionDefinition ted && ted.TokenType == TokenType.EmptyString)).ToList();

            for (int i = 0; i < expressionDefinitionsToRemove.Count(); i++)
            {
                Stack.RemoveAt(Stack.Count - 1);
            }

            ItemSet tos = Stack.Last();
            List <ParsingTableEntry> entries = ParsingTable.GetSegment(tos).Entries
                                               .Where(x => x is GotoParsingTableEntry g &&
                                                      g.ItemSet == tos &&
                                                      g.ExpressionDefinition.IsEqualTo(target)).ToList();

            if (entries.Count > 1)
            {
                throw new Exception();
            }

            GotoParsingTableEntry gotoEntry = (GotoParsingTableEntry)entries.First();

            if (DebugModeEnabled)
            {
                Console.WriteLine("REDUCE DEST " + gotoEntry.Destination.Id + ", TARGET " + target.ToString());
            }
            Stack.Add(gotoEntry.Destination);

            return(true);
        }
Esempio n. 2
0
        public ParsingTable(List <ItemSet> C,
                            List <ExpressionDefinition> symbols,
                            Func <ActionParsingTableEntry, bool> shift,
                            Func <ActionParsingTableEntry, bool> accept,
                            Func <ActionParsingTableEntry, bool> reduce)
        {
            Dictionary <string, ExpressionSet> follows = new Dictionary <string, ExpressionSet>();

            // Actions
            foreach (ItemSet set in C)
            {
                foreach (Item item in set)
                {
                    if (item.ExpressionAfterDot != null &&
                        item.ExpressionAfterDot is TerminalExpressionDefinition ted)
                    {
                        AddActionEntry(item, shift, "s", set, item.ExpressionAfterDot as TerminalExpressionDefinition);
                    }
                    else if (item.SubProduction.Production.Identifier == ParserConstants.Initial)
                    {
                        TerminalExpressionDefinition expressionDefinition = item.ExpressionAfterDot as TerminalExpressionDefinition;
                        expressionDefinition = expressionDefinition ?? new TerminalExpressionDefinition()
                        {
                            TokenType = TokenType.EndMarker
                        };

                        AddActionEntry(item, accept, "a", set, expressionDefinition);
                    }
                    else if (item.IsDotIndexAtEnd())
                    {
                        string        identifier = item.SubProduction.Production.Identifier;
                        ExpressionSet follow;

                        if (!follows.TryGetValue(identifier, out follow))
                        {
                            follow = new NonTerminalExpressionDefinition()
                            {
                                Identifier = identifier
                            }.Follow();
                            follows.Add(identifier, follow);
                        }

                        foreach (TerminalExpressionDefinition ted1 in follow)
                        {
                            AddActionEntry(item, reduce, "r", set, ted1);
                        }
                    }
                }
            }

            // Goto's
            foreach (ItemSet set in C)
            {
                foreach (NonTerminalExpressionDefinition symbol in symbols.Where(x => x is NonTerminalExpressionDefinition))
                {
                    if (set.Transitions.Any(x => x.Key.IsEqualTo(symbol)))
                    {
                        GetOrCreateSegment(set).Entries.Add(new GotoParsingTableEntry
                        {
                            ExpressionDefinition = symbol,
                            ItemSet     = set,
                            Destination = set.Transitions[symbol]
                        });
                    }
                }
            }
        }