2024-08-18 12:01:27 +08:00
|
|
|
|
using CanonSharp.Pascal.Scanner;
|
2024-08-13 14:46:11 +08:00
|
|
|
|
using CanonSharp.Tests.Utils;
|
|
|
|
|
|
2024-08-18 12:01:27 +08:00
|
|
|
|
namespace CanonSharp.Tests.ScannerTests;
|
2024-08-13 14:46:11 +08:00
|
|
|
|
|
|
|
|
|
public class LexicalParserTests : LexicalTestBase
|
|
|
|
|
{
|
|
|
|
|
[Fact]
|
|
|
|
|
public void LexicalParserTest1()
|
|
|
|
|
{
|
|
|
|
|
const string pascalProgram = """
|
|
|
|
|
program HelloWorld;
|
|
|
|
|
var
|
|
|
|
|
message: char;
|
|
|
|
|
begin
|
|
|
|
|
message := 'h';
|
|
|
|
|
writeln(message);
|
|
|
|
|
end.
|
|
|
|
|
""";
|
|
|
|
|
|
|
|
|
|
ValidateLexicalTokens(LexicalScanner.PascalParser(), pascalProgram, [
|
|
|
|
|
(LexicalTokenType.Keyword, "program"),
|
|
|
|
|
(LexicalTokenType.Identifier, "HelloWorld"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "var"),
|
|
|
|
|
(LexicalTokenType.Identifier, "message"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ":"),
|
|
|
|
|
(LexicalTokenType.Keyword, "char"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "begin"),
|
|
|
|
|
(LexicalTokenType.Identifier, "message"),
|
|
|
|
|
(LexicalTokenType.Operator, ":="),
|
|
|
|
|
(LexicalTokenType.Character, "h"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Identifier, "writeln"),
|
|
|
|
|
(LexicalTokenType.Delimiter, "("),
|
|
|
|
|
(LexicalTokenType.Identifier, "message"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ")"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "end"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ".")
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void LexicalParserTest2()
|
|
|
|
|
{
|
|
|
|
|
const string program = """
|
|
|
|
|
program main;
|
|
|
|
|
var
|
|
|
|
|
ab: integer;
|
|
|
|
|
begin
|
|
|
|
|
ab := 3;
|
|
|
|
|
write(ab);
|
|
|
|
|
end.
|
|
|
|
|
""";
|
|
|
|
|
|
|
|
|
|
ValidateLexicalTokens(LexicalScanner.PascalParser(), program, [
|
|
|
|
|
(LexicalTokenType.Keyword, "program"),
|
|
|
|
|
(LexicalTokenType.Identifier, "main"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "var"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ":"),
|
|
|
|
|
(LexicalTokenType.Keyword, "integer"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "begin"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Operator, ":="),
|
|
|
|
|
(LexicalTokenType.ConstInteger, "3"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Identifier, "write"),
|
|
|
|
|
(LexicalTokenType.Delimiter, "("),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ")"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "end"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ".")
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void LexicalParserTest3()
|
|
|
|
|
{
|
|
|
|
|
const string pascalProgram = """
|
|
|
|
|
{test}
|
|
|
|
|
program main;
|
|
|
|
|
var
|
|
|
|
|
ab, ba: integer;
|
|
|
|
|
begin
|
|
|
|
|
ab := 3;
|
|
|
|
|
ba := 5;
|
|
|
|
|
ab := 5;
|
|
|
|
|
write(ab + ba);
|
|
|
|
|
end.
|
|
|
|
|
""";
|
|
|
|
|
|
|
|
|
|
ValidateLexicalTokens(LexicalScanner.PascalParser(), pascalProgram, [
|
|
|
|
|
(LexicalTokenType.Keyword, "program"),
|
|
|
|
|
(LexicalTokenType.Identifier, "main"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "var"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ","),
|
|
|
|
|
(LexicalTokenType.Identifier, "ba"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ":"),
|
|
|
|
|
(LexicalTokenType.Keyword, "integer"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "begin"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Operator, ":="),
|
|
|
|
|
(LexicalTokenType.ConstInteger, "3"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ba"),
|
|
|
|
|
(LexicalTokenType.Operator, ":="),
|
|
|
|
|
(LexicalTokenType.ConstInteger, "5"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Operator, ":="),
|
|
|
|
|
(LexicalTokenType.ConstInteger, "5"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Identifier, "write"),
|
|
|
|
|
(LexicalTokenType.Delimiter, "("),
|
|
|
|
|
(LexicalTokenType.Identifier, "ab"),
|
|
|
|
|
(LexicalTokenType.Operator, "+"),
|
|
|
|
|
(LexicalTokenType.Identifier, "ba"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ")"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ";"),
|
|
|
|
|
(LexicalTokenType.Keyword, "end"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ".")
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-18 12:01:27 +08:00
|
|
|
|
[Fact]
|
|
|
|
|
public void LexicalParserTest4()
|
|
|
|
|
{
|
|
|
|
|
ValidateLexicalTokens(LexicalScanner.PascalParser(), "array [0..9] of integer", [
|
|
|
|
|
(LexicalTokenType.Keyword, "array"),
|
|
|
|
|
(LexicalTokenType.Delimiter, "["),
|
|
|
|
|
(LexicalTokenType.ConstInteger, "0"),
|
|
|
|
|
(LexicalTokenType.Delimiter, ".."),
|
|
|
|
|
(LexicalTokenType.ConstInteger, "9"),
|
|
|
|
|
(LexicalTokenType.Delimiter, "]"),
|
|
|
|
|
(LexicalTokenType.Keyword, "of"),
|
|
|
|
|
(LexicalTokenType.Keyword, "integer")
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-13 14:46:11 +08:00
|
|
|
|
[Theory]
|
|
|
|
|
[InlineData("""
|
|
|
|
|
program exFunction;
|
|
|
|
|
var
|
|
|
|
|
a, b, ret : integer;
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
a := 100;
|
|
|
|
|
b := 200;
|
|
|
|
|
{ calling a function to get max valued }
|
|
|
|
|
ret := a - b;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end.
|
|
|
|
|
""", 29)]
|
|
|
|
|
[InlineData("""
|
|
|
|
|
{
|
|
|
|
|
This is a block comment that does closed.
|
|
|
|
|
}
|
|
|
|
|
program CommentClosed;
|
|
|
|
|
""", 3)]
|
|
|
|
|
[InlineData("""
|
|
|
|
|
{}
|
|
|
|
|
program CommentClosed;
|
|
|
|
|
""", 3)]
|
|
|
|
|
public void LexicalParserTest(string input, int count)
|
|
|
|
|
{
|
|
|
|
|
LexicalScanner scanner = new();
|
|
|
|
|
|
|
|
|
|
List<LexicalToken> tokens = scanner.Tokenize(new StringReadState(input)).ToList();
|
|
|
|
|
Assert.Equal(count, tokens.Count);
|
|
|
|
|
}
|
|
|
|
|
}
|