Example #1
0
        private static DfaAndState <TLabel> CreateDfaAndState(IDfa <Optional <Rule <TLabel> >, TLabel> dfa, IState state)
        {
            var pair = new DfaAndState <TLabel>
            {
                Dfa   = dfa,
                State = state
            };

            return(pair);
        }
Example #2
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 #3
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);
        }