private static DfaAndState <TLabel> CreateDfaAndState(IDfa <Optional <Rule <TLabel> >, TLabel> dfa, IState state) { var pair = new DfaAndState <TLabel> { Dfa = dfa, State = state }; return(pair); }
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>)); }
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); }