Example #1
0
 public Parser(
     CompiledGrammar <TLabel> grammar,
     IReadOnlyDictionary <Tuple <IDfa <Optional <Rule <TLabel> >, TLabel>, IState, TLabel>,
                          ParseAction <TLabel> > table)
 {
     this.grammar = grammar;
     this.table   = table;
 }
Example #2
0
        public static CompiledGrammar <TLabel> CompileGrammar(Grammar <TLabel> grammar)
        {
            var result = new CompiledGrammar <TLabel>();

            result.StartSymbol = grammar.StartSymbol;

            result.Rules = grammar.Rules.GroupBy((rule) => rule.Lhs).ToDictionary(
                keySelector: (group) => group.Key,
                elementSelector: (group) => CompileRules(group.ToList()));

            return(result);
        }
Example #3
0
            public ParseProcess(
                CompiledGrammar <TLabel> grammar,
                IReadOnlyDictionary <Tuple <IDfa <Optional <Rule <TLabel> >, TLabel>, IState, TLabel>,
                                     ParseAction <TLabel> > table, IDiagnostics diagnostics)
            {
                this.rules       = grammar.Rules;
                this.table       = table;
                this.diagnostics = diagnostics;
                var startSymbol = grammar.StartSymbol;

                this.statesStack = new Stack <IState>(new[] { this.rules[startSymbol].StartingState() });
                this.dfaStack    = new Stack <IDfa <Optional <Rule <TLabel> >, TLabel> >(new[] { this.rules[startSymbol] });
                this.nodesStack  = new Stack <List <ParseTree <TLabel> > >(new[] { new List <ParseTree <TLabel> >() });
            }
Example #4
0
        public static IReadOnlyDictionary <DfaAndState <Symbol>, IReadOnlyCollection <Symbol> > GetFirstSymbols(
            CompiledGrammar <Symbol> grammar,
            IReadOnlyCollection <DfaAndState <Symbol> > nullables)
        {
            var nullablesSet = new HashSet <DfaAndState <Symbol> >(nullables);

            var firstSymbols = new Dictionary <DfaAndState <Symbol>, HashSet <Symbol> >();
            var graph        = new Dictionary <DfaAndState <Symbol>, List <DfaAndState <Symbol> > >();

            foreach (var rule in grammar.Rules)
            {
                var dfa = rule.Value;
                foreach (var state in DfaUtils.GetAllStates(dfa))
                {
                    var stateEntity = StateEntity(dfa, state);
                    firstSymbols[stateEntity] = new HashSet <Symbol>();
                    graph[stateEntity]        = new List <DfaAndState <Symbol> >();

                    foreach (var transition in dfa.Transitions(state))
                    {
                        Symbol symbol    = transition.Key;
                        var    nextState = transition.Value;
                        if (dfa.Label(nextState).IsNone() && dfa.IsStable(nextState))
                        {
                            continue;
                        }

                        firstSymbols[stateEntity].Add(symbol);

                        if (!grammar.Rules.ContainsKey(symbol))
                        {
                            continue;
                        }

                        var symbolEntity = StateEntity(grammar.Rules[symbol], grammar.Rules[symbol].StartingState());
                        graph[stateEntity].Add(symbolEntity);

                        if (nullablesSet.Contains(symbolEntity))
                        {
                            graph[stateEntity].Add(StateEntity(dfa, transition.Value));
                        }
                    }
                }
            }

            TransitiveClosure(graph, firstSymbols);

            return(firstSymbols.ToDictionary(kpv => kpv.Key, kpv => kpv.Value as IReadOnlyCollection <Symbol>));
        }
Example #5
0
                                           ParseAction <TLabel> > Parse(
            CompiledGrammar <TLabel> grammar,
            IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > follow,
            IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > firstPlus)
        {
            var parseTable =
                new Dictionary <Tuple <IDfa <Optional <Rule <TLabel> >, TLabel>, IState, TLabel>, ParseAction <TLabel> >();
            var allSymbols = (TLabel[])Enum.GetValues(typeof(TLabel));
            var error      = string.Empty;

            foreach (var rule in grammar.Rules)
            {
                var dfa       = rule.Value;
                var allStates = dfa.GetAllStates();

                foreach (var state in allStates)
                {
                    foreach (var firstSymbol in allSymbols)
                    {
                        var key     = Tuple.Create(dfa, state, firstSymbol);
                        var actions = GetAllParseActions(grammar, state, dfa, firstSymbol, follow, firstPlus);

                        if (actions.Count > 1)
                        {
                            var errorMessage =
                                $"Many possible actions for label {firstSymbol}: {{{string.Join(", ", actions)}}}\n";
                            error += errorMessage;
                        }
                        else if (actions.Count == 1)
                        {
                            parseTable[key] = actions.ElementAt(0);
                        }
                    }
                }
            }

            if (!error.Equals(string.Empty))
            {
                throw new InvalidOperationException(error);
            }

            return(parseTable);
        }
