public void GenerateAutomaton() { SubProduction startingRule = Grammar.Instance.First(x => x.Identifier == ParserConstants.Initial).First(); GrammarSymbols = Grammar.Instance.Symbols(); Item startingItem = new Item(startingRule, 0, new HashSet <TerminalExpressionDefinition> { new TerminalExpressionDefinition { TokenType = TokenType.EndMarker } }); Initial = new ItemSet(new List <Item> { startingItem }).Closure(); CanonicalSets = Initial.GetCanonicalSets(GrammarSymbols); PropogateLookaheads(GrammarSymbols); }
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); }