Example #1
0
        private void printShiftReduceConflicts(TextWriter reportOutput)
        {
            foreach (State state in parserStates)
            {
                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    BitVectorSet shiftSymbols = new BitVectorSet(grammar.NumTerminals);
                    foreach (Transition trans in state.Transitions)
                    {
                        if (trans is TerminalTransition)
                        {
                            shiftSymbols.Add(trans.TransitionSymbol);
                        }
                    }

                    BitVectorSet reduceSymbols = new BitVectorSet(grammar.NumTerminals);
                    foreach (BitVectorSet lookaheadSet in lookaheadSets[stateLookaheadIndex[state.StateNumber]])
                    {
                        reduceSymbols.UnionWith(lookaheadSet);
                    }

                    foreach (int terminal in shiftSymbols.GetIntersectionWith(reduceSymbols))
                    {
                        reportOutput.WriteLine("Warning: shift/reduce conflict in state {0} on symbol '{1}'.",
                                               state.StateNumber, grammar.SymbolNames[terminal]);
                    }
                }
            }
        }
Example #2
0
        private void printItemHTML(Item item, BitVectorSet conflictSymbols, TextWriter writer)
        {
            writer.Write(getSymbolPrintName(item.Production.LHSSymbol));
            writer.Write(" ::=");

            for (int i = 0; i < item.Production.RHSSymbols.Count; i++)
            {
                if (i == item.Position)
                {
                    writer.Write(" ·");
                    if ((item.Production.RHSSymbols[i] < grammar.NumTerminals) &&
                        conflictSymbols.Contains(item.Production.RHSSymbols[i]))
                    {
                        writer.Write(" <span style=\"color:red\">{0}</span>", getSymbolPrintName(item.Production.RHSSymbols[i]));
                    }
                    else
                    {
                        writer.Write(" " + getSymbolPrintName(item.Production.RHSSymbols[i]));
                    }
                }
                else
                {
                    writer.Write(" " + getSymbolPrintName(item.Production.RHSSymbols[i]));
                }
            }

            if (item.IsFinal)
            {
                writer.Write(" ·");
            }
        }
Example #3
0
        //tenhle overload se volá po posledním výpočtu lookaheadů, kde jsme ochotni tolerovat i shift/reduce
        //konflikty, kde budeme preferovat shift; proto tento overload zjišťuje, zda se v daném automatu
        //nacházejí i reduce/reduce konflikty, se kterými už bychom si neuměli rozumně poradit
        private bool checkForConflicts(LookaheadComplexity lastStage, out bool reduceReduceConflictsInAutomaton)
        {
            bool conflictsInAutomaton = false;

            reduceReduceConflictsInAutomaton = false;

            foreach (State state in parserStates)
            {
                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    BitVectorSet accumulator       = new BitVectorSet(grammar.NumTerminals);
                    BitVectorSet reduceAccumulator = new BitVectorSet(grammar.NumTerminals);

                    foreach (Transition trans in state.Transitions)
                    {
                        if (trans is TerminalTransition)
                        {
                            accumulator.Add(trans.TransitionSymbol);
                        }
                    }

                    bool conflictsInThisState = false;

                    foreach (BitVectorSet lookaheadSet in lookaheadSets[stateLookaheadIndex[state.StateNumber]])
                    {
                        if (!reduceAccumulator.IsDisjointWith(lookaheadSet))
                        {
                            conflictsInThisState             = true;
                            reduceReduceConflictsInAutomaton = true;
                            break;
                        }
                        else
                        {
                            if (!accumulator.IsDisjointWith(lookaheadSet))
                            {
                                conflictsInThisState = true;
                            }

                            reduceAccumulator.UnionWith(lookaheadSet);
                        }
                    }

                    if (conflictsInThisState)
                    {
                        conflictsInAutomaton = true;
                    }
                    else
                    {
                        numInconsistentStates--;
                        stateResolvedAt[state.StateNumber] = lastStage;
                    }
                }
            }

            return(conflictsInAutomaton);
        }
