public void MinimizeIncomplete() { // We build a simple, incomplete DFA var dfa = new Dfa <string, char>(); dfa.InitialState = "A"; dfa.AcceptingStates.Add("D"); dfa.AddTransition("A", '0', "B"); dfa.AddTransition("A", '1', "C"); dfa.AddTransition("B", '0', "C"); dfa.AddTransition("C", '0', "B"); dfa.AddTransition("C", '1', "D"); // Minimize it var minDfa = dfa.Minimize(); var expectedStates = new[] { "A", "B", "C", "D" }.Select(ParseStateSet); var gotStates = minDfa.States.ToHashSet(); var expectedAcceptingStates = new[] { "D" }.Select(ParseStateSet); var gotAcceptingStates = minDfa.AcceptingStates.ToHashSet(); Assert.True(gotStates.SetEquals(expectedStates)); Assert.True(gotAcceptingStates.SetEquals(expectedAcceptingStates)); Assert.Equal(5, minDfa.Transitions.Count); AssertTransition(minDfa, "A", '0', "B"); AssertTransition(minDfa, "A", '1', "C"); AssertTransition(minDfa, "B", '0', "C"); AssertTransition(minDfa, "C", '0', "B"); AssertTransition(minDfa, "C", '1', "D"); }
/* * Function: DTrans */ public DTrans(Spec s, Dfa dfa) { dtrans = new int[s.dtrans_ncols]; label = s.dtrans_list.Count; accept = dfa.GetAccept(); anchor = dfa.GetAnchor(); }
public void MinimizeIncompleteIssue() { var dfa = new Dfa <string, char>(); dfa.InitialState = "q0"; dfa.AcceptingStates.Add("q3"); dfa.AcceptingStates.Add("q4"); dfa.AddTransition("q0", '0', "q1"); dfa.AddTransition("q1", 'x', "q2"); dfa.AddTransition("q2", '0', "q3"); dfa.AddTransition("q3", '0', "q4"); dfa.AddTransition("q4", '0', "q4"); var minDfa = dfa.Minimize(); var expectedStates = new[] { "q0", "q1", "q2", "q3, q4" }.Select(ParseStateSet); var gotStates = minDfa.States.ToHashSet(); var expectedAcceptingStates = new[] { "q3, q4" }.Select(ParseStateSet); var gotAcceptingStates = minDfa.AcceptingStates.ToHashSet(); Assert.True(gotStates.SetEquals(expectedStates)); Assert.True(gotAcceptingStates.SetEquals(expectedAcceptingStates)); Assert.Equal(4, minDfa.Transitions.Count); AssertTransition(minDfa, "q0", '0', "q1"); AssertTransition(minDfa, "q1", 'x', "q2"); AssertTransition(minDfa, "q2", '0', "q3, q4"); AssertTransition(minDfa, "q3, q4", '0', "q3, q4"); }
public static void EquivalenceOfTwoDfas() { // // Equivalence of two DFAs (Example 4.21 in book) // var eqDfas = new Dfa <string>('A', new [] { 'A', 'C', 'D' }); // start state is redundant for finding equivalent blocks // First DFA eqDfas.AddTrans('A', "0", 'A'); eqDfas.AddTrans('A', "1", 'B'); eqDfas.AddTrans('B', "0", 'A'); eqDfas.AddTrans('B', "1", 'B'); // Second DFA eqDfas.AddTrans('C', "0", 'D'); eqDfas.AddTrans('C', "1", 'E'); eqDfas.AddTrans('D', "0", 'D'); eqDfas.AddTrans('D', "1", 'E'); eqDfas.AddTrans('E', "0", 'C'); eqDfas.AddTrans('E', "1", 'E'); SaveFile("dfa_eq.dot", DotLanguagePrinter.ToDotLanguage(eqDfas)); //System.Console.WriteLine(); Console.WriteLine($"Eq state pairs: {eqDfas.DisplayEquivalentPairs()}"); Console.WriteLine($"Eq state sets: {eqDfas.DisplayMergedEqSets()}"); }
public void Dump(IndentWriter writer, Dfa dfa) { foreach (var state in dfa.States) { Dump(writer, state); } }
public static void NonMinimalDfa() { // // Non-minimal DFA (Exercise 4.4.1 in the book) // var nonMinDfa = new Dfa <string>('A', new [] { 'D' }); nonMinDfa.AddTrans('A', "0", 'B'); nonMinDfa.AddTrans('A', "1", 'A'); nonMinDfa.AddTrans('B', "0", 'A'); nonMinDfa.AddTrans('B', "1", 'C'); nonMinDfa.AddTrans('C', "0", 'D'); nonMinDfa.AddTrans('C', "1", 'B'); nonMinDfa.AddTrans('D', "0", 'D'); nonMinDfa.AddTrans('D', "1", 'A'); nonMinDfa.AddTrans('E', "0", 'D'); nonMinDfa.AddTrans('E', "1", 'F'); nonMinDfa.AddTrans('F', "0", 'G'); nonMinDfa.AddTrans('F', "1", 'E'); nonMinDfa.AddTrans('G', "0", 'F'); nonMinDfa.AddTrans('G', "1", 'G'); nonMinDfa.AddTrans('H', "0", 'G'); nonMinDfa.AddTrans('H', "1", 'D'); SaveFile("dfaNonMin.dot", DotLanguagePrinter.ToDotLanguage(nonMinDfa)); Console.WriteLine($"Eq state pairs: {nonMinDfa.DisplayEquivalentPairs()}"); Console.WriteLine($"Eq state sets: {nonMinDfa.DisplayMergedEqSets()}"); var minDfa = nonMinDfa.ToMinimumDfa(); SaveFile("dfaMin.dot", DotLanguagePrinter.ToDotLanguage(minDfa)); }
public static void Write(DfaState start, string fileName) { var dfa = new Dfa(start); XmlSerializer xs = new XmlSerializer(typeof(Dfa)); using (Stream s = File.Create(fileName)) xs.Serialize(s, dfa); }
/* * Function: NewCDfa */ public static Dfa NewDfa(Spec spec) { Dfa dfa; dfa = new Dfa(spec.dfa_states.Count); spec.dfa_states.Add(dfa); return(dfa); }
public void DfaIsCreatedWithNoError() { Dfa dfa = _automata.Construct().ConstructDfaUsingPowerSet(); Assert.IsNotNull(dfa); string dotfile = dfa.WriteGraph(); Assert.AreEqual(_dfaDotFile, dotfile); }
public void DfaCanFindNextValidState() { Dfa dfa = _automata.Construct().ConstructDfaUsingPowerSet(); Assert.IsNotNull(dfa); string next = dfa.FindNextValidString("gice"); Assert.AreEqual(next, "gice"); }
public void AddTarget(char ch, Dfa next) { for (int index = 0; index < this.m_arcs.Count; ++index) { Arc arc = (Arc)this.m_arcs[index]; if (arc.Match(ch)) { next.AddNfaNode(arc.m_next); } } }
CreateActionTable <SYMBOL_ENUM, TREE_NODE>(Productions <SYMBOL_ENUM, TREE_NODE> productions, PrecedenceTable <SYMBOL_ENUM> precedenceTable, GrammarReport <SYMBOL_ENUM, TREE_NODE> report, int lookaheadWidth) where SYMBOL_ENUM : struct where TREE_NODE : class { if (productions == null) { return(null); } if (lookaheadWidth < 1) { throw new ArgumentException("Lookahead width is too small"); } precedenceTable.Validate(lookaheadWidth); BuilderSets <SYMBOL_ENUM, TREE_NODE> builder_sets = BuilderSets.Create(productions, lookaheadWidth); report.Setup(productions, builder_sets); { IEnumerable <Tuple <SYMBOL_ENUM, bool> > err_recur_lhs = productions.Entries // do not check Auto recursive .Where(prod => ((prod.Recursive == RecursiveEnum.No) && builder_sets.CoverSets.IsRecursive(prod.LhsNonTerminal)) || ((prod.Recursive == RecursiveEnum.Yes) && !builder_sets.CoverSets.IsRecursive(prod.LhsNonTerminal))) .Select(prod => Tuple.Create(prod.LhsNonTerminal, !builder_sets.CoverSets.IsRecursive(prod.LhsNonTerminal))).Distinct().ToArray(); if (err_recur_lhs.Any()) { if (err_recur_lhs.Where(it => it.Item2).Any()) { report.AddError("Productions incorrectly marked as recursive: " + err_recur_lhs.Where(it => it.Item2).Select(it => "\"" + productions.SymbolsRep.Get(it.Item1) + "\"").Join(",") + "."); } if (err_recur_lhs.Where(it => !it.Item2).Any()) { report.AddError("Productions incorrectly marked as non-recursive: " + err_recur_lhs.Where(it => !it.Item2).Select(it => "\"" + productions.SymbolsRep.Get(it.Item1) + "\"").Join(",") + "."); } return(null); } } Dfa <SYMBOL_ENUM, TREE_NODE> dfa = Worker.CreateDfa(productions, lookaheadWidth, builder_sets.PrecomputedRhsFirsts, builder_sets.HorizonSets); report.Setup(dfa); return(new ActionBuilder <SYMBOL_ENUM, TREE_NODE>().FillActionTable(productions, builder_sets.FirstSets, builder_sets.CoverSets, builder_sets.HorizonSets, lookaheadWidth, dfa, precedenceTable, report)); }
public void DFA_invalid_when_initial_null() { var q0 = State.Create("q0").AssertSome(); var qs = new[] { q0 }.ToImmutableArray(); var dfa = new Dfa( ImmutableHashSet <char> .Empty, qs, qs, null); dfa.IsValid.ShouldBeFalse(); }
public void DFA_invalid_when_AcceptStates_empty() { var q0 = State.Create("q0").AssertSome(); var qs = new[] { q0 }.ToImmutableArray(); var dfa = new Dfa( ImmutableHashSet <char> .Empty, qs, ImmutableArray <State> .Empty, q0); dfa.IsValid.ShouldBeFalse(); }
public static void BuildAndShow(String filename, Regex r) { Nfa nfa = r.MkNfa(new Nfa.NameSource()); Console.WriteLine(nfa); Console.WriteLine("---"); Dfa dfa = nfa.ToDfa(); Console.WriteLine(dfa); Console.WriteLine("Writing DFA graph to file " + filename); dfa.WriteDot(filename); Console.WriteLine(); }
public IDfaSet Read() { var map = this.reader.ReadInt32Array(); var setsCount = this.reader.ReadInt32(); var sets = new Set[setsCount]; for (var s = 0; s < sets.Length; ++s) { var intervalCount = this.reader.ReadInt32(); var intervals = new Interval[intervalCount]; for (var i = 0; i < intervalCount; ++i) { var min = this.reader.ReadInt32(); var max = this.reader.ReadInt32(); intervals[i] = new Interval(min, max); } sets[s] = new Set(intervals); } var dfaCount = this.reader.ReadInt32(); var dfas = new Dfa[dfaCount]; for (var d = 0; d < dfaCount; ++d) { var stateCount = this.reader.ReadInt32(); var states = new DfaState[stateCount]; for (var s = 0; s < stateCount; ++s) { var final = this.reader.ReadBool(); var payload = this.reader.ReadInt32() - 1; states[s] = new DfaState(s, final, payload); } for (var s = 0; s < stateCount; ++s) { var transitionCount = this.reader.ReadInt32(); var transitions = new DfaTrans[transitionCount]; for (var t = 0; t < transitionCount; ++t) { var setId = this.reader.ReadInt32(); var targetId = this.reader.ReadInt32(); Debug.Assert(targetId < stateCount); transitions[t] = new DfaTrans(states[targetId], sets[setId]); } states[s].Transitions = transitions; } dfas[d] = new Dfa(states); } return(new DfaSet(dfas, map, dfas.Last())); }
public void DeadStatesTest() { var dfa = new Dfa <string>(); dfa.AddEdge(0, "A", 3); dfa.AddEdge(1, "B", 3); dfa.AddEdge(2, "C", 3); dfa.AddEdge(0, "E", 1); dfa.AddEdge(1, "E", 2); dfa.AddBadState(3); var emptyDfa = new Dfa <string>(); var rules = new Dictionary <string, IDfa <Optional <Rule <string> >, string> > { ["A"] = dfa, ["E"] = emptyDfa }; var grammar = new CompiledGrammar <string> { Rules = rules }; var nullables = new List <DfaAndState <string> > { new DfaAndState <string> { Dfa = emptyDfa, State = new ValueState <int>(0) } }; var firstSymbols = FirstHelper <string> .GetFirstSymbols(grammar, nullables); var expected = new[] { "E", "E", string.Empty, string.Empty }; for (int i = 0; i < 4; ++i) { var stateEntity = new DfaAndState <string> { Dfa = dfa, State = new ValueState <int>(i) }; string output = string.Join(',', firstSymbols[stateEntity].OrderBy(x => x)); Assert.AreEqual(expected[i], output, $"Unexpected output on test {i}: expected is [{expected[i]}], but found [{output}]"); } }
/// <summary> /// Search a given dataset for the given query /// </summary> /// <param name="query">What you are searching for</param> /// <param name="dataset">The dataset to search</param> /// <param optional="true" name="fuzziness"> /// The distance away from root to search. Default is 0 which means only exact matches can be found /// </param> /// <returns>A list of items found in the dataset given the query</returns> public override IEnumerable <string> Search(string query, IList <string> dataset, int fuzziness = 0) { List <string> matches = new List <string>(); Dfa levenshteinAutomata = _LevenshteinAutomata(query, fuzziness); string match = levenshteinAutomata.FindNextValidString("\u0001"); string prevLookup = ""; while (match != null) { string next = LookupFunc(match, dataset); if (next == null) { break; } int index = dataset.IndexOf(next); int indexPrevLookup = dataset.IndexOf(prevLookup); if (next.Contains(match)) { matches.Add(next); dataset.RemoveAt(index); next = dataset[index]; } else if (next == prevLookup) { dataset.RemoveAt(index); next = dataset[index]; } if (indexPrevLookup >= 0 && indexPrevLookup < dataset.Count) { dataset.RemoveAt(indexPrevLookup); } prevLookup = next; match = levenshteinAutomata.FindNextValidString(next); if (index >= dataset.Count) { break; } } return(matches); }
private static Dfa CreateLinearDfa(IReadOnlyList <Label> sequence) { var numStates = sequence.Count + 2; var allLabels = (Label[])Enum.GetValues(typeof(Label)); var dfa = new Dfa(numStates); for (var start = 0; start < numStates; start++) { foreach (var label in allLabels) { var end = (start < sequence.Count && sequence[start].Equals(label)) ? start + 1 : numStates - 1; dfa.Edges[start][label] = end; } } return(dfa); }
public void DumpTerminal(IWriter writer, string head, Dfa dfa) { writer.WriteLine($"{head}"); try { var iwriter = new IndentWriter(); iwriter.Indent(() => { new DfaDumper().Dump(iwriter, dfa); }); iwriter.Dump(writer); } catch (Exception e) { writer.WriteLine($"{e}"); } }
public void CompleteSimple() { // We build a DFA that accepts a* // And we complete it over { a, b } var dfa = new Dfa <char, char>(); dfa.InitialState = 'q'; dfa.AcceptingStates.Add('q'); dfa.AddTransition('q', 'a', 'q'); dfa.Alphabet.Add('b'); Assert.True(dfa.Complete('t')); var expectedStates = new[] { 'q', 't' }.ToHashSet(); Assert.True(expectedStates.SetEquals(dfa.States)); Assert.Equal(4, dfa.Transitions.Count); AssertTransition(dfa, 'q', 'a', 'q'); AssertTransition(dfa, 'q', 'b', 't'); AssertTransition(dfa, 't', 'a', 't'); AssertTransition(dfa, 't', 'b', 't'); }
public void LookaheadDfaVerySimpleTest() { var productions = new Dictionary <CharSymbol, IProduction <CharSymbol>[]>(); productions[new CharSymbol('E')] = new StringProduction[] { new StringProduction('E', "a") }; // production: E -> a DfaState <CharSymbol> s1 = new DfaState <CharSymbol>("1"); DfaState <CharSymbol> s2 = new DfaState <CharSymbol>("2"); DfaState <CharSymbol> sError = new DfaState <CharSymbol>("X"); var t1 = new List <KeyValuePair <CharSymbol, DfaState <CharSymbol> > > { new KeyValuePair <CharSymbol, DfaState <CharSymbol> >(CharSymbol.MinValue, sError), new KeyValuePair <CharSymbol, DfaState <CharSymbol> >(new CharSymbol('a'), s2), new KeyValuePair <CharSymbol, DfaState <CharSymbol> >(new CharSymbol('b'), sError) }; var t2 = new List <KeyValuePair <CharSymbol, DfaState <CharSymbol> > > { new KeyValuePair <CharSymbol, DfaState <CharSymbol> >(CharSymbol.MinValue, sError) }; var tError = new List <KeyValuePair <CharSymbol, DfaState <CharSymbol> > > { new KeyValuePair <CharSymbol, DfaState <CharSymbol> >(CharSymbol.MinValue, sError) }; s1.Initialize(0, t1); s2.Initialize(1, t2); sError.Initialize(0, tError); var automatons = new Dictionary <CharSymbol, Dfa <CharSymbol> >(); //automatons[new CharSymbol(Char.MinValue)] = automatons[new CharSymbol('E')] = new Dfa <CharSymbol>(s1); foreach (var i in automatons) { Console.WriteLine("dfa {0}: {1}", i.Key, i.Value.ToString()); } var grammar = new Grammar <CharSymbol>(new CharSymbol('E'), productions); grammar.InjectAutomatons(automatons); var ldfa = builder.Build(grammar, new CharSymbol('E'), s1); Console.WriteLine("Ldfa {0}", ldfa); }
public ActionTable(Dfa <SYMBOL_ENUM, TREE_NODE> dfa, Productions <SYMBOL_ENUM, TREE_NODE> productions, int lookaheadWidth) : base(null, null, null, productions.StartSymbol, productions.EofSymbol, productions.SyntaxErrorSymbol, lookaheadWidth) { this.symbolsRep = productions.SymbolsRep; this.symbols = productions.NonAndTerminals.ToList(); int symbolValuesWidth = 1 + productions.NonAndTerminals.Concat(productions.EofSymbol).Select(it => (int)(object)it).Max(); actionsTable = new IEnumerable <ParseAction <SYMBOL_ENUM, TREE_NODE> > [ dfa.IndexRange(), (int)Math.Pow(symbolValuesWidth, lookaheadWidth) ]; edgesTable = CreateEdgesTable(dfa.IndexRange(), symbolValuesWidth); recoveryTable = new IEnumerable <NfaCell <SYMBOL_ENUM, TREE_NODE> > [dfa.IndexRange(), symbolValuesWidth]; foreach (Node <SYMBOL_ENUM, TREE_NODE> node in dfa.Nodes) { foreach (KeyValuePair <SYMBOL_ENUM, Node <SYMBOL_ENUM, TREE_NODE> > edge in node.EdgesTo) { int edge_int = (int)(object)edge.Key; edgesTable[node.State.Index, edge_int] = edge.Value.State.Index; IEnumerable <NfaCell <SYMBOL_ENUM, TREE_NODE> > recovery_items = edge.Value.State.ParsingActiveItems.Where(it => it.IsAtRecoveryPoint).Select(it => it.CreateCell()).ToList(); if (recovery_items.Any()) { recoveryTable[node.State.Index, edge_int] = recovery_items; } } } }
private static Dfa <string, char> BuildLast2DifferentCharsDfa() { var dfa = new Dfa <string, char>(); dfa.InitialState = "S"; dfa.AcceptingStates.Add("AB"); dfa.AcceptingStates.Add("BA"); dfa.AddTransition("S", 'a', "A"); dfa.AddTransition("S", 'b', "B"); dfa.AddTransition("A", 'a', "AA"); dfa.AddTransition("A", 'b', "AB"); dfa.AddTransition("AA", 'a', "AA"); dfa.AddTransition("AA", 'b', "AB"); dfa.AddTransition("B", 'a', "BA"); dfa.AddTransition("B", 'b', "BB"); dfa.AddTransition("BB", 'a', "BA"); dfa.AddTransition("BB", 'b', "BB"); dfa.AddTransition("AB", 'a', "BA"); dfa.AddTransition("AB", 'b', "BB"); dfa.AddTransition("BA", 'a', "AA"); dfa.AddTransition("BA", 'b', "AB"); return(dfa); }
private void ProcessData() { TInput value; while (LinkedFifoBuffer <TInput> .TryGetValue(ref this.bufferPosition, out value)) { var newState = this.state; var newSymbol = this.ProcessStateMachine(ref newState, value); if (Dfa <TLetter> .IsEndState(newState)) { if (this.tokenSymbol.HasValue || newState == Dfa <TLetter> .Accept) { var position = this.bufferPosition; this.FlushPendingToken(); if (newState == Dfa <TLetter> .Accept) { this.tokenEnd = this.tokenStart = this.bufferPosition = position; // restore position after EOF letter this.ProcessEof(); } else { continue; } } else { this.HandleLexicalError(false); } } this.state = newState; if (newSymbol.HasValue) { this.tokenEnd = this.bufferPosition; this.tokenSymbol = newSymbol.Value; } } }
// // Regular languages, NFA, DFA // public static void CourseExercise() { var dfa = new Dfa <string>('A', new [] { 'B', 'E' }); dfa.AddTrans('A', "0", 'E'); dfa.AddTrans('A', "1", 'D'); dfa.AddTrans('B', "0", 'A'); dfa.AddTrans('B', "1", 'C'); dfa.AddTrans('C', "0", 'G'); dfa.AddTrans('C', "1", 'B'); dfa.AddTrans('D', "0", 'E'); dfa.AddTrans('D', "1", 'A'); dfa.AddTrans('E', "0", 'H'); dfa.AddTrans('E', "1", 'C'); dfa.AddTrans('F', "0", 'C'); dfa.AddTrans('F', "1", 'B'); dfa.AddTrans('G', "0", 'F'); dfa.AddTrans('G', "1", 'E'); dfa.AddTrans('H', "0", 'B'); dfa.AddTrans('H', "1", 'H'); var minDfa = dfa.ToMinimumDfa(); SaveFile("exercise.dot", DotLanguagePrinter.ToDotLanguage(minDfa)); }
public IStateTableWriter CreateStateWriter(Dfa dfa, ScannerStateTable tableFactory) => new UncompressedStateWriter(tableFactory);
public IStateTableWriter CreateStateWriter(Dfa dfa, ScannerStateTable tableFactory) => new CompressStateWriter(dfa, tableFactory);
public void ThreeDfasTest() { var firstDfa = new Dfa <string>(); firstDfa.AddEdge(0, "D", 1); firstDfa.AddEdge(0, "F", 4); firstDfa.AddEdge(0, "C", 3); firstDfa.AddEdge(0, "B", 2); firstDfa.AddEdge(2, "B", 7); firstDfa.AddEdge(3, "A", 5); firstDfa.AddEdge(4, "G", 6); firstDfa.AddEdge(6, "A", 5); var secondDfa = new Dfa <string>(); secondDfa.AddEdge(0, "B", 1); secondDfa.AddEdge(0, "C", 2); secondDfa.AddEdge(2, "A", 3); secondDfa.AddEdge(1, "E", 4); var thirdDfa = new Dfa <string>(); var rules = new Dictionary <string, IDfa <Optional <Rule <string> >, string> > { ["A"] = firstDfa, ["B"] = secondDfa, ["C"] = thirdDfa }; var grammar = new CompiledGrammar <string> { Rules = rules }; var nullables = new List <DfaAndState <string> > { new DfaAndState <string> { Dfa = thirdDfa, State = new ValueState <int>(0) } }; var firstSymbols = FirstHelper <string> .GetFirstSymbols(grammar, nullables); var expected = new[] { new[] { "A,B,C,D,F", string.Empty, "A,B,C,D,F", "A,B,C,D,F", "G", string.Empty, "A,B,C,D,F", string.Empty }, new[] { "A,B,C,D,F", "E", "A,B,C,D,F", string.Empty, string.Empty }, new[] { string.Empty } }; var size = new int[] { 8, 5, 1 }; var dfas = new ConcreteDfa <Optional <Rule <string> >, string>[] { firstDfa, secondDfa, thirdDfa }; for (int test = 0; test < 3; ++test) { for (int i = 0; i < size[test]; ++i) { var stateEntity = new DfaAndState <string> { Dfa = dfas[test], State = new ValueState <int>(i) }; string output = string.Join(',', firstSymbols[stateEntity].OrderBy(x => x)); Assert.AreEqual(expected[test][i], output, $"Unexpected output on test ({test}, {i}): expected is [{expected[test][i]}], but found [{output}]"); } } }
public IDfaWriter Create(Dfa dfa, ITableWriterFactory tableWriterFactory, ISyntaxErrorHandler syntaxErrorHandler) => new DfaSwitchWriter(dfa, syntaxErrorHandler);