Canon/Canon.Tests/GrammarParserTests/SimpleGrammarWithEmptyTests.cs
jackfiled 6130adfa7c feat: 按照open_set中的示例调整语法 (#71)
添加了构建LR分析表冲突的报错

Reviewed-on: PostGuard/Canon#71
2024-05-01 21:06:27 +08:00

165 lines
5.9 KiB
C#

using Canon.Core.Enums;
using Canon.Core.Exceptions;
using Canon.Core.GrammarParser;
using Xunit.Abstractions;
namespace Canon.Tests.GrammarParserTests;
public class SimpleGrammarWithEmptyTests(ITestOutputHelper testOutputHelper)
{
/// <summary>
/// 带有空产生式的简单语法(课后题4.18)
/// S -> A
/// A -> BA | ε
/// B -> aB | a
/// 为了方便测试指定
/// A ProgramStruct
/// B ProgramBody
/// a Identifier
/// </summary>
private readonly ITestOutputHelper _testOutputHelper = testOutputHelper;
private static readonly Dictionary<NonTerminator, List<List<TerminatorBase>>> s_simpleGrammar = new()
{
{
new NonTerminator(NonTerminatorType.StartNonTerminator), [
[new NonTerminator(NonTerminatorType.ProgramStruct)]
]
},
{
new NonTerminator(NonTerminatorType.ProgramStruct), [
[
new NonTerminator(NonTerminatorType.ProgramBody),
new NonTerminator(NonTerminatorType.ProgramStruct)
],
[Terminator.EmptyTerminator]
]
},
{
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 =>
{
if (pair.Key == new NonTerminator(NonTerminatorType.StartNonTerminator))
{
Assert.Equal(2, pair.Value.Count);
Assert.Contains(Terminator.IdentifierTerminator, pair.Value);
Assert.Contains(Terminator.EmptyTerminator, pair.Value);
return true;
}
return false;
});
Assert.Contains(builder.FirstSet, pair =>
{
if (pair.Key == new NonTerminator(NonTerminatorType.ProgramStruct))
{
Assert.Equal(2, pair.Value.Count);
Assert.Contains(Terminator.IdentifierTerminator, pair.Value);
Assert.Contains(Terminator.EmptyTerminator, pair.Value);
return true;
}
return true;
});
Assert.Contains(builder.FirstSet, pair =>
{
if (pair.Key == new NonTerminator(NonTerminatorType.ProgramBody))
{
Assert.Single(pair.Value);
Assert.Contains(Terminator.IdentifierTerminator, pair.Value);
return true;
}
return false;
});
}
[Fact]
public void StatesTest()
{
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());
}
[Fact]
public void ParserTest()
{
GrammarBuilder builder = new()
{
Generators = s_simpleGrammar, Begin = new NonTerminator(NonTerminatorType.StartNonTerminator)
};
Grammar grammar = builder.Build();
Assert.Throws<ReduceAndShiftConflictException>(() => grammar.ToGrammarParser());
}
}