Example #4
0
        //projde všechny dosud nevyřešené stavy a podívá se, jestli byla minulá fáze výpočtu dostatečná
        //na to, aby rozřešila konflikty, které se v nich objevují; parametr lastStage popisuje, jak vypadala
        //poslední fáze výpočtu a můžeme tak pro diagnostické důvody sledovat, které stavy jsou vyřešeny
        //v kterém stádiu výpočtu
        private bool checkForConflicts(LookaheadComplexity lastStage)
        {
            bool conflictsInAutomaton = false;

            foreach (State state in parserStates)
            {
                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    BitVectorSet accumulator = new BitVectorSet(grammar.NumTerminals);

                    //inicializujeme akumulační proměnnou na množinu terminálů, které v daném stavu můžeme přečíst
                    foreach (Transition trans in state.Transitions)
                    {
                        if (trans is TerminalTransition)
                        {
                            accumulator.Add(trans.TransitionSymbol);
                        }
                    }

                    bool conflictsInThisState = false;

                    //akumulační proměnná prochází kolem všech lookahead množin a testuje se s nimi na disjunktnost,
                    //sama potom přebírá jejich prvky (nemusíme tak testovat každou dvojici množin)
                    foreach (BitVectorSet lookaheadSet in lookaheadSets[stateLookaheadIndex[state.StateNumber]])
                    {
                        if (!accumulator.IsDisjointWith(lookaheadSet))
                        {
                            conflictsInThisState = true;
                            break;
                        }
                        else
                        {
                            accumulator.UnionWith(lookaheadSet);
                        }
                    }

                    if (conflictsInThisState)
                    {
                        conflictsInAutomaton = true;
                    }
                    else
                    {
                        numInconsistentStates--;
                        stateResolvedAt[state.StateNumber] = lastStage;
                    }
                }
            }

            return(conflictsInAutomaton);
        }
Example #5
0
        private void printLookahead(BitVectorSet lookaheadSet, BitVectorSet conflictSymbols, TextWriter writer)
        {
            StringBuilder lookaheadSetString = new StringBuilder();
            lookaheadSetString.Append('{');
            foreach (int lookaheadSymbol in lookaheadSet)
            {
                if (conflictSymbols.Contains(lookaheadSymbol))
                    lookaheadSetString.AppendFormat("<span style=\"color:red\">{0}</span>", getSymbolPrintName(lookaheadSymbol));
                else
                    lookaheadSetString.Append(getSymbolPrintName(lookaheadSymbol));
                lookaheadSetString.Append(", ");
            }
            lookaheadSetString.Remove(lookaheadSetString.Length - 2, 2);
            lookaheadSetString.Append('}');

            writer.Write(lookaheadSetString.ToString());
        }
Example #6
0
        private void printShiftReduceConflicts(TextWriter reportOutput)
        {
            foreach (State state in parserStates)
                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    BitVectorSet shiftSymbols = new BitVectorSet(grammar.NumTerminals);
                    foreach (Transition trans in state.Transitions)
                        if (trans is TerminalTransition)
                            shiftSymbols.Add(trans.TransitionSymbol);

                    BitVectorSet reduceSymbols = new BitVectorSet(grammar.NumTerminals);
                    foreach (BitVectorSet lookaheadSet in lookaheadSets[stateLookaheadIndex[state.StateNumber]])
                        reduceSymbols.UnionWith(lookaheadSet);

                    foreach (int terminal in shiftSymbols.GetIntersectionWith(reduceSymbols))
                        reportOutput.WriteLine("Warning: shift/reduce conflict in state {0} on symbol '{1}'.",
                            state.StateNumber, grammar.SymbolNames[terminal]);
                }
        }
Example #7
0
        private void printLookahead(BitVectorSet lookaheadSet, BitVectorSet conflictSymbols, TextWriter writer)
        {
            StringBuilder lookaheadSetString = new StringBuilder();

            lookaheadSetString.Append('{');
            foreach (int lookaheadSymbol in lookaheadSet)
            {
                if (conflictSymbols.Contains(lookaheadSymbol))
                {
                    lookaheadSetString.AppendFormat("<span style=\"color:red\">{0}</span>", getSymbolPrintName(lookaheadSymbol));
                }
                else
                {
                    lookaheadSetString.Append(getSymbolPrintName(lookaheadSymbol));
                }
                lookaheadSetString.Append(", ");
            }
            lookaheadSetString.Remove(lookaheadSetString.Length - 2, 2);
            lookaheadSetString.Append('}');

            writer.Write(lookaheadSetString.ToString());
        }
