add: basic grammar parser including expression and program.
This commit is contained in:
245
CanonSharp.Tests/ParserTests/ExpressionParserTests.cs
Normal file
245
CanonSharp.Tests/ParserTests/ExpressionParserTests.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using CanonSharp.Pascal.Parser;
|
||||
using CanonSharp.Pascal.SyntaxTree;
|
||||
using CanonSharp.Tests.Utils;
|
||||
|
||||
namespace CanonSharp.Tests.ParserTests;
|
||||
|
||||
public sealed class ExpressionParserTests : GrammarParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void BoolTest()
|
||||
{
|
||||
BooleanValueNode node = RunParser<BooleanValueNode>(GrammarParser.FactorParser(), "false");
|
||||
Assert.False(node.Value);
|
||||
|
||||
node = RunParser<BooleanValueNode>(GrammarParser.FactorParser(), "true");
|
||||
Assert.True(node.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NumberTest()
|
||||
{
|
||||
IntegerValueNode integerValueNode = RunParser<IntegerValueNode>(GrammarParser.FactorParser(), "123456");
|
||||
Assert.Equal(123456, integerValueNode.Value);
|
||||
|
||||
FloatValueNode floatValueNode = RunParser<FloatValueNode>(GrammarParser.FactorParser(), "123.456");
|
||||
Assert.Equal(123.456, floatValueNode.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnaryOperatorTest()
|
||||
{
|
||||
UnaryOperatorNode node = RunParser<UnaryOperatorNode>(GrammarParser.FactorParser(), "- 123");
|
||||
Assert.Equal(UnaryOperatorType.Minus, node.OperatorType);
|
||||
Assert.Equal(123, node.Node.Convert<IntegerValueNode>().Value);
|
||||
|
||||
node = RunParser<UnaryOperatorNode>(GrammarParser.FactorParser(), "+ 100.5");
|
||||
Assert.Equal(UnaryOperatorType.Plus, node.OperatorType);
|
||||
Assert.Equal(100.5, node.Node.Convert<FloatValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IdentifierTest()
|
||||
{
|
||||
VariableNode node = RunParser<VariableNode>(GrammarParser.FactorParser(), "temp");
|
||||
Assert.Equal("temp", node.IdentifierName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SingleTermTest()
|
||||
{
|
||||
VariableNode node = RunParser<VariableNode>(GrammarParser.TermParser(), "temp");
|
||||
Assert.Equal("temp", node.IdentifierName);
|
||||
|
||||
UnaryOperatorNode unaryOperatorNode = RunParser<UnaryOperatorNode>(GrammarParser.TermParser(), "- 123");
|
||||
Assert.Equal(UnaryOperatorType.Minus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(123, unaryOperatorNode.Node.Convert<IntegerValueNode>().Value);
|
||||
|
||||
unaryOperatorNode = RunParser<UnaryOperatorNode>(GrammarParser.TermParser(), "+ 100.5");
|
||||
Assert.Equal(UnaryOperatorType.Plus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(100.5, unaryOperatorNode.Node.Convert<FloatValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultiplyTermTest1()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.TermParser(), "10 / 2");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Divide, node.OperatorType);
|
||||
Assert.Equal(10, node.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(2, node.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultiplyTermTest2()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.TermParser(), "10 div 2");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.IntegerDivide, node.OperatorType);
|
||||
Assert.Equal(10, node.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(2, node.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultiplyTermTest3()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.TermParser(), "temp * 2 div 3");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.IntegerDivide, node.OperatorType);
|
||||
Assert.Equal(3, node.Right.Convert<IntegerValueNode>().Value);
|
||||
BinaryOperatorNode leftNode = node.Left.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.Multiply, leftNode.OperatorType);
|
||||
Assert.Equal("temp", leftNode.Left.Convert<VariableNode>().IdentifierName);
|
||||
Assert.Equal(2, leftNode.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleExpressionTest1()
|
||||
{
|
||||
VariableNode node = RunParser<VariableNode>(GrammarParser.SimpleExpressionParser(), "temp");
|
||||
Assert.Equal("temp", node.IdentifierName);
|
||||
|
||||
UnaryOperatorNode unaryOperatorNode =
|
||||
RunParser<UnaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "- 123");
|
||||
Assert.Equal(UnaryOperatorType.Minus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(123, unaryOperatorNode.Node.Convert<IntegerValueNode>().Value);
|
||||
|
||||
unaryOperatorNode = RunParser<UnaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "+ 100.5");
|
||||
Assert.Equal(UnaryOperatorType.Plus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(100.5, unaryOperatorNode.Node.Convert<FloatValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleExpressionTest2()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "1 + 1");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Add, node.OperatorType);
|
||||
Assert.Equal(1, node.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(1, node.Right.Convert<IntegerValueNode>().Value);
|
||||
|
||||
node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "1 + 1 - 2");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Subtract, node.OperatorType);
|
||||
Assert.Equal(2, node.Right.Convert<IntegerValueNode>().Value);
|
||||
|
||||
BinaryOperatorNode leftNode = node.Left.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.Add, leftNode.OperatorType);
|
||||
Assert.Equal(1, leftNode.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(1, leftNode.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleExpressionTest3()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "1 - 2 * 5");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Subtract, node.OperatorType);
|
||||
Assert.Equal(1, node.Left.Convert<IntegerValueNode>().Value);
|
||||
|
||||
BinaryOperatorNode rightNode = node.Right.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.Multiply, rightNode.OperatorType);
|
||||
Assert.Equal(2, rightNode.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(5, rightNode.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleExpressionTest4()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "1 + +1");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Add, node.OperatorType);
|
||||
Assert.Equal(1, node.Left.Convert<IntegerValueNode>().Value);
|
||||
UnaryOperatorNode unaryOperatorNode = node.Right.Convert<UnaryOperatorNode>();
|
||||
Assert.Equal(UnaryOperatorType.Plus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(1, unaryOperatorNode.Node.Convert<IntegerValueNode>().Value);
|
||||
|
||||
node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "1 - -1");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Subtract, node.OperatorType);
|
||||
Assert.Equal(1, node.Left.Convert<IntegerValueNode>().Value);
|
||||
unaryOperatorNode = node.Right.Convert<UnaryOperatorNode>();
|
||||
Assert.Equal(UnaryOperatorType.Minus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(1, unaryOperatorNode.Node.Convert<IntegerValueNode>().Value);
|
||||
|
||||
node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "+ 1 - - 1");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Subtract, node.OperatorType);
|
||||
unaryOperatorNode = node.Left.Convert<UnaryOperatorNode>();
|
||||
Assert.Equal(UnaryOperatorType.Plus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(1, unaryOperatorNode.Node.Convert<IntegerValueNode>().Value);
|
||||
unaryOperatorNode = node.Right.Convert<UnaryOperatorNode>();
|
||||
Assert.Equal(UnaryOperatorType.Minus, unaryOperatorNode.OperatorType);
|
||||
Assert.Equal(1, unaryOperatorNode.Node.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleExpressionTest5()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.SimpleExpressionParser(),
|
||||
"true and temp or temp and false");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Or, node.OperatorType);
|
||||
|
||||
BinaryOperatorNode left = node.Left.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.And, left.OperatorType);
|
||||
BinaryOperatorNode right = node.Right.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.And, right.OperatorType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExpressionTest1()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.ExpressionParser(),
|
||||
"true and temp or temp and false");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Or, node.OperatorType);
|
||||
|
||||
BinaryOperatorNode left = node.Left.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.And, left.OperatorType);
|
||||
BinaryOperatorNode right = node.Right.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.And, right.OperatorType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExpressionTest2()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.ExpressionParser(), "2 >= 1");
|
||||
Assert.Equal(BinaryOperatorType.GreaterEqual, node.OperatorType);
|
||||
Assert.Equal(2, node.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(1, node.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExpressionTest3()
|
||||
{
|
||||
BinaryOperatorNode node = RunParser<BinaryOperatorNode>(GrammarParser.ExpressionParser(), "(1 + 1) * 2");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Multiply, node.OperatorType);
|
||||
Assert.Equal(2, node.Right.Convert<IntegerValueNode>().Value);
|
||||
|
||||
node = node.Left.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.Add, node.OperatorType);
|
||||
Assert.Equal(1, node.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(1, node.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExpressionsTest1()
|
||||
{
|
||||
List<BinaryOperatorNode> nodes =
|
||||
RunParser<BinaryOperatorNode>(GrammarParser.ExpressionsParser(), "1 + 1, 2 * 3");
|
||||
|
||||
Assert.Equal(BinaryOperatorType.Add, nodes[0].OperatorType);
|
||||
Assert.Equal(BinaryOperatorType.Multiply, nodes[1].OperatorType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VariableTest1()
|
||||
{
|
||||
VariableNode node = RunParser<VariableNode>(GrammarParser.VariableParser(), "temp");
|
||||
Assert.Equal("temp", node.IdentifierName);
|
||||
}
|
||||
|
||||
|
||||
}
|
41
CanonSharp.Tests/ParserTests/ProgramParserTests.cs
Normal file
41
CanonSharp.Tests/ParserTests/ProgramParserTests.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using CanonSharp.Pascal.SyntaxTree;
|
||||
using CanonSharp.Tests.Utils;
|
||||
|
||||
namespace CanonSharp.Tests.ParserTests;
|
||||
|
||||
public class ProgramParserTests : GrammarParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ProgramParseTest1()
|
||||
{
|
||||
Program program = ProgramParse("""
|
||||
program main;
|
||||
begin
|
||||
end.
|
||||
""");
|
||||
|
||||
Assert.Equal("main", program.Head.ProgramName.LiteralValue);
|
||||
Assert.Empty(program.Body.MainBlock.Statements);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgramParseTest2()
|
||||
{
|
||||
Program program = ProgramParse("""
|
||||
program main;
|
||||
begin
|
||||
temp := 1 + 1;
|
||||
end.
|
||||
""");
|
||||
|
||||
Assert.Equal("main", program.Head.ProgramName.LiteralValue);
|
||||
|
||||
AssignNode assignNode = program.Body.MainBlock.Statements[0].Convert<AssignNode>();
|
||||
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||
|
||||
BinaryOperatorNode binaryOperatorNode = assignNode.Expression.Convert<BinaryOperatorNode>();
|
||||
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
||||
Assert.Equal(1, binaryOperatorNode.Left.Convert<IntegerValueNode>().Value);
|
||||
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
}
|
82
CanonSharp.Tests/ParserTests/StatementParserTests.cs
Normal file
82
CanonSharp.Tests/ParserTests/StatementParserTests.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using CanonSharp.Pascal.Parser;
|
||||
using CanonSharp.Pascal.SyntaxTree;
|
||||
using CanonSharp.Tests.Utils;
|
||||
|
||||
namespace CanonSharp.Tests.ParserTests;
|
||||
|
||||
public class StatementParserTests : GrammarParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void StatementTest1()
|
||||
{
|
||||
AssignNode node = RunParser<AssignNode>(GrammarParser.StatementParser(), "temp := 1");
|
||||
|
||||
Assert.Equal("temp", node.Variable.IdentifierName);
|
||||
Assert.Equal(1, node.Expression.Convert<IntegerValueNode>().Value);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("""
|
||||
begin
|
||||
temp := 1 + 1;
|
||||
flag := true and false;
|
||||
end
|
||||
""")]
|
||||
[InlineData("""
|
||||
begin
|
||||
temp := 1 + 1;
|
||||
flag := true and false
|
||||
end
|
||||
""")]
|
||||
public void CompoundStatementTest1(string input)
|
||||
{
|
||||
BlockNode node = RunParser<BlockNode>(GrammarParser.CompoundStatementParser(), input);
|
||||
|
||||
Assert.Equal(2, node.Statements.Count);
|
||||
AssignNode assignNode = node.Statements[0].Convert<AssignNode>();
|
||||
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||
|
||||
assignNode = node.Statements[1].Convert<AssignNode>();
|
||||
Assert.Equal("flag", assignNode.Variable.IdentifierName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompoundStatementTest2()
|
||||
{
|
||||
BlockNode node = RunParser<BlockNode>(GrammarParser.CompoundStatementParser(), "begin end");
|
||||
Assert.Empty(node.Statements);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgramHeadTest1()
|
||||
{
|
||||
ProgramHead head = RunParser<ProgramHead>(GrammarParser.ProgramHeadParser(), "program main");
|
||||
|
||||
Assert.Equal("main", head.ProgramName.LiteralValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("""
|
||||
begin
|
||||
temp := 1 + 1;
|
||||
flag := true and false;
|
||||
end
|
||||
""")]
|
||||
[InlineData("""
|
||||
begin
|
||||
temp := 1 + 1;
|
||||
flag := true and false
|
||||
end
|
||||
""")]
|
||||
public void ProgramBodyTest1(string input)
|
||||
{
|
||||
BlockNode node = RunParser<ProgramBody>(GrammarParser.ProgramBodyParser(), input).MainBlock;
|
||||
|
||||
Assert.Equal(2, node.Statements.Count);
|
||||
AssignNode assignNode = node.Statements[0].Convert<AssignNode>();
|
||||
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||
|
||||
assignNode = node.Statements[1].Convert<AssignNode>();
|
||||
Assert.Equal("flag", assignNode.Variable.IdentifierName);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user