using Canon.Core.Enums; using Canon.Core.GrammarParser; using Xunit.Abstractions; namespace Canon.Tests.GrammarParserTests; public class SimpleGrammarWithEmptyTests(ITestOutputHelper testOutputHelper) { /// /// 带有空产生式的简单语法(课后题4.18) /// S -> A /// A -> BA | ε /// B -> aB | b /// 为了方便测试指定 /// A ProgramStruct /// B ProgramBody /// a Identifier /// b Identifier /// // private readonly ITestOutputHelper _testOutputHelper; private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; private static readonly Dictionary>> s_simpleGrammar = new() { { new NonTerminator(NonTerminatorType.StartNonTerminator), [ [new NonTerminator(NonTerminatorType.ProgramStruct)] ] }, { new NonTerminator(NonTerminatorType.ProgramStruct), [ [ new NonTerminator(NonTerminatorType.ProgramBody), new NonTerminator(NonTerminatorType.ProgramStruct) ], [] ] }, { new NonTerminator(NonTerminatorType.ProgramBody), [ [ Terminator.IdentifierTerminator, new NonTerminator(NonTerminatorType.ProgramBody) ], [Terminator.IdentifierTerminator] ] } }; [Fact] public void FirstSetTest() { GrammarBuilder builder = new() { Generators = s_simpleGrammar, Begin = new NonTerminator(NonTerminatorType.StartNonTerminator) }; builder.Build(); Assert.Contains(builder.FirstSet, pair => pair.Key == new NonTerminator(NonTerminatorType.StartNonTerminator)); Assert.Contains(builder.FirstSet, pair => pair.Key == new NonTerminator(NonTerminatorType.ProgramStruct)); Assert.Contains(builder.FirstSet, pair => pair.Key == new NonTerminator(NonTerminatorType.ProgramBody)); foreach (HashSet terminators in builder.FirstSet.Values) { Assert.Single(terminators); Assert.Contains(Terminator.IdentifierTerminator, terminators); } } [Fact] public void StatsTest() { GrammarBuilder builder = new() { Generators = s_simpleGrammar, Begin = new NonTerminator(NonTerminatorType.StartNonTerminator) }; Grammar grammar = builder.Build(); Assert.Equal(6, builder.Automation.Count); Assert.Contains(new NonTerminator(NonTerminatorType.ProgramStruct), grammar.BeginState.Transformer.Keys); Assert.Contains(new NonTerminator(NonTerminatorType.ProgramBody), grammar.BeginState.Transformer.Keys); Assert.Contains(Terminator.IdentifierTerminator, grammar.BeginState.Transformer.Keys); Assert.Equal(7, grammar.BeginState.Expressions.Count); _testOutputHelper.WriteLine("--- 0 ---"); _testOutputHelper.WriteLine(grammar.BeginState.ToString()); LrState state1 = grammar.BeginState.Transformer[new NonTerminator(NonTerminatorType.ProgramStruct)]; Assert.Single(state1.Expressions); _testOutputHelper.WriteLine("--- 1 ---"); _testOutputHelper.WriteLine(state1.ToString()); LrState state2 = grammar.BeginState.Transformer[new NonTerminator(NonTerminatorType.ProgramBody)]; Assert.Contains(new NonTerminator(NonTerminatorType.ProgramStruct), state2.Transformer.Keys); Assert.Contains(new NonTerminator(NonTerminatorType.ProgramBody), state2.Transformer.Keys); Assert.Contains(Terminator.IdentifierTerminator, state2.Transformer.Keys); Assert.Equal(7, state2.Expressions.Count); _testOutputHelper.WriteLine("--- 2 ---"); _testOutputHelper.WriteLine(state2.ToString()); LrState state3 = grammar.BeginState.Transformer[Terminator.IdentifierTerminator]; Assert.Contains(new NonTerminator(NonTerminatorType.ProgramBody), state3.Transformer.Keys); Assert.Contains(Terminator.IdentifierTerminator, state3.Transformer.Keys); Assert.Equal(8, state3.Expressions.Count); _testOutputHelper.WriteLine("--- 3 ---"); _testOutputHelper.WriteLine(state3.ToString()); LrState state4 = state2.Transformer[new NonTerminator(NonTerminatorType.ProgramStruct)]; Assert.Empty(state4.Transformer); Assert.Single(state4.Expressions); _testOutputHelper.WriteLine("--- 4 ---"); _testOutputHelper.WriteLine(state4.ToString()); LrState state5 = state3.Transformer[new NonTerminator(NonTerminatorType.ProgramBody)]; Assert.Empty(state5.Transformer); Assert.Equal(2, state5.Expressions.Count); _testOutputHelper.WriteLine("--- 5 ---"); _testOutputHelper.WriteLine(state5.ToString()); } }