Example #8
0
        private void printItemHTML(Item item, BitVectorSet conflictSymbols, TextWriter writer)
        {
            writer.Write(getSymbolPrintName(item.Production.LHSSymbol));
            writer.Write(" ::=");

            for (int i = 0; i < item.Production.RHSSymbols.Count; i++)
            {
                if (i == item.Position)
                {
                    writer.Write(" ·");
                    if ((item.Production.RHSSymbols[i] < grammar.NumTerminals) &&
                         conflictSymbols.Contains(item.Production.RHSSymbols[i]))
                        writer.Write(" <span style=\"color:red\">{0}</span>", getSymbolPrintName(item.Production.RHSSymbols[i]));
                    else
                        writer.Write(" " + getSymbolPrintName(item.Production.RHSSymbols[i]));
                }
                else
                    writer.Write(" " + getSymbolPrintName(item.Production.RHSSymbols[i]));
            }

            if (item.IsFinal)
                writer.Write(" ·");
        }
Example #9
0
        /// <summary>
        /// Computes the ParseTable and GotoTable of a Grammar's ParserData, logging the automata's graph
        /// to a logfile should the <i>grammar</i> prove to be non-LALR(1) or should the caller explicitly
        /// state he wants a log. Any reports generated by the processor will be sent to the <i>reportOutput</i>
        /// TextWriter instance.
        /// </summary>
        /// <param name="grammar">The Grammar whose tables are to be computed. GrammarDefinition ought to be
        /// set and filled with appropriate data and ParserData should be initialized.</param>
        /// <param name="logfileName">The name of the file to which the automaton is to be logged; <b>null</b>
        /// if logging should be disabled.</param>
        /// <param name="explicitLogging">A Boolean value determining whether the automaton should be
        /// written to the logfile even though there are no inconsistencies.</param>
        /// <param name="reportOutput">The TextWriter to which the report should be written; <b>null</b>
        /// if reporting should be disabled.</param>
        public void ComputeTables(Grammar grammar, string logfileName, bool explicitLogging, TextWriter reportOutput)
        {
            // INICIALIZACE

            this.grammar = grammar;

            //inicializace a výpočet productionsByRHSNonterminals
            productionsByRHSNonterminals = new List <Production> [grammar.GrammarDefinition.NumNonterminals];
            for (int nonterminal = 0; nonterminal < productionsByRHSNonterminals.Length; nonterminal++)
            {
                productionsByRHSNonterminals[nonterminal] = new List <Production>();
            }

            foreach (Production production in grammar.Productions)
            {
                foreach (int rhsSymbol in production.RHSSymbols)
                {
                    if (rhsSymbol >= grammar.NumTerminals)
                    {
                        productionsByRHSNonterminals[rhsSymbol - grammar.NumTerminals].Add(production);
                    }
                }
            }

            //inicializace transitionsByNonterminals, hodnoty jsou do seznamů posléze nasázeny ve funkci
            //exploreTransitions, která zároveň vyrábí LR(0) automat
            transitionsByNonterminals = new List <NonterminalTransition> [grammar.NumNonterminals];
            for (int nonterminal = 0; nonterminal < grammar.NumNonterminals; nonterminal++)
            {
                transitionsByNonterminals[nonterminal] = new List <NonterminalTransition>();
            }

            numNonterminalTransitions = 0;

            conflictingItems = new List <List <Item> >();
            lookaheadSets    = new List <List <BitVectorSet> >();


            parserStates = new List <State>();

            // TVORBA LR(0) AUTOMATU

            //vytvoříme počáteční ItemSet a nastartujeme rekurzivní
            //exploreTransitions

            Item    startItem = new Item(grammar.Productions[0], 0);
            ItemSet startIS   = new ItemSet();

            startIS.Add(startItem);
            startIS.CloseItemSet(grammar);

            State initialState = new State(0, startIS);

            parserStates.Add(initialState);

            //spočítá nám parserStates, hrany mezi nimi, nonterminalTransitions (počet neterminálních hran)
            //a transitionsByNonterminals
            exploreTransitions(initialState);


            //tenhle kousek inicializace si musel počkat na dopočítání stavů automatu
            stateLookaheadIndex = new int[parserStates.Count];
            for (int i = 0; i < parserStates.Count; i++)
            {
                stateLookaheadIndex[i] = -1;
            }

            //původní hodnota Look
            stateResolvedAt = new LookaheadComplexity[parserStates.Count];


            // ŘEŠENÍ NEDETERMINISTICKÝCH STAVŮ (KONFLIKTŮ)

            numInconsistentStates = 0;

            foreach (State state in parserStates)
            {
                List <Item> finalItems = new List <Item>();
                stateResolvedAt[state.StateNumber] = LookaheadComplexity.LR0;

                foreach (Item item in state.ItemSet)
                {
                    if (item.IsFinal)
                    {
                        finalItems.Add(item);
                    }
                }

                if (finalItems.Count >= 2)
                {
                    stateLookaheadIndex[state.StateNumber] = numInconsistentStates;
                    stateResolvedAt[state.StateNumber]     = LookaheadComplexity.Unresolved;
                    numInconsistentStates++;
                    conflictingItems.Add(finalItems);
                }
                else if (finalItems.Count >= 1)
                {
                    bool canRead = false;
                    foreach (Transition trans in state.Transitions)
                    {
                        if (trans is TerminalTransition)
                        {
                            canRead = true;
                            break;
                        }
                    }
                    if (canRead)
                    {
                        stateLookaheadIndex[state.StateNumber] = numInconsistentStates;
                        stateResolvedAt[state.StateNumber]     = LookaheadComplexity.Unresolved;
                        numInconsistentStates++;
                        conflictingItems.Add(finalItems);
                    }
                }
            }

            if (numInconsistentStates > 0)
            {
                //Vstupní gramatika není LR(0), bude tedy třeba spočítat lookahead množiny pro nekonzistentní
                //stavy. Použijeme postup DeRemera a Pennella, kdy se pokusíme každý nekonzistení stav nejdříve
                //vyřešit pomocí SLR(1) lookahead množin a až poté případně přikročíme k výpočtu LALR(1) lookaheadů.

                //Krok 1. Určit, které neterminály jsou nulovatelné.

                computeNullableNonterminals();

                //Krok 2. Spočítat SLR(1) lookaheady.
                //Připravíme se na počítání Read a SLR-Follow množin a pokusíme se vyřešit konflikty
                //pouze pomocí SLR(1) lookaheadů.


                //Direct Read množina pro každou neterminální hranu
                initDR =
                    (trans =>
                {
                    BitVectorSet set = new BitVectorSet(grammar.NumTerminals);
                    foreach (Transition nextTrans in trans.Destination.Transitions)
                    {
                        if (nextTrans is TerminalTransition)
                        {
                            set.Add(nextTrans.TransitionSymbol);
                        }
                    }
                    return(set);
                });

                read    = new BitVectorSet[numNonterminalTransitions];
                N_reads = new int[numNonterminalTransitions];
                reads   = new ReadsOracle(this);

                if (!forceLalr1)
                {
                    getNontermIndex = (nonterm => nonterm - grammar.NumTerminals);

                    //původní hodnota pro nějaký neterminál bude sjednocení Read množin všech hran označených
                    //tímto neterminálem; vyplývá téměř přímo z definice výpočtu Follow množin SLR(1) parserů
                    initSLR = (nonterm =>
                    {
                        BitVectorSet set = new BitVectorSet(grammar.NumTerminals);
                        foreach (NonterminalTransition trans in transitionsByNonterminals[nonterm - grammar.NumTerminals])
                        {
                            if (N_reads[getTransNumber(trans)] == 0)
                            {
                                digraphTraverse <NonterminalTransition>(trans, N_reads, read, reads, initDR, getTransNumber);
                            }
                            set.UnionWith(read[getTransNumber(trans)]);
                        }
                        return(set);
                    });

                    slr_follow  = new BitVectorSet[grammar.NumNonterminals];
                    N_slr       = new int[grammar.NumNonterminals];
                    slr_follows = new SLROracle(this);

                    foreach (State state in parserStates)
                    {
                        if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                        {
                            List <BitVectorSet> stateLookaheads = new List <BitVectorSet>();

                            foreach (Item conflictItem in conflictingItems[stateLookaheadIndex[state.StateNumber]])
                            {
                                if (N_slr[getNontermIndex(conflictItem.Production.LHSSymbol)] == 0)
                                {
                                    digraphTraverse <int>(conflictItem.Production.LHSSymbol, N_slr, slr_follow, slr_follows, initSLR, getNontermIndex);
                                }

                                stateLookaheads.Add(slr_follow[getNontermIndex(conflictItem.Production.LHSSymbol)]);
                            }

                            lookaheadSets.Add(stateLookaheads);
                        }
                    }
                }

                //Krok 3. Spočítat LALR(1) lookaheady.
                //Pokud SLR(1) lookaheady nevyřešily všechny konflikty, spočteme pro nedořešené stavy
                //LALR(1) lookaheady.

                if (forceLalr1 || checkForConflicts(LookaheadComplexity.SLR1))
                {
                    initRead = (trans =>
                    {
                        if (N_reads[getTransNumber(trans)] == 0)
                        {
                            digraphTraverse <NonterminalTransition>(trans, N_reads, read, reads, initDR, getTransNumber);
                        }
                        return(new BitVectorSet(read[getTransNumber(trans)]));
                    });

                    follow     = new BitVectorSet[numNonterminalTransitions];
                    N_includes = new int[numNonterminalTransitions];
                    includes   = new IncludesOracle(this);

                    foreach (State state in parserStates)
                    {
                        if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                        {
                            List <BitVectorSet> stateLookaheads = new List <BitVectorSet>();

                            foreach (Item conflictItem in conflictingItems[stateLookaheadIndex[state.StateNumber]])
                            {
                                BitVectorSet lookaheadSet = new BitVectorSet(grammar.NumTerminals);

                                foreach (NonterminalTransition trans in lookback(state, conflictItem))
                                {
                                    if (N_includes[getTransNumber(trans)] == 0)
                                    {
                                        digraphTraverse <NonterminalTransition>(trans, N_includes, follow, includes, initRead, getTransNumber);
                                    }

                                    lookaheadSet.UnionWith(follow[getTransNumber(trans)]);
                                }

                                stateLookaheads.Add(lookaheadSet);
                            }

                            //v případě, že je tohle naše první počítání lookahead množin, tak musíme
                            //založit pro stav novou položku v seznamu lookaheadSets; v opačném případě
                            //přepíšeme tu, kterou jsme vytvořili při počítání minulém
                            if (forceLalr1)
                            {
                                lookaheadSets.Add(stateLookaheads);
                            }
                            else
                            {
                                lookaheadSets[stateLookaheadIndex[state.StateNumber]] = stateLookaheads;
                            }
                        }
                    }

                    //Krok 4. Ověřit parser
                    //Pokud parser stále obsahuje konflikty, vypíšeme uživateli do logu podobu stavového
                    //automatu a vyznačíme v ní konflikty. Pokud parser konflikty neobsahuje, zapíšeme
                    //poznatky do tabulek a máme hotovo.

                    bool reduceReduceConflicts;
                    bool conflicts = checkForConflicts(LookaheadComplexity.LALR1, out reduceReduceConflicts);
                    if (reduceReduceConflicts)
                    {
                        if (logfileName != null)
                        {
                            printAutomatonStates(logfileName);
                            throw new GrammarException(string.Format("Reduce/reduce conflicts detected in the resulting parser.\r\nThe grammar isn't LALR(1).\r\nCheck the log file {0} for details.", logfileName));
                        }
                        else
                        {
                            throw new GrammarException("Reduce/reduce conflicts detected in the resulting parser.\r\nThe grammar isn't LALR(1).");
                        }
                    }
                    else if (conflicts)
                    {
                        if (reportOutput != null)
                        {
                            printShiftReduceConflicts(reportOutput);
                        }
                    }
                }
            }

            ParserAction[,] parseTable = new ParserAction[parserStates.Count, grammar.NumTerminals];
            int[,] gotoTable           = new int[parserStates.Count, grammar.NumNonterminals];
            for (int i = 0; i < parserStates.Count; i++)
            {
                for (int j = 0; j < grammar.NumNonterminals; j++)
                {
                    gotoTable[i, j] = -1;
                }
            }

            for (int stateNumber = 0; stateNumber < parserStates.Count; stateNumber++)
            {
                if (stateLookaheadIndex[stateNumber] >= 0)
                {
                    for (int i = 0; i < conflictingItems[stateLookaheadIndex[stateNumber]].Count; i++)
                    {
                        ParserAction action = new ParserAction();
                        action.ActionType = ParserActionType.Reduce;
                        action.Argument   = conflictingItems[stateLookaheadIndex[stateNumber]][i].Production.ProductionCode;
                        foreach (int symbol in lookaheadSets[stateLookaheadIndex[stateNumber]][i])
                        {
                            parseTable[stateNumber, symbol] = action;
                        }
                    }
                }
                else
                {
                    foreach (Item item in parserStates[stateNumber].ItemSet)
                    {
                        if (item.IsFinal)
                        {
                            ParserAction action = new ParserAction();
                            action.ActionType = ParserActionType.Reduce;
                            action.Argument   = item.Production.ProductionCode;
                            for (int symbol = 0; symbol < grammar.NumTerminals; symbol++)
                            {
                                parseTable[stateNumber, symbol] = action;
                            }
                        }
                    }
                }

                foreach (Transition trans in parserStates[stateNumber].Transitions)
                {
                    if (trans is TerminalTransition)
                    {
                        parseTable[stateNumber, trans.TransitionSymbol].ActionType = ParserActionType.Shift;
                        parseTable[stateNumber, trans.TransitionSymbol].Argument   = trans.Destination.StateNumber;
                    }
                    else
                    {
                        gotoTable[stateNumber, trans.TransitionSymbol - grammar.NumTerminals] = trans.Destination.StateNumber;
                    }
                }
            }

            grammar.ParserData.ParseTable = parseTable;
            grammar.ParserData.GotoTable  = gotoTable;

            if (explicitLogging)
            {
                printAutomatonStates(logfileName);
            }

            if (reportOutput != null)
            {
                printSuccessReport(reportOutput);
            }
        }