Example #6
0
        public static IReadOnlyDictionary <DfaAndState <TLabel>, IReadOnlyCollection <TLabel> > GetFollowSymbols(
            CompiledGrammar <TLabel> grammar,
            IReadOnlyCollection <DfaAndState <TLabel> > nullables,
            IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > first,
            TLabel eofSymbol)
        {
            var resultSymbols = new Dictionary <TLabel, HashSet <TLabel> >();

            GetDefault(resultSymbols, grammar.StartSymbol).Add(eofSymbol);

            var resultStates = new Dictionary <DfaAndState <TLabel>, HashSet <TLabel> >();

            while (true)
            {
                bool anythingChanged = false;

                foreach (var rule in grammar.Rules)
                {
                    var dfa = rule.Value;

                    foreach (var state in DfaUtils.GetAllStates(dfa))
                    {
                        var label       = dfa.Label(state);
                        var dfaAndState = new DfaAndState <TLabel> {
                            Dfa = dfa, State = state
                        };
                        var stateFollows = GetDefault(resultStates, dfaAndState);

                        if (label.IsSome())
                        {
                            var symFollows = GetDefault(resultSymbols, label.Get().Lhs);

                            foreach (var sym in symFollows)
                            {
                                anythingChanged = stateFollows.Add(sym) || anythingChanged;
                            }
                        }

                        foreach (var transition in dfa.Transitions(state))
                        {
                            TLabel edgeSymbol = transition.Key;

                            var nextState       = transition.Value;
                            var nextDfaAndState = new DfaAndState <TLabel> {
                                Dfa = dfa, State = nextState
                            };
                            if (dfa.Label(nextState).IsNone() && dfa.IsStable(nextState))
                            {
                                continue;
                            }

                            anythingChanged = stateFollows.Add(edgeSymbol) || anythingChanged;

                            // And also add First (first is the same as Follow of the initial state)
                            if (grammar.Rules.ContainsKey(edgeSymbol))
                            {
                                var edgeStartState = new DfaAndState <TLabel> {
                                    Dfa = grammar.Rules[edgeSymbol]
                                };
                                edgeStartState.State = edgeStartState.Dfa.StartingState();
                                foreach (var sym in GetDefault(resultStates, edgeStartState))
                                {
                                    anythingChanged = stateFollows.Add(sym) || anythingChanged;
                                }
                            }

                            var edgeFollows = GetDefault(resultSymbols, edgeSymbol);
                            foreach (var sym in GetDefault(resultStates, nextDfaAndState))
                            {
                                anythingChanged = edgeFollows.Add(sym) || anythingChanged;
                            }
                        }
                    }
                }

                if (!anythingChanged)
                {
                    break;
                }
            }

            var resultStatesCorrect = new Dictionary <DfaAndState <TLabel>, HashSet <TLabel> >();

            // Contrary to expectations, resultStates doesn't contain correct follows for accepting states of the automatas,
            // because they can be reused.
            // To sum up: 'follow for states' doesn't make sense, only for symbols, but we fake 'follow for states' to conform with the API.
            foreach (var rule in grammar.Rules)
            {
                var dfa = rule.Value;

                foreach (var state in DfaUtils.GetAllStates(dfa))
                {
                    var label       = dfa.Label(state);
                    var dfaAndState = new DfaAndState <TLabel> {
                        Dfa = dfa, State = state
                    };
                    var stateFollows = GetDefault(resultStates, dfaAndState);

                    if (label.IsSome())
                    {
                        resultStatesCorrect[dfaAndState] = resultSymbols[label.Get().Lhs];
                    }
                }
            }

            return(resultStatesCorrect.ToDictionary(kpv => kpv.Key, kpv => kpv.Value as IReadOnlyCollection <TLabel>));
        }
