// ugly, but fast (as little additions to hashset as possible) private static void bufferCombinedLookaheads(Dictionary <Production <SYMBOL_ENUM, TREE_NODE>, Dictionary <int, SymbolChunkSet <SYMBOL_ENUM> > > precomputedRhsFirsts, Production <SYMBOL_ENUM, TREE_NODE> production, int rhsSeenCount, SymbolChunkSet <SYMBOL_ENUM> afterLookaheads, int lookaheadWidth, List <SymbolChunk <SYMBOL_ENUM> > buffer ) { int count = buffer.Count; foreach (SymbolChunk <SYMBOL_ENUM> chunk in precomputedRhsFirsts[production][rhsSeenCount].Chunks) { if (chunk.Count == lookaheadWidth) { buffer.Add(chunk); } else { buffer.AddRange(SymbolChunkSet.MultiConcat(chunk, afterLookaheads, lookaheadWidth)); } } if (buffer.Count == count) { buffer.AddRange(afterLookaheads.Chunks); } }
public static IEnumerable <uint> MultiConcat <SYMBOL_ENUM>(uint chunk1, SymbolChunkSet <SYMBOL_ENUM> set2, int lookaheadWidth) where SYMBOL_ENUM : struct { foreach (uint chunk2 in set2.Chunks) { yield return(Concat(chunk1, chunk2, lookaheadWidth)); } }
private static SymbolChunkSet <SYMBOL_ENUM> computeCombinedLookaheads(Dictionary <Production <SYMBOL_ENUM, TREE_NODE>, Dictionary <int, SymbolChunkSet <SYMBOL_ENUM> > > precomputedRhsFirsts, Production <SYMBOL_ENUM, TREE_NODE> production, int rhsSeenCount, SymbolChunkSet <SYMBOL_ENUM> afterLookaheads, int lookaheadWidth ) { var buffer = new List <SymbolChunk <SYMBOL_ENUM> >(Math.Max(afterLookaheads.Count, precomputedRhsFirsts[production][rhsSeenCount].Count) + 1); bufferCombinedLookaheads(precomputedRhsFirsts, production, rhsSeenCount, afterLookaheads, lookaheadWidth, buffer); return(new SymbolChunkSet <SYMBOL_ENUM>(buffer)); }
private static string dumpSymbolChunkSet(SymbolChunkSet <int> set, string symbolTypeName, Func <int, string> symbolNameConvert) { if (set == null || set.IsEmpty) { return(null); } else { return(CodeWords.New + " SymbolChunkSet<" + symbolTypeName + ">(" + set.Chunks.Select(chunk => "SymbolChunk.Create(" + chunk.Symbols.Select(s => symbolNameConvert(s)).Join(",") + ")").Join(",") + ")"); } }
internal bool Add(SYMBOL_ENUM symbol, SymbolChunkSet <SYMBOL_ENUM> set, SYMBOL_ENUM source) { bool change = false; foreach (SymbolChunk <SYMBOL_ENUM> chunk in set.Chunks) { if (!covers[symbol].ContainsKey(chunk)) { covers[symbol].Add(chunk, source); change = true; } } return(change); }
internal static ReductionAction <SYMBOL_ENUM, TREE_NODE> Create <SYMBOL_ENUM, TREE_NODE>(SingleState <SYMBOL_ENUM, TREE_NODE> state, CoverSets <SYMBOL_ENUM> coverSets, HorizonSets <SYMBOL_ENUM> horizonSets) where SYMBOL_ENUM : struct where TREE_NODE : class { SymbolChunkSet <SYMBOL_ENUM> cover = coverSets[state.LhsSymbol]; SymbolChunkSet <SYMBOL_ENUM> horizon = horizonSets[state.LhsSymbol]; // if we have internal conflict between symbols, we cannot use horizon data (because we couldn't tell if we reached horizon) bool use_horizon = !horizon.IsEmpty && !cover.Overlaps(horizon); var action = new ReductionAction <SYMBOL_ENUM, TREE_NODE>(state.CreateCell(), use_horizon ? horizon : null, use_horizon ? new SymbolChunkSet <SYMBOL_ENUM>() : null); return(action); }
private void bootstrapFromFirstSets(SYMBOL_ENUM symbol) { SymbolChunkSet <SYMBOL_ENUM> follow_set = followSets[symbol]; // in all RHS of productions find our symbol foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.ProductionsWithNoErrorSymbol()) { for (int i = 0; i < prod.RhsSymbols.Count(); ++i) { // we are above our symbol on RHS of the production if (prod.RhsSymbols[i].Equals(symbol)) { // get first set of what can happen AFTER our symbol -- this will be follow set by definition SymbolChunkSet <SYMBOL_ENUM> chunk_set = firstSets.GetFirstsOf(prod.RhsSymbols.Skip(i + 1), terminals, syntaxErrorSymbol, lookaheadWidth); { SymbolChunkSet <SYMBOL_ENUM> tmp = new SymbolChunkSet <SYMBOL_ENUM>(); // add LHS non-terminal at the end of too short chunks as generator // because what follows LHS also follows given symbol foreach (SymbolChunk <SYMBOL_ENUM> chunk in chunk_set.Chunks) { if (chunk.Count < lookaheadWidth) { tmp.Add(chunk.Append(prod.LhsNonTerminal)); } else { tmp.Add(chunk); } } chunk_set = tmp; } if (chunk_set.IsEmpty) { chunk_set.Add(SymbolChunk.Create(prod.LhsNonTerminal)); } follow_set.Add(chunk_set); } } } }
public static IEnumerable <uint> MultiConcat <SYMBOL_ENUM>(uint chunk, SymbolChunkSet <SYMBOL_ENUM> tailSet, int limitLength) where SYMBOL_ENUM : struct { if (SymbolChunkTraits.Count(chunk) >= limitLength) { yield return(SymbolChunkTraits.GetFirsts(chunk, limitLength)); } else { foreach (uint tail_chunk in tailSet.Chunks) { yield return(SymbolChunkTraits.Concat(chunk, tail_chunk, limitLength)); } } }
private void bootstrapFromFirstSets(SYMBOL_ENUM symbol) { SymbolChunkSet <SYMBOL_ENUM> current_set = horizonSets[symbol]; // in all RHS of productions find our symbol foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.Entries) { if (symbol.Equals(prod.LhsNonTerminal) || coverSets[symbol].Contains(SymbolChunk.Create(prod.LhsNonTerminal))) { continue; } for (int i = 0; i < prod.RhsSymbols.Count(); ++i) { // we are on our symbol on RHS of the production if (prod.RhsSymbols[i].Equals(symbol)) { // get first set of what can happen AFTER our symbol -- this will be our horizon SymbolChunkSet <SYMBOL_ENUM> src_set = firstSets.GetFirstsOf(prod.RhsSymbols.Skip(i + 1), terminals, syntaxErrorSymbol, lookaheadWidth); SymbolChunkSet <SYMBOL_ENUM> chunk_set = new SymbolChunkSet <SYMBOL_ENUM>(); // add follow set at the end of too short chunks foreach (SymbolChunk <SYMBOL_ENUM> chunk in src_set.Chunks) { if (chunk.Count < lookaheadWidth) { chunk_set.Add(SymbolChunkSet.MultiConcat(chunk, followSets[prod.LhsNonTerminal], lookaheadWidth)); } else { chunk_set.Add(chunk); } } if (chunk_set.IsEmpty) { chunk_set.Add(followSets[prod.LhsNonTerminal]); } current_set.Add(chunk_set); } } } }
public SymbolChunkSet <SYMBOL_ENUM> GetFirstsOf(IEnumerable <SYMBOL_ENUM> symbols, IEnumerable <SYMBOL_ENUM> terminals, SYMBOL_ENUM errorSymbol, int lookaheadWidth) { var sets = new List <SymbolChunkSet <SYMBOL_ENUM> >(); SYMBOL_ENUM?last = null; foreach (SYMBOL_ENUM sym in symbols.Reverse()) { if (!sym.Equals(errorSymbol)) { sets.Add(this[sym]); } else { sets.Add(SymbolChunkSet.MultiplyUpTo(terminals.Except(new[] { last.Value }), lookaheadWidth)); } last = sym; } sets.Reverse(); return(SymbolChunkSet.MultiConcat(sets.ToArray(), lookaheadWidth)); }
private void resolveFollowSetsDependencies() { bool changed = true; while (changed) { changed = false; foreach (SymbolChunkSet <SYMBOL_ENUM> fset in followSets.Values) { // only empty sets or without generators if (fset.Chunks.All(chunk => !chunk.Symbols.Any() || !nonTerminals.Contains(chunk.Symbols.Last()))) { continue; } var replacement = new SymbolChunkSet <SYMBOL_ENUM>(); foreach (SymbolChunk <SYMBOL_ENUM> chunk in fset.Chunks) { if (!chunk.Symbols.Any() || !nonTerminals.Contains(chunk.Symbols.Last())) { replacement.Add(chunk); } else { replacement.Add(SymbolChunkSet.MultiConcat(chunk.SkipLast(), followSets[chunk.Symbols.Last()], lookaheadWidth)); } } if (fset.Equals(replacement)) { continue; } fset.Assign(replacement); changed = true; } } }
private CoverSets <SYMBOL_ENUM> initCoverSets() { var cover_sets = new CoverSets <SYMBOL_ENUM>(); foreach (SYMBOL_ENUM sym in terminals) { var set = new SymbolChunkSet <SYMBOL_ENUM>(); set.Add(SymbolChunk.Create(sym)); cover_sets.Add(sym, set, sym); } // fill non terminals with everything found in the productions, terminals will stay as they are added here // non terminals will serve as generators foreach (SYMBOL_ENUM non_term in nonTerminals) { var set = new SymbolChunkSet <SYMBOL_ENUM>(); foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.FilterByLhs(non_term)) { foreach (SYMBOL_ENUM sym in prod.RhsSymbols) { // if we have error symbol inside production it means LHS cover all non-terminals, because // error symbol for that LHS covers everything except what stands after error symbol (stop marker) // thus, everything except stop marker plus stop marker gives --> everything if (sym.Equals(syntaxErrorSymbol)) { set.Add(terminals.Select(it => SymbolChunk.Create(it))); } else { set.Add(SymbolChunk.Create(sym)); } } } cover_sets.Add(non_term, set, non_term); } return(cover_sets); }
private void initFirstSets() { firstSets = new FirstSets <SYMBOL_ENUM>(lookaheadWidth); foreach (SYMBOL_ENUM sym in terminals) { var set = new SymbolChunkSet <SYMBOL_ENUM>(); set.Add(SymbolChunk.Create(sym)); firstSets.Add(sym, set); } foreach (SYMBOL_ENUM sym in nonTerminals) { var set = new SymbolChunkSet <SYMBOL_ENUM>(); // iterate over all productions for this symbol except for error recovery productions foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions .FilterByLhs(sym) .Where(it => !it.RhsSymbols.Contains(syntaxErrorSymbol))) { // we take only terminals from front IEnumerable <SYMBOL_ENUM> first_chunk = prod.RhsSymbols.TakeWhile(it => terminals.Contains(it)); int count = first_chunk.Count(); if (count >= lookaheadWidth) // we have more than enough { set.Add(SymbolChunk.Create(first_chunk.Take(lookaheadWidth))); } // we have less, but there was no more here else if (count == prod.RhsSymbols.Count) { set.Add(SymbolChunk.Create(first_chunk)); } } firstSets.Add(sym, set); } }
private SymbolChunkSet <SYMBOL_ENUM> coverAsChunkSet(SYMBOL_ENUM symbol) { return(SymbolChunkSet.Create(covers[symbol].Keys)); }
public static ReductionAction <SYMBOL_ENUM, TREE_NODE> Create <SYMBOL_ENUM, TREE_NODE>(NfaCell <SYMBOL_ENUM, TREE_NODE> cell, SymbolChunkSet <SYMBOL_ENUM> acceptHorizon, SymbolChunkSet <SYMBOL_ENUM> rejectHorizon) where SYMBOL_ENUM : struct where TREE_NODE : class { return(new ReductionAction <SYMBOL_ENUM, TREE_NODE>(cell, acceptHorizon, rejectHorizon)); }
public void Add(SYMBOL_ENUM symbol, SymbolChunkSet <SYMBOL_ENUM> set) { sets.Add(symbol, set); }