Example #10
0
        private void printStatesHTML(TextWriter writer)
        {
            writer.WriteLine("<h2>Parser states</h2>");

            if (numInconsistentStates > 0)
            {
                writer.Write("<b>States with inconsistencies:</b> ");

                StringBuilder inconsistentStatesString = new StringBuilder();
                foreach (State state in parserStates)
                {
                    if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                    {
                        inconsistentStatesString.AppendFormat("<a href=\"#State{0}\">{0}</a>, ", state.StateNumber);
                    }
                }
                inconsistentStatesString.Remove(inconsistentStatesString.Length - 2, 2);

                writer.WriteLine(inconsistentStatesString.ToString());
            }

            foreach (State state in parserStates)
            {
                writer.Write("<a name=\"State{0}\" id=\"State{0}\"/>", state.StateNumber);
                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    writer.WriteLine("<h3 style=\"color:red\">State {0}</h3>", state.StateNumber);
                }
                else
                {
                    writer.WriteLine("<h3>State {0}</h3>", state.StateNumber);
                }

                writer.WriteLine("<b>Items:</b>");
                writer.WriteLine("<ul>");

                BitVectorSet conflictSymbols = new BitVectorSet(grammar.NumTerminals);

                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    //najde symboly, pro které je tento stav nedeterministický, úpravou algoritmu na hledání
                    //konfliktů použitém v metodě checkForConflicts
                    BitVectorSet accumulator = new BitVectorSet(grammar.NumTerminals);

                    foreach (Transition trans in state.Transitions)
                    {
                        if (trans is TerminalTransition)
                        {
                            accumulator.Add(trans.TransitionSymbol);
                        }
                    }

                    foreach (BitVectorSet lookaheadSet in lookaheadSets[stateLookaheadIndex[state.StateNumber]])
                    {
                        BitVectorSet newConflictSymbols = accumulator.GetIntersectionWith(lookaheadSet);
                        accumulator.UnionWith(lookaheadSet);
                        conflictSymbols.UnionWith(newConflictSymbols);
                    }
                }

                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.LR0)
                {
                    //žádný lookahead
                    foreach (Item item in state.ItemSet)
                    {
                        writer.Write("<li>");
                        printItemHTML(item, conflictSymbols, writer);
                        writer.WriteLine("</li>");
                    }
                }
                else
                {
                    //nejdřív vypíšeme finální itemy a jejich lookahead množiny; pro každý konfliktní symbol
                    //v lookahead množině navíc vypíšeme cestu, jakou se do lookahead množiny dostal
                    for (int i = 0; i < conflictingItems[stateLookaheadIndex[state.StateNumber]].Count; i++)
                    {
                        writer.Write("<li>");
                        printItemHTML(conflictingItems[stateLookaheadIndex[state.StateNumber]][i], conflictSymbols, writer);

                        writer.WriteLine("<br>");
                        printLookahead(lookaheadSets[stateLookaheadIndex[state.StateNumber]][i], conflictSymbols, writer);

                        if (!conflictSymbols.IsDisjointWith(lookaheadSets[stateLookaheadIndex[state.StateNumber]][i]))
                        {
                            writer.WriteLine("<br>");
                            printSymbolExplanations(state, conflictingItems[stateLookaheadIndex[state.StateNumber]][i],
                                                    conflictSymbols.GetIntersectionWith(lookaheadSets[stateLookaheadIndex[state.StateNumber]][i]), writer);
                        }

                        writer.WriteLine("</li>");
                    }

                    //pak vypíšeme zbylé itemy
                    foreach (Item item in state.ItemSet)
                    {
                        if (!item.IsFinal)
                        {
                            writer.Write("<li>");
                            printItemHTML(item, conflictSymbols, writer);
                            writer.WriteLine("</li>");
                        }
                    }
                }

                writer.WriteLine("</ul>");

                writer.Write("<b>Accessing states:</b> ");

                StringBuilder accessingStatesString = new StringBuilder();
                foreach (State accessingState in state.AccessingStates)
                {
                    accessingStatesString.AppendFormat("<a href=\"#State{0}\">{0}</a>, ", accessingState.StateNumber);
                }
                if (accessingStatesString.Length > 0)
                {
                    accessingStatesString.Remove(accessingStatesString.Length - 2, 2);
                }

                writer.Write(accessingStatesString.ToString());
                writer.WriteLine("<br>");

                writer.Write("<b>Transitions:</b> ");

                StringBuilder transitionsString = new StringBuilder();
                foreach (Transition trans in state.Transitions)
                {
                    transitionsString.AppendFormat("<a href=\"#State{0}\">{0}</a>({1}), ",
                                                   trans.Destination.StateNumber, getSymbolPrintName(trans.TransitionSymbol));
                }
                if (transitionsString.Length > 0)
                {
                    transitionsString.Remove(transitionsString.Length - 2, 2);
                }

                writer.Write(transitionsString.ToString());
                writer.WriteLine("<br>");
            }
        }