Example #7
0
        public static IReadOnlyCollection <DfaAndState <TLabel> > GetNullableSymbols(CompiledGrammar <TLabel> grammar)
        {
            // TLabel - nieterminal
            // Rule<TLabel> - produkcja
            var statesToProcess         = new Queue <DfaAndState <TLabel> >();
            var dfaToLhSymbol           = new Dictionary <IDfa <Optional <Rule <TLabel> >, TLabel>, TLabel>();
            var nullableSymbols         = new HashSet <TLabel>();
            var potentialNullableStates = new Dictionary <TLabel, List <DfaAndState <TLabel> > >();
            var visitedStates           = new HashSet <DfaAndState <TLabel> >(); // all visited states are nullable

            foreach (var rule in grammar.Rules)
            {
                var ruleDfa = rule.Value;
                foreach (var state in ruleDfa.GetAllStates())
                {
                    if (IsAccepting(ruleDfa, state))
                    {
                        var queuePair = CreateDfaAndState(ruleDfa, state);
                        if (!visitedStates.Contains(queuePair))
                        {
                            visitedStates.Add(queuePair);
                            statesToProcess.Enqueue(queuePair);
                        }

                        if (!dfaToLhSymbol.ContainsKey(ruleDfa))
                        {
                            dfaToLhSymbol.Add(ruleDfa, rule.Key);
                        }
                    }
                }
            }

            var reverseTransitions = GetReverseTransitions(grammar);

            while (statesToProcess.Count > 0)
            {
                var queuePair = statesToProcess.Dequeue();

                if (queuePair.State.Equals(queuePair.Dfa.StartingState()))
                {
                    var lhSymbol = dfaToLhSymbol[queuePair.Dfa];
                    nullableSymbols.Add(lhSymbol);
                    if (!potentialNullableStates.ContainsKey(lhSymbol))
                    {
                        potentialNullableStates.Add(lhSymbol, new List <DfaAndState <TLabel> >());
                    }

                    foreach (var stateDfaPair in potentialNullableStates[lhSymbol])
                    {
                        if (!visitedStates.Contains(stateDfaPair))
                        {
                            visitedStates.Add(stateDfaPair);
                            statesToProcess.Enqueue(stateDfaPair);
                        }
                    }

                    potentialNullableStates.Clear();
                }

                foreach (var transition in reverseTransitions[queuePair.Dfa][queuePair.State])
                {
                    var symbol = transition.Key;
                    foreach (var newState in transition.Value)
                    {
                        var newQueuePair = CreateDfaAndState(queuePair.Dfa, newState);
                        if (visitedStates.Contains(newQueuePair))
                        {
                            continue;
                        }

                        if (nullableSymbols.Contains(symbol))
                        {
                            if (!visitedStates.Contains(newQueuePair))
                            {
                                visitedStates.Add(newQueuePair);
                                statesToProcess.Enqueue(newQueuePair);
                            }
                        }
                        else
                        {
                            if (!potentialNullableStates.ContainsKey(symbol))
                            {
                                potentialNullableStates.Add(symbol, new List <DfaAndState <TLabel> >());
                            }

                            potentialNullableStates[symbol].Add(newQueuePair);
                        }
                    }
                }
            }

            return(visitedStates);
        }
Example #8
0
        private static IReadOnlyDictionary <IDfa <Optional <Rule <TLabel> >, TLabel>, Dictionary <IState, Dictionary <TLabel, HashSet <IState> > > > GetReverseTransitions(CompiledGrammar <TLabel> grammar)
        {
            var reverseTransitions = new Dictionary <IDfa <Optional <Rule <TLabel> >, TLabel>, Dictionary <IState, Dictionary <TLabel, HashSet <IState> > > >();

            foreach (var rule in grammar.Rules)
            {
                reverseTransitions.Add(rule.Value, GetReverseTransitions(rule.Value));
            }

            return(reverseTransitions);
        }
Example #9
0
        private static IReadOnlyCollection <ParseAction <TLabel> > GetAllParseActions(
            CompiledGrammar <TLabel> grammar,
            IState state,
            IDfa <Optional <Rule <TLabel> >, TLabel> dfa,
            TLabel label,
            IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > follow,
            IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > firstPlus)
        {
            var actions = new List <ParseAction <TLabel> >();

            var stateLabel  = dfa.Label(state);
            var dfaAndState = new DfaAndState <TLabel>()
            {
                Dfa = dfa, State = state
            };

            if (stateLabel.IsSome() && follow.ContainsKey(label) && follow[label].Contains(dfaAndState))
            {
                actions.Add(
                    new ParseAction <TLabel>()
                {
                    Kind = ParseAction <TLabel> .ActionKind.Reduce, Label = stateLabel.Get().Lhs
                });
            }

            var transitions = dfa.Transitions(state);

            if (transitions.ContainsKey(label))
            {
                var nextState = transitions[label];
                if (!dfa.IsStable(nextState) || dfa.Label(nextState).IsSome())
                {
                    actions.Add(
                        new ParseAction <TLabel>()
                    {
                        Kind = ParseAction <TLabel> .ActionKind.Shift, Label = label
                    });
                }
            }

            if (firstPlus.ContainsKey(label))
            {
                var firstPlusStates = firstPlus[label];
                foreach (var transitionLabel in transitions.Keys)
                {
                    var nextState = transitions[transitionLabel];
                    if ((!dfa.IsStable(nextState) || dfa.Label(nextState).IsSome()) && grammar.Rules.ContainsKey(transitionLabel))
                    {
                        var subDfa = grammar.Rules[transitionLabel];
                        var subDfaAndStartState = new DfaAndState <TLabel>()
                        {
                            Dfa = subDfa, State = subDfa.StartingState()
                        };

                        if (firstPlusStates.Contains(subDfaAndStartState))
                        {
                            actions.Add(
                                new ParseAction <TLabel>()
                            {
                                Kind = ParseAction <TLabel> .ActionKind.Call, Label = transitionLabel
                            });
                        }
                    }
                }
            }

            return(actions);
        }