//rekurzivně projde ještě neexistující graf stavů automatu; nové vrcholy objevuje zkoumáním //ItemSetu private void exploreTransitions(State thisState) { //symboly, jež příslušejí hranám vedoucím z tohoto stavu IEnumerable <int> appropriateSymbols = (from item in thisState.ItemSet where !item.IsFinal select item.Production.RHSSymbols[item.Position]).Distinct(); foreach (int symbol in appropriateSymbols) { ItemSet successorIS = thisState.ItemSet.NucleusAfterTransition(symbol); successorIS.CloseItemSet(grammar); //podíváme se, jestli jsme na stav s tímto ItemSetem už nenarazili int successorIndex; for (successorIndex = 0; successorIndex < parserStates.Count; successorIndex++) { if (successorIS.SetEquals(parserStates[successorIndex].ItemSet)) { break; } } State successorState; if (successorIndex == parserStates.Count) { successorState = new State(successorIndex, successorIS); parserStates.Add(successorState); exploreTransitions(successorState); } else { successorState = parserStates[successorIndex]; } Transition newTransition; if (symbol < grammar.NumTerminals) { newTransition = new TerminalTransition(thisState, successorState, symbol); } else { newTransition = new NonterminalTransition(thisState, successorState, symbol, numNonterminalTransitions++); } thisState.Transitions.Add(newTransition); successorState.AccessingStates.Add(thisState); if (newTransition is NonterminalTransition) { transitionsByNonterminals[symbol - grammar.NumTerminals].Add(newTransition as NonterminalTransition); } } }
private void printSymbolExplanations(State state, Item finalItem, BitVectorSet conflictSymbols, TextWriter writer) { //Vyrazíme ze všech vrcholů (vrcholy jsou tady neterminální hrany automatu) //ležících v lookback(state, finalItem), které mají ve follow množině nějaký konfliktní symbol. //Prohledáváním do hloubkyv grafu relace 'includes' najdeme nejbližší vrcholy, které mají v Read //množinách dohromady všechny hledané konfliktní symboly. Posléze vyrazíme z těchto nalezených vrcholů, //tentokrát po hranách relace 'reads' a budeme hledat nejbližší vrcholy, které mají v Direct Read množinách //dohromady všechny hledané symboly. Z posledně nalezených vrcholů už jsme vždy schopni vystopovat //cestu zpět přes reads, includes a lookback hrany až k původnímu konfliktnímu itemu. //pole předků a značky u navštívených vrcholů pro oba grafy NonterminalTransition[] includesPredecessors = new NonterminalTransition[numNonterminalTransitions]; bool[] includesExplored = new bool[numNonterminalTransitions]; NonterminalTransition[] readsPredecessors = new NonterminalTransition[numNonterminalTransitions]; bool[] readsExplored = new bool[numNonterminalTransitions]; BitVectorSet symbolsLeftToExplain = new BitVectorSet(conflictSymbols); //BFS fronty pro oba průchody obou grafů Queue <NonterminalTransition> includesTransitions = new Queue <NonterminalTransition>(); Queue <NonterminalTransition> readsTransitions = new Queue <NonterminalTransition>(); //vrcholy, které mají v DR množinách konfliktní symboly List <NonterminalTransition> rootTransitions = new List <NonterminalTransition>(); //procházení po lookback hranách foreach (NonterminalTransition trans in lookback(state, finalItem)) { if (!follow[getTransNumber(trans)].IsDisjointWith(conflictSymbols)) { includesTransitions.Enqueue(trans); includesExplored[getTransNumber(trans)] = true; } } //průchod přes includes hrany while ((includesTransitions.Count > 0) && (!symbolsLeftToExplain.IsEmpty())) { NonterminalTransition trans = includesTransitions.Dequeue(); BitVectorSet readSet = read[getTransNumber(trans)]; if (!readSet.IsDisjointWith(symbolsLeftToExplain)) { BitVectorSet symbolsJustExplained = readSet.GetIntersectionWith(symbolsLeftToExplain); symbolsLeftToExplain -= symbolsJustExplained; readsTransitions.Enqueue(trans); readsExplored[getTransNumber(trans)] = true; } foreach (NonterminalTransition next in includes.GetNeighboursFor(trans)) { if (!includesExplored[getTransNumber(next)]) { includesPredecessors[getTransNumber(next)] = trans; includesExplored[getTransNumber(next)] = true; includesTransitions.Enqueue(next); } } } //reset hledaných symbolů a průchod přes reads hrany symbolsLeftToExplain = new BitVectorSet(conflictSymbols); while ((readsTransitions.Count > 0) && (!symbolsLeftToExplain.IsEmpty())) { NonterminalTransition trans = readsTransitions.Dequeue(); BitVectorSet DRSet = initDR(trans); if (!DRSet.IsDisjointWith(symbolsLeftToExplain)) { BitVectorSet symbolsJustExplained = DRSet.GetIntersectionWith(symbolsLeftToExplain); symbolsLeftToExplain -= symbolsJustExplained; rootTransitions.Add(trans); } foreach (NonterminalTransition next in reads.GetNeighboursFor(trans)) { if (!readsExplored[getTransNumber(next)]) { readsPredecessors[getTransNumber(next)] = trans; readsExplored[getTransNumber(next)] = true; readsTransitions.Enqueue(next); } } } //teď už jen vystopujeme všechny potřebné cesty z neterminální hrany, která obsahovala konfliktní //symbol ve své DR množině, až k itemu, kde tímto symbolem přispěla a způsobila konflikt foreach (NonterminalTransition root in rootTransitions) { Stack <NonterminalTransition> readsPath = new Stack <NonterminalTransition>(); Stack <NonterminalTransition> includesPath = new Stack <NonterminalTransition>(); NonterminalTransition trans = root; while (readsPredecessors[getTransNumber(trans)] != null) { readsPath.Push(trans); trans = readsPredecessors[getTransNumber(trans)]; } while (includesPredecessors[getTransNumber(trans)] != null) { includesPath.Push(trans); trans = includesPredecessors[getTransNumber(trans)]; } writer.Write("({0}, ", state.StateNumber); printItemHTML(finalItem, conflictSymbols, writer); writer.Write(") <b><i>lookback</i></b> (<a href=\"#State{0}\">{0}</a>, {1})", trans.Source.StateNumber, getSymbolPrintName(trans.TransitionSymbol)); foreach (NonterminalTransition transition in includesPath) { writer.Write(" <b><i>includes</i></b> (<a href=\"#State{0}\">{0}</a>, {1})", transition.Source.StateNumber, getSymbolPrintName(transition.TransitionSymbol)); } foreach (NonterminalTransition transition in readsPath) { writer.Write(" <b><i>reads</i></b> (<a href=\"#State{0}\">{0}</a>, {1})", transition.Source.StateNumber, getSymbolPrintName(transition.TransitionSymbol)); } writer.Write(" and {"); StringBuilder explainedSymbolsString = new StringBuilder(); foreach (int explainedSymbol in initDR(root).GetIntersectionWith(conflictSymbols)) { explainedSymbolsString.AppendFormat("<span style=\"color:red\">{0}</span>, ", getSymbolPrintName(explainedSymbol)); } explainedSymbolsString.Remove(explainedSymbolsString.Length - 2, 2); writer.Write(explainedSymbolsString.ToString()); writer.Write("} ⊂ <b>DR</b>(" + root.Source.StateNumber.ToString() + ", " + getSymbolPrintName(root.TransitionSymbol) + ")"); writer.WriteLine("<br>"); } }
private void printSymbolExplanations(State state, Item finalItem, BitVectorSet conflictSymbols, TextWriter writer) { //Vyrazíme ze všech vrcholů (vrcholy jsou tady neterminální hrany automatu) //ležících v lookback(state, finalItem), které mají ve follow množině nějaký konfliktní symbol. //Prohledáváním do hloubkyv grafu relace 'includes' najdeme nejbližší vrcholy, které mají v Read //množinách dohromady všechny hledané konfliktní symboly. Posléze vyrazíme z těchto nalezených vrcholů, //tentokrát po hranách relace 'reads' a budeme hledat nejbližší vrcholy, které mají v Direct Read množinách //dohromady všechny hledané symboly. Z posledně nalezených vrcholů už jsme vždy schopni vystopovat //cestu zpět přes reads, includes a lookback hrany až k původnímu konfliktnímu itemu. //pole předků a značky u navštívených vrcholů pro oba grafy NonterminalTransition[] includesPredecessors = new NonterminalTransition[numNonterminalTransitions]; bool[] includesExplored = new bool[numNonterminalTransitions]; NonterminalTransition[] readsPredecessors = new NonterminalTransition[numNonterminalTransitions]; bool[] readsExplored = new bool[numNonterminalTransitions]; BitVectorSet symbolsLeftToExplain = new BitVectorSet(conflictSymbols); //BFS fronty pro oba průchody obou grafů Queue<NonterminalTransition> includesTransitions = new Queue<NonterminalTransition>(); Queue<NonterminalTransition> readsTransitions = new Queue<NonterminalTransition>(); //vrcholy, které mají v DR množinách konfliktní symboly List<NonterminalTransition> rootTransitions = new List<NonterminalTransition>(); //procházení po lookback hranách foreach (NonterminalTransition trans in lookback(state, finalItem)) { if (!follow[getTransNumber(trans)].IsDisjointWith(conflictSymbols)) { includesTransitions.Enqueue(trans); includesExplored[getTransNumber(trans)] = true; } } //průchod přes includes hrany while ((includesTransitions.Count > 0) && (!symbolsLeftToExplain.IsEmpty())) { NonterminalTransition trans = includesTransitions.Dequeue(); BitVectorSet readSet = read[getTransNumber(trans)]; if (!readSet.IsDisjointWith(symbolsLeftToExplain)) { BitVectorSet symbolsJustExplained = readSet.GetIntersectionWith(symbolsLeftToExplain); symbolsLeftToExplain -= symbolsJustExplained; readsTransitions.Enqueue(trans); readsExplored[getTransNumber(trans)] = true; } foreach (NonterminalTransition next in includes.GetNeighboursFor(trans)) if (!includesExplored[getTransNumber(next)]) { includesPredecessors[getTransNumber(next)] = trans; includesExplored[getTransNumber(next)] = true; includesTransitions.Enqueue(next); } } //reset hledaných symbolů a průchod přes reads hrany symbolsLeftToExplain = new BitVectorSet(conflictSymbols); while ((readsTransitions.Count > 0) && (!symbolsLeftToExplain.IsEmpty())) { NonterminalTransition trans = readsTransitions.Dequeue(); BitVectorSet DRSet = initDR(trans); if (!DRSet.IsDisjointWith(symbolsLeftToExplain)) { BitVectorSet symbolsJustExplained = DRSet.GetIntersectionWith(symbolsLeftToExplain); symbolsLeftToExplain -= symbolsJustExplained; rootTransitions.Add(trans); } foreach (NonterminalTransition next in reads.GetNeighboursFor(trans)) if (!readsExplored[getTransNumber(next)]) { readsPredecessors[getTransNumber(next)] = trans; readsExplored[getTransNumber(next)] = true; readsTransitions.Enqueue(next); } } //teď už jen vystopujeme všechny potřebné cesty z neterminální hrany, která obsahovala konfliktní //symbol ve své DR množině, až k itemu, kde tímto symbolem přispěla a způsobila konflikt foreach (NonterminalTransition root in rootTransitions) { Stack<NonterminalTransition> readsPath = new Stack<NonterminalTransition>(); Stack<NonterminalTransition> includesPath = new Stack<NonterminalTransition>(); NonterminalTransition trans = root; while (readsPredecessors[getTransNumber(trans)] != null) { readsPath.Push(trans); trans = readsPredecessors[getTransNumber(trans)]; } while (includesPredecessors[getTransNumber(trans)] != null) { includesPath.Push(trans); trans = includesPredecessors[getTransNumber(trans)]; } writer.Write("({0}, ", state.StateNumber); printItemHTML(finalItem, conflictSymbols, writer); writer.Write(") <b><i>lookback</i></b> (<a href=\"#State{0}\">{0}</a>, {1})", trans.Source.StateNumber, getSymbolPrintName(trans.TransitionSymbol)); foreach (NonterminalTransition transition in includesPath) writer.Write(" <b><i>includes</i></b> (<a href=\"#State{0}\">{0}</a>, {1})", transition.Source.StateNumber, getSymbolPrintName(transition.TransitionSymbol)); foreach (NonterminalTransition transition in readsPath) writer.Write(" <b><i>reads</i></b> (<a href=\"#State{0}\">{0}</a>, {1})", transition.Source.StateNumber, getSymbolPrintName(transition.TransitionSymbol)); writer.Write(" and {"); StringBuilder explainedSymbolsString = new StringBuilder(); foreach (int explainedSymbol in initDR(root).GetIntersectionWith(conflictSymbols)) explainedSymbolsString.AppendFormat("<span style=\"color:red\">{0}</span>, ", getSymbolPrintName(explainedSymbol)); explainedSymbolsString.Remove(explainedSymbolsString.Length - 2, 2); writer.Write(explainedSymbolsString.ToString()); writer.Write("} ⊂ <b>DR</b>(" + root.Source.StateNumber.ToString() + ", " + getSymbolPrintName(root.TransitionSymbol) + ")"); writer.WriteLine("<br>"); } }