// generator is the non-terminal placed at the end of the chunk // such non-terminal generates what can follow it, which can contain also non-terminal at the end // which generates... // ...until we get the length of required lookahead count public FollowSets <SYMBOL_ENUM> ComputeFollowSets() { followSets = new FollowSets <SYMBOL_ENUM>(lookaheadWidth); // fill all symbols with initially empty follow set foreach (SYMBOL_ENUM symbol in nonTerminals.Concat(terminals)) { followSets.Add(symbol, new SymbolChunkSet <SYMBOL_ENUM>()); } followSets[startSymbol].Add(SymbolChunk.CreateRepeat(eofSymbol, lookaheadWidth)); foreach (SYMBOL_ENUM symbol in nonTerminals.Concat(terminals)) { bootstrapFromFirstSets(symbol); } // each chunk can have only terminals, or terminals + 1 non terminal at the end (as FollowSet tail generator) resolveFollowSetsDependencies(); // removal of follow sets "generators" foreach (SymbolChunkSet <SYMBOL_ENUM> fset in followSets.Values) { fset.RemoveWhere(chunk => nonTerminals.Contains(chunk.Symbols.Last())); } return(followSets); }
public BuilderHorizonSets(Productions <SYMBOL_ENUM, TREE_NODE> productions, int lookaheadWidth, FirstSets <SYMBOL_ENUM> firstSets, CoverSets <SYMBOL_ENUM> coverSets, FollowSets <SYMBOL_ENUM> followSets) : base(productions, lookaheadWidth) { this.firstSets = firstSets; this.followSets = followSets; this.coverSets = coverSets; if (!coverSets.HasNonTerminals || lookaheadWidth != coverSets.LookaheadWidth) { throw new ArgumentException("Internal error."); } }