Example #11
0
        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>");
            }
        }
Example #12
0
        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>");
            }
        }
Example #13
0
        private void printStatesHTML(TextWriter writer)
        {
            writer.WriteLine("<h2>Parser states</h2>");

            if (numInconsistentStates > 0)
            {
                writer.Write("<b>States with inconsistencies:</b> ");

                StringBuilder inconsistentStatesString = new StringBuilder();
                foreach (State state in parserStates)
                    if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                        inconsistentStatesString.AppendFormat("<a href=\"#State{0}\">{0}</a>, ", state.StateNumber);
                inconsistentStatesString.Remove(inconsistentStatesString.Length - 2, 2);

                writer.WriteLine(inconsistentStatesString.ToString());
            }

            foreach (State state in parserStates)
            {
                writer.Write("<a name=\"State{0}\" id=\"State{0}\"/>", state.StateNumber);
                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                    writer.WriteLine("<h3 style=\"color:red\">State {0}</h3>", state.StateNumber);
                else
                    writer.WriteLine("<h3>State {0}</h3>", state.StateNumber);

                writer.WriteLine("<b>Items:</b>");
                writer.WriteLine("<ul>");

                BitVectorSet conflictSymbols = new BitVectorSet(grammar.NumTerminals);

                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.Unresolved)
                {
                    //najde symboly, pro které je tento stav nedeterministický, úpravou algoritmu na hledání
                    //konfliktů použitém v metodě checkForConflicts
                    BitVectorSet accumulator = new BitVectorSet(grammar.NumTerminals);

                    foreach (Transition trans in state.Transitions)
                        if (trans is TerminalTransition)
                            accumulator.Add(trans.TransitionSymbol);

                    foreach (BitVectorSet lookaheadSet in lookaheadSets[stateLookaheadIndex[state.StateNumber]])
                    {
                        BitVectorSet newConflictSymbols = accumulator.GetIntersectionWith(lookaheadSet);
                        accumulator.UnionWith(lookaheadSet);
                        conflictSymbols.UnionWith(newConflictSymbols);
                    }
                }

                if (stateResolvedAt[state.StateNumber] == LookaheadComplexity.LR0)
                {
                    //žádný lookahead
                    foreach (Item item in state.ItemSet)
                    {
                        writer.Write("<li>");
                        printItemHTML(item, conflictSymbols, writer);
                        writer.WriteLine("</li>");
                    }
                }
                else
                {
                    //nejdřív vypíšeme finální itemy a jejich lookahead množiny; pro každý konfliktní symbol
                    //v lookahead množině navíc vypíšeme cestu, jakou se do lookahead množiny dostal
                    for (int i = 0; i < conflictingItems[stateLookaheadIndex[state.StateNumber]].Count; i++)
                    {
                        writer.Write("<li>");
                        printItemHTML(conflictingItems[stateLookaheadIndex[state.StateNumber]][i], conflictSymbols, writer);

                        writer.WriteLine("<br>");
                        printLookahead(lookaheadSets[stateLookaheadIndex[state.StateNumber]][i], conflictSymbols, writer);

                        if (!conflictSymbols.IsDisjointWith(lookaheadSets[stateLookaheadIndex[state.StateNumber]][i]))
                        {
                            writer.WriteLine("<br>");
                            printSymbolExplanations(state, conflictingItems[stateLookaheadIndex[state.StateNumber]][i],
                                conflictSymbols.GetIntersectionWith(lookaheadSets[stateLookaheadIndex[state.StateNumber]][i]), writer);
                        }

                        writer.WriteLine("</li>");
                    }

                    //pak vypíšeme zbylé itemy
                    foreach (Item item in state.ItemSet)
                        if (!item.IsFinal)
                        {
                            writer.Write("<li>");
                            printItemHTML(item, conflictSymbols, writer);
                            writer.WriteLine("</li>");
                        }
                }

                writer.WriteLine("</ul>");

                writer.Write("<b>Accessing states:</b> ");

                StringBuilder accessingStatesString = new StringBuilder();
                foreach (State accessingState in state.AccessingStates)
                    accessingStatesString.AppendFormat("<a href=\"#State{0}\">{0}</a>, ", accessingState.StateNumber);
                if (accessingStatesString.Length > 0)
                    accessingStatesString.Remove(accessingStatesString.Length - 2, 2);

                writer.Write(accessingStatesString.ToString());
                writer.WriteLine("<br>");

                writer.Write("<b>Transitions:</b> ");

                StringBuilder transitionsString = new StringBuilder();
                foreach (Transition trans in state.Transitions)
                    transitionsString.AppendFormat("<a href=\"#State{0}\">{0}</a>({1}), ",
                                    trans.Destination.StateNumber, getSymbolPrintName(trans.TransitionSymbol));
                if (transitionsString.Length > 0)
                    transitionsString.Remove(transitionsString.Length - 2, 2);

                writer.Write(transitionsString.ToString());
                writer.WriteLine("<br>");
            }
        }