public static Dfa <TSymbol> ProductDfa(DfaUtils.MinimizedDfa <TSymbol>[] dfas) { if (dfas.Length == 0) { throw new ArgumentException(); } else if (dfas.Length == 1) { return(new Dfa <TSymbol>(dfas[0])); } else { DfaUtils.MinimizedDfa <TSymbol> cur = dfas[0]; for (int i = 1; i < dfas.Length; i++) { cur = DfaUtils.MakeMinimizedProductDfa < DfaUtils.MinimizedDfa <TSymbol>, DfaUtils.MinimizedDfaState <TSymbol>, DfaUtils.MinimizedDfa <TSymbol>, DfaUtils.MinimizedDfaState <TSymbol>, TSymbol >(cur, dfas[i], new DfaUtils.AmbiguityHandler(MaxAmbiguityHandler)); } return(new Dfa <TSymbol>(cur)); } }
//1:0 --a--> 2 //2:1 --a--> 3 //3:2 --a--> 2 public void SimpleTest2() { var firstState = new DfaUtils.MinimizedDfaState <char>(); firstState._accepting = 0; var secondState = new DfaUtils.MinimizedDfaState <char>(); secondState._accepting = 1; var thirdState = new DfaUtils.MinimizedDfaState <char>(); thirdState._accepting = 2; firstState._transitions = new KeyValuePair <char, DfaUtils.MinimizedDfaState <char> >[1] { new KeyValuePair <char, DfaUtils.MinimizedDfaState <char> >('a', secondState) }; secondState._transitions = new KeyValuePair <char, DfaUtils.MinimizedDfaState <char> >[1] { new KeyValuePair <char, DfaUtils.MinimizedDfaState <char> >('a', thirdState) }; thirdState._transitions = new KeyValuePair <char, DfaUtils.MinimizedDfaState <char> >[1] { new KeyValuePair <char, DfaUtils.MinimizedDfaState <char> >('a', secondState) }; var dfa = new DfaUtils.MinimizedDfa <char>(); dfa._start = firstState; dfa = DfaUtils.Minimized <DfaUtils.MinimizedDfa <char>, DfaUtils.MinimizedDfaState <char>, char>(dfa); var stateList = DfaUtils.PrepareStateList <DfaUtils.MinimizedDfa <char>, DfaUtils.MinimizedDfaState <char>, char>(dfa); Assert.AreEqual(stateList.Count, 3); }
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>)); }
public static DfaUtils.MinimizedDfa <TSymbol> RegexDfa(RegEx <TSymbol> RegEx, uint acceptingStateMarker) { if (acceptingStateMarker == 0) { throw new ArgumentOutOfRangeException(); } AbstractDfa <DFAState <TSymbol>, TSymbol> factorDfa = (AbstractDfa <DFAState <TSymbol>, TSymbol>) new RegExDfa <TSymbol>(RegEx, acceptingStateMarker); return(DfaUtils.MakeMinimizedProductDfa < AbstractDfa <DFAState <TSymbol>, TSymbol>, DFAState <TSymbol>, AbstractDfa <DFAState <TSymbol>, TSymbol>, DFAState <TSymbol>, TSymbol >(factorDfa, factorDfa, new DfaUtils.AmbiguityHandler(MaxAmbiguityHandler))); }
public void MakeMinimizedProductDfaTypePunnedInvocation() { IDfa <char> someDfa = DfaUtils.MakeEmptyLanguageDfa <char>(); var someOtherDfa = DfaUtils.MakeMinimizedProductDfa(someDfa, someDfa, (a, b) => { if (a != 0 && b != 0) { throw new ArgumentException(); } return(a + b); }); Assert.NotNull(someOtherDfa); Assert.NotNull(someOtherDfa.Start); Assert.AreEqual(someOtherDfa.Start.Accepting, 0); Assert.AreEqual(someOtherDfa.Start.Transitions.Count, 1); Assert.AreEqual(someOtherDfa.Start.Transitions[0].Key, '\0'); Assert.AreSame(someOtherDfa.Start.Transitions[0].Value, someOtherDfa.Start); }
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>)); }
public void MinimizedEmpty() { DfaUtils.MakeEmptyLanguageDfa <char>(); }