public void TestSimple2() { var a1 = new ConcreteDfa <bool, char>(); // ab a1.AddEdge(0, 'b', 3); a1.AddEdge(0, 'a', 1); a1.AddEdge(1, 'b', 2); a1.Labels[0] = false; a1.Labels[1] = false; a1.Labels[2] = true; a1.Labels[3] = false; var a2 = new ConcreteDfa <bool, char>(); // (ab)* a2.AddEdge(0, 'a', 1); a2.AddEdge(1, 'b', 0); a2.Labels[0] = true; a2.Labels[1] = false; var merged1 = DfaMerger <int, char> .Merge( new Dictionary <int, IDfa <bool, char> > { { 1, a1 }, { 2, a2 } }, (labels) => !labels.Any()? 0 : labels.Min()); Assert.AreEqual(2, GetTargetLabel(merged1, string.Empty, 0)); Assert.AreEqual(0, GetTargetLabel(merged1, "a", 0)); Assert.AreEqual(1, GetTargetLabel(merged1, "ab", 0)); Assert.AreEqual(2, GetTargetLabel(merged1, "abab", 0)); Assert.AreEqual(2, GetTargetLabel(merged1, "ababab", 0)); Assert.AreEqual(0, GetTargetLabel(merged1, "ababa", 0)); Assert.IsTrue(DfaEquivalence <int, char> .AreEquivalent(merged1, merged1)); var merged2 = new ConcreteDfa <int, char>(); merged2.AddEdge(0, 'a', 1); merged2.AddEdge(1, 'b', 2); merged2.AddEdge(2, 'a', 3); merged2.AddEdge(3, 'b', 4); merged2.AddEdge(4, 'a', 3); merged2.AddEdge(0, 'b', 5); merged2.AddEdge(1, 'a', 5); merged2.AddEdge(2, 'b', 5); merged2.AddEdge(3, 'a', 5); merged2.AddEdge(4, 'b', 5); merged2.AddEdge(5, 'a', 5); merged2.AddEdge(5, 'b', 5); merged2.Labels[0] = 2; merged2.Labels[1] = 0; merged2.Labels[2] = 1; merged2.Labels[3] = 0; merged2.Labels[4] = 2; merged2.Labels[5] = 0; Assert.IsTrue(DfaEquivalence <int, char> .AreEquivalent(merged1, merged2)); }
public void SingleDfaTest() { var grammar = new CompiledGrammar <Tag>(); var rules = new Dictionary <Tag, IDfa <Optional <Rule <Tag> >, Tag> >(); var dfa = new ConcreteDfa <Optional <Rule <Tag> >, Tag>(); dfa.AddEdge(0, Tag.A, 1); dfa.AddEdge(1, Tag.A, 2); dfa.AddEdge(1, Tag.B, 1); dfa.AddEdge(2, Tag.A, 2); dfa.Labels.Add(0, Optional <Rule <Tag> > .None()); dfa.Labels.Add(1, Optional <Rule <Tag> > .None()); var r = new Rule <Tag> { Lhs = Tag.A }; dfa.Labels.Add(2, Optional <Rule <Tag> > .Some(r)); rules.Add(Tag.A, dfa); grammar.Rules = rules; var output = NullablesHelper <Tag> .GetNullableSymbols(grammar); Assert.AreEqual(1, output.Count); }
private static DfaAndState <string> GetMockState() { IDfa <Optional <Rule <string> >, string> dfa = new ConcreteDfa <Optional <Rule <string> >, string>(); return(new DfaAndState <string> { Dfa = dfa, State = dfa.StartingState() }); }
private static ConcreteDfa <bool, char> CreateLetterPlusDfa(char letter) { var result = new ConcreteDfa <bool, char>(); // 'letter'+ result.AddEdge(0, letter, 1); result.AddEdge(1, letter, 1); result.Labels[0] = false; result.Labels[1] = true; return(result); }
public void AlmostAllNullable() { var dfa1 = new ConcreteDfa <Optional <Rule <Tag> >, Tag>(); dfa1.AddEdge(0, Tag.B, 0); dfa1.AddEdge(0, Tag.A, 1); var rules1 = new Rule <Tag>() { Lhs = Tag.A, Rhs = new ConcatRegex <Tag>(new AtomicRegex <Tag>(Tag.B), new AtomicRegex <Tag>(Tag.A)) }; dfa1.Labels.Add(0, Optional <Rule <Tag> > .Some(rules1)); var rules2 = new Rule <Tag> { Lhs = Tag.A, Rhs = new ConcatRegex <Tag>(new AtomicRegex <Tag>(Tag.B), new AtomicRegex <Tag>(Tag.B)) }; dfa1.Labels.Add(1, Optional <Rule <Tag> > .Some(rules2)); var dfa2 = new ConcreteDfa <Optional <Rule <Tag> >, Tag>(); dfa2.AddEdge(0, Tag.A, 1); dfa2.AddEdge(0, Tag.B, 0); dfa2.AddEdge(0, Tag.B, 3); dfa2.AddEdge(1, Tag.A, 2); dfa2.AddEdge(2, Tag.A, 2); dfa2.AddEdge(2, Tag.B, 2); var rules3 = new Rule <Tag>() { Lhs = Tag.B, Rhs = new ConcatRegex <Tag>(new AtomicRegex <Tag>(Tag.A), new AtomicRegex <Tag>(Tag.A)) }; dfa2.Labels.Add(0, Optional <Rule <Tag> > .None()); dfa2.Labels.Add(1, Optional <Rule <Tag> > .None()); dfa2.Labels.Add(2, Optional <Rule <Tag> > .Some(rules3)); dfa2.Labels.Add(3, Optional <Rule <Tag> > .None()); var grammar = new CompiledGrammar <Tag>(); var rules = new Dictionary <Tag, IDfa <Optional <Rule <Tag> >, Tag> > { { Tag.A, dfa1 }, { Tag.B, dfa2 } }; grammar.Rules = rules; var nullables = NullablesHelper <Tag> .GetNullableSymbols(grammar); Assert.AreEqual(5, nullables.Count); }
public void TestSimple() { var a1 = CreateLetterPlusDfa('a'); // a+ var a2 = CreateLetterPlusDfa('b'); // b+ Assert.AreEqual(true, GetTargetLabel(a2, "bbb", false)); Assert.AreEqual(false, GetTargetLabel(a2, string.Empty, false)); var merged = DfaMerger <int, char> .Merge( new Dictionary <int, IDfa <bool, char> > { { 1, a1 }, { 2, a2 } }, (labels) => !labels.Any()? 0 : labels.Min()); Assert.AreEqual(1, GetTargetLabel(merged, "a", 0)); Assert.AreEqual(2, GetTargetLabel(merged, "b", 0)); Assert.AreEqual(2, GetTargetLabel(merged, "bb", 0)); Assert.AreEqual(2, GetTargetLabel(merged, "bbbbb", 0)); Assert.AreEqual(1, GetTargetLabel(merged, "aaaaaaaaaa", 0)); Assert.AreEqual(0, GetTargetLabel(merged, string.Empty, 0)); Assert.AreEqual(0, GetTargetLabel(merged, "baa", 0)); var merged2 = new ConcreteDfa <int, char>(); merged2.AddEdge(0, 'a', 1); merged2.AddEdge(0, 'b', 2); merged2.AddEdge(1, 'a', 1); merged2.AddEdge(1, 'b', 3); merged2.AddEdge(2, 'a', 3); merged2.AddEdge(2, 'b', 2); merged2.AddEdge(3, 'a', 3); merged2.AddEdge(3, 'b', 3); merged2.Labels[0] = 0; merged2.Labels[1] = 1; merged2.Labels[2] = 2; merged2.Labels[3] = 0; Assert.IsTrue(DfaEquivalence <int, char> .AreEquivalent(merged, merged2)); }
public void TestConflict() { var a1 = CreateLetterPlusDfa('a'); // a+ var merged1 = DfaMerger <int, char> .Merge( new Dictionary <int, IDfa <bool, char> > { { 1, a1 }, { 2, a1 } }, labels => !labels.Any()? 0 : labels.Min()); Assert.AreEqual(0, GetTargetLabel(merged1, string.Empty, 0)); Assert.AreEqual(1, GetTargetLabel(merged1, "a", 0)); Assert.AreEqual(0, GetTargetLabel(merged1, "b", 0)); var a1Numeric = new ConcreteDfa <int, char>(); // a+ a1Numeric.AddEdge(0, 'a', 1); a1Numeric.AddEdge(1, 'a', 1); a1Numeric.Labels[0] = 0; a1Numeric.Labels[1] = 1; Assert.IsTrue(DfaEquivalence <int, char> .AreEquivalent(merged1, a1Numeric)); }
public void TestGetAllStates() { var dfa = new ConcreteDfa <bool, char>(); Assert.AreEqual(dfa.GetAllStates().Count, 1); dfa.AddEdge(0, 'a', 1); dfa.AddEdge(1, 'b', 2); Assert.AreEqual(dfa.GetAllStates().Count, 3); dfa.AddEdge(0, 'c', 3); dfa.AddEdge(3, 'd', 2); dfa.AddEdge(0, 'e', 2); Assert.AreEqual(dfa.GetAllStates().Count, 4); dfa.AddEdge(2, 'f', 4); dfa.AddEdge(4, 'g', 0); dfa.AddEdge(0, 'h', 5); Assert.AreEqual(dfa.GetAllStates().Count, 6); }
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 void Test1() { // Z –> d | XYZ // Y –> c | a // X –> Y | ε var rules = new Dictionary <char, IDfa <Optional <Rule <char> >, char> >(); var zdfa = new ConcreteDfa <Optional <Rule <char> >, char>(); zdfa.Magic = 0; zdfa.AddEdge(0, 'X', 1); zdfa.AddEdge(1, 'Y', 2); zdfa.AddEdge(2, 'Z', 3); zdfa.AddEdge(0, 'd', 3); zdfa.Labels.Add(0, REJECT); zdfa.Labels.Add(1, REJECT); zdfa.Labels.Add(2, REJECT); zdfa.Labels.Add(3, this.ACCEPT('Z')); rules.Add('Z', zdfa); var ydfa = new ConcreteDfa <Optional <Rule <char> >, char>(); ydfa.Magic = 1; ydfa.AddEdge(0, 'c', 1); ydfa.AddEdge(0, 'a', 1); ydfa.Labels.Add(0, REJECT); ydfa.Labels.Add(1, this.ACCEPT('Y')); rules.Add('Y', ydfa); var xdfa = new ConcreteDfa <Optional <Rule <char> >, char>(); xdfa.Magic = 2; xdfa.AddEdge(0, 'Y', 1); xdfa.Labels.Add(0, this.ACCEPT('X')); xdfa.Labels.Add(1, this.ACCEPT('X')); rules.Add('X', xdfa); var grammar = new CompiledGrammar <char> { Rules = rules, StartSymbol = 'Z' }; var nullables = NullablesHelper <char> .GetNullableSymbols(grammar); { var output = nullables.OrderBy(x => (x.Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic).ThenBy(x => (x.State as ValueState <int>).Value).ToList(); Assert.AreEqual(4, output.Count); Assert.AreEqual(0, (output[0].Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic); Assert.AreEqual(3, (output[0].State as ValueState <int>).Value); Assert.AreEqual(1, (output[1].Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic); Assert.AreEqual(1, (output[1].State as ValueState <int>).Value); Assert.AreEqual(2, (output[2].Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic); Assert.AreEqual(0, (output[2].State as ValueState <int>).Value); Assert.AreEqual(2, (output[3].Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic); Assert.AreEqual(1, (output[3].State as ValueState <int>).Value); } var first = FirstHelper <char> .GetFirstSymbols(grammar, nullables); { var output = first.OrderBy(x => (x.Key.Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic).ThenBy(x => (x.Key.State as ValueState <int>).Value).ToList(); var symbols = output[0].Value.ToList(); // Z0 symbols.Sort(); Assert.AreEqual(5, symbols.Count); Assert.AreEqual('X', symbols[0]); Assert.AreEqual('Y', symbols[1]); Assert.AreEqual('a', symbols[2]); Assert.AreEqual('c', symbols[3]); Assert.AreEqual('d', symbols[4]); symbols = output[1].Value.ToList(); // Z1 symbols.Sort(); Assert.AreEqual(3, symbols.Count); Assert.AreEqual('Y', symbols[0]); Assert.AreEqual('a', symbols[1]); Assert.AreEqual('c', symbols[2]); symbols = output[2].Value.ToList(); // Z2 symbols.Sort(); Assert.AreEqual(6, symbols.Count); Assert.AreEqual('X', symbols[0]); Assert.AreEqual('Y', symbols[1]); Assert.AreEqual('Z', symbols[2]); Assert.AreEqual('a', symbols[3]); Assert.AreEqual('c', symbols[4]); Assert.AreEqual('d', symbols[5]); symbols = output[3].Value.ToList(); // Z3 Assert.AreEqual(0, symbols.Count); symbols = output[4].Value.ToList(); // Y0 symbols.Sort(); Assert.AreEqual(2, symbols.Count); Assert.AreEqual('a', symbols[0]); Assert.AreEqual('c', symbols[1]); symbols = output[5].Value.ToList(); // Y1 Assert.AreEqual(0, symbols.Count); symbols = output[6].Value.ToList(); // X0 symbols.Sort(); Assert.AreEqual(3, symbols.Count); Assert.AreEqual('Y', symbols[0]); Assert.AreEqual('a', symbols[1]); Assert.AreEqual('c', symbols[2]); symbols = output[7].Value.ToList(); // X1 Assert.AreEqual(0, symbols.Count); } var follow = FollowHelper <char> .GetFollowSymbols(grammar, nullables, first.InverseRelation(), '\uffff'); { var output = follow.OrderBy(x => (x.Key.Dfa as ConcreteDfa <Optional <Rule <char> >, char>).Magic).ThenBy(x => (x.Key.State as ValueState <int>).Value).ToList(); var symbols = output[0].Value.ToList(); // Z3 Assert.AreEqual(1, symbols.Count); Assert.AreEqual('\uffff', symbols[0]); symbols = output[1].Value.ToList(); // Y1 symbols.Sort(); Assert.AreEqual(6, symbols.Count); Assert.AreEqual('X', symbols[0]); Assert.AreEqual('Y', symbols[1]); Assert.AreEqual('Z', symbols[2]); Assert.AreEqual('a', symbols[3]); Assert.AreEqual('c', symbols[4]); Assert.AreEqual('d', symbols[5]); symbols = output[2].Value.ToList(); // X0 symbols.Sort(); Assert.AreEqual(3, symbols.Count); Assert.AreEqual('Y', symbols[0]); Assert.AreEqual('a', symbols[1]); Assert.AreEqual('c', symbols[2]); symbols = output[3].Value.ToList(); // X1 symbols.Sort(); Assert.AreEqual(3, symbols.Count); Assert.AreEqual('Y', symbols[0]); Assert.AreEqual('a', symbols[1]); Assert.AreEqual('c', symbols[2]); } }
public void Test0SimpleParens() { var rules = new Dictionary <char, IDfa <Optional <Rule <char> >, char> >(); var dfa = new ConcreteDfa <Optional <Rule <char> >, char>(); dfa.AddEdge(0, '(', 1); dfa.AddEdge(1, 'S', 2); dfa.AddEdge(2, ')', 3); dfa.Labels.Add(0, this.ACCEPT('S')); dfa.Labels.Add(1, REJECT); dfa.Labels.Add(2, REJECT); dfa.Labels.Add(3, this.ACCEPT('S')); rules.Add('S', dfa); var grammar = new CompiledGrammar <char> { Rules = rules, StartSymbol = 'S' }; var nullables = NullablesHelper <char> .GetNullableSymbols(grammar); { Assert.AreEqual(2, nullables.Count); var states = nullables.Select(x => ((ValueState <int>)x.State).Value).ToList(); states.Sort(); Assert.AreEqual(0, states[0]); Assert.AreEqual(3, states[1]); } var first = FirstHelper <char> .GetFirstSymbols(grammar, nullables); { var output = first.OrderBy(x => (x.Key.State as ValueState <int>).Value).ToList(); var symbols = output[0].Value.ToList(); Assert.AreEqual(1, symbols.Count); Assert.AreEqual('(', symbols[0]); symbols = output[1].Value.ToList(); symbols.Sort(); Assert.AreEqual(3, symbols.Count); Assert.AreEqual('(', symbols[0]); Assert.AreEqual(')', symbols[1]); Assert.AreEqual('S', symbols[2]); symbols = output[2].Value.ToList(); Assert.AreEqual(1, symbols.Count); Assert.AreEqual(')', symbols[0]); symbols = output[3].Value.ToList(); Assert.AreEqual(0, symbols.Count); } var follow = FollowHelper <char> .GetFollowSymbols(grammar, nullables, first.InverseRelation(), '\uffff'); { var output = follow.OrderBy(x => (x.Key.State as ValueState <int>).Value).ToList(); var symbols = output[0].Value.ToList(); // state 0 symbols.Sort(); Assert.AreEqual(2, symbols.Count); Assert.AreEqual(')', symbols[0]); Assert.AreEqual('\uffff', symbols[1]); symbols = output[1].Value.ToList(); // state 3 symbols.Sort(); Assert.AreEqual(2, symbols.Count); Assert.AreEqual(')', symbols[0]); Assert.AreEqual('\uffff', symbols[1]); } }