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); }
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] }); } } } }