feat-generater (#69)
Reviewed-on: PostGuard/Canon#69 Co-authored-by: Lan_G <2911328695@qq.com> Co-committed-by: Lan_G <2911328695@qq.com>
This commit is contained in:
35
Canon.Tests/CodeGeneratorTests/BasicTest.cs
Normal file
35
Canon.Tests/CodeGeneratorTests/BasicTest.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Canon.Core.SemanticParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CodeGeneratorTests;
|
||||
|
||||
public class BasicTest
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public BasicTest(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgramStructTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nint main()\n{\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
}
|
64
Canon.Tests/CodeGeneratorTests/DeclarationTests.cs
Normal file
64
Canon.Tests/CodeGeneratorTests/DeclarationTests.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Canon.Core.SemanticParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CodeGeneratorTests;
|
||||
|
||||
public class DeclarationTests
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public DeclarationTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstDeclarationTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
const a = 'a'; b = 200; c = 3.14; d = 'm';
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nconst char a = 'a';\nconst " +
|
||||
"int b = 200;\nconst double c = 3.14;\nconst char d = 'm';\nint main()\n{\n;\n\nreturn 0;\n}\n",
|
||||
visitor.Builder.Build());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarDeclarationTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a, b, c:array[3..6, 4..999, 0..7, 8..80] of real;
|
||||
d, e, f:integer;
|
||||
g, h:array [6..8] of boolean;
|
||||
i, j:char;
|
||||
m, n:integer;
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\ndouble c[4][996][8][73]," +
|
||||
" b[4][996][8][73], a[4][996][8][73];\nint f, e, d;\nbool h[3], g[3];\nchar j, i;" +
|
||||
"\nint n, m;\nint main()\n{\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
}
|
66
Canon.Tests/CodeGeneratorTests/ExpressionTests.cs
Normal file
66
Canon.Tests/CodeGeneratorTests/ExpressionTests.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using Canon.Core.SemanticParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CodeGeneratorTests;
|
||||
|
||||
public class ExpressionTests
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public ExpressionTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExpressionTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a, b:integer; flag, tag:boolean;
|
||||
begin
|
||||
a := 1;
|
||||
b := a + b * 1 / 1 - 1 div 1 - - 2;
|
||||
tag := flag or tag;
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nint b, a;\n" +
|
||||
"bool tag, flag;\nint main()\n{\na = 1;\nb = a + b * 1 /(double)1 - 1 / 1 - (-2);" +
|
||||
"\ntag = flag || tag;\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ArrayTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a: array[9..12, 3..5, 6..20] of real; b: array[5..10] of integer;
|
||||
begin
|
||||
a[9, 4, 20] := 3.6 + b[6] - a[12, 5, 6];
|
||||
b[5] := 250;
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\ndouble a[4][3][15];" +
|
||||
"\nint b[6];\nint main()\n{\na[9-9][4-3][20-6] = 3.6 + b[6-5] - a[12-9][5-3][6-6];" +
|
||||
"\nb[5-5] = 250;\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
|
||||
}
|
40
Canon.Tests/CodeGeneratorTests/ReadTest.cs
Normal file
40
Canon.Tests/CodeGeneratorTests/ReadTest.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Canon.Core.SemanticParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CodeGeneratorTests;
|
||||
|
||||
public class ReadTest
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public ReadTest(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleReadTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a, b:integer;
|
||||
begin
|
||||
read(a);
|
||||
write(b + 1);
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nint b, a;\n" +
|
||||
"bool tag, flag;\nint main()\n{\na = 1;\nb = a + b * 1 /(double)1 - 1 / 1 - (-2);" +
|
||||
"\ntag = flag || tag;\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
}
|
118
Canon.Tests/CodeGeneratorTests/StatementTests.cs
Normal file
118
Canon.Tests/CodeGeneratorTests/StatementTests.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using Canon.Core.SemanticParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CodeGeneratorTests;
|
||||
|
||||
public class StatementTests
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public StatementTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IfTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a:integer;
|
||||
begin
|
||||
a := 1;
|
||||
if a = 1 then
|
||||
a := 1
|
||||
else
|
||||
begin
|
||||
if a = 2 + a then
|
||||
a := a
|
||||
else a := 999;
|
||||
end;
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nint a;\nint main()\n" +
|
||||
"{\na = 1;\nif(a == 1)\na = 1;\nelse\n{\nif(a == 2 + a)\n" +
|
||||
"a = a;\nelse\na = 999;\n;\n;\n}\n;\n;\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ForLoopTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a, b, c:integer;
|
||||
begin
|
||||
b := 5;
|
||||
c := 6;
|
||||
for a := 1 to 60 do
|
||||
begin
|
||||
for b := a + c to 5 * a do
|
||||
begin
|
||||
c := 1;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\n" +
|
||||
"int c, b, a;\nint main()\n" +
|
||||
"{\nb = 5;\nc = 6;\nfor(a = 1; a <= 60; a++){\n" +
|
||||
"for(b = a + c; b <= 5 * a; b++)" +
|
||||
"{\nc = 1;\n;\n}\n;\n;\n;\n}\n;\n;\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcedureCallTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a, b:integer; c:real;
|
||||
|
||||
function test1(var a1:integer; b1:integer; c1:real):integer;
|
||||
var i, j, k:integer;
|
||||
begin
|
||||
a1:= 10086;
|
||||
b1 := 2;
|
||||
c1 := 63;
|
||||
test1 := test1(i, j, k);
|
||||
end;
|
||||
|
||||
begin
|
||||
test1(a, b, c);
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nint b, a;\ndouble c;" +
|
||||
"\nint test1(int* a1, int b1, double c1)\n{" +
|
||||
"\nint test1;\nint k, j, i;\n" +
|
||||
"{\n(*a1) = 10086;\nb1 = 2;\nc1 = 63;\n" +
|
||||
"test1 = test1(&i, j, k);\n;\n}\nreturn test1;\n}\n" +
|
||||
"int main()\n{\ntest1(&a, b, c);\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
}
|
84
Canon.Tests/CodeGeneratorTests/SubprogramTests.cs
Normal file
84
Canon.Tests/CodeGeneratorTests/SubprogramTests.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using Canon.Core.SemanticParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CodeGeneratorTests;
|
||||
|
||||
public class SubprogramTests
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public SubprogramTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcedureDeclarationTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
const PI = 3.1415;
|
||||
procedure test1;
|
||||
var ch:char;
|
||||
begin
|
||||
end;
|
||||
procedure test2;
|
||||
var i, j:integer;
|
||||
begin
|
||||
end;
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nconst double pi = 3.1415;\n" +
|
||||
"void test1()\n{\nchar ch;\n{\n;\n}\n\n}\n" +
|
||||
"void test2()\n{\nint j, i;\n{\n;\n}\n\n}\n" +
|
||||
"int main()\n{\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FunctionDeclarationTest()
|
||||
{
|
||||
const string program = """
|
||||
program main;
|
||||
var a, b: boolean;
|
||||
function func1(var a:integer; b:integer; c:real):integer;
|
||||
begin
|
||||
a := b + c;
|
||||
func1 := a * 3;
|
||||
end;
|
||||
function func2(var a, b:boolean; c: array[0..6,3..8] of char):char;
|
||||
begin
|
||||
a := b and not b;
|
||||
func2 := c[5,8];
|
||||
end;
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
ProgramStruct root = CompilerHelpers.Analyse(program);
|
||||
SyntaxTreeTraveller traveller = new();
|
||||
CCodeGenerateVisitor visitor = new();
|
||||
traveller.Travel(root, visitor);
|
||||
|
||||
string result = visitor.Builder.Build();
|
||||
_output.WriteLine(result);
|
||||
Assert.Equal("#include <stdbool.h>\n#include <stdio.h>\nbool b, a;" +
|
||||
"\nint func1(int* a, int b, double c)\n{\nint func1;\n" +
|
||||
"{\n(*a) = b + c;\nfunc1 = (*a) * 3;\n;\n}\nreturn func1;\n}\n" +
|
||||
"char func2(bool* a, bool* b, char c[][6])\n{\nchar func2;\n" +
|
||||
"{\n(*a) = (*b) && (!(*b));\nfunc2 = c[5-0][8-3];\n;\n}\nreturn func2;\n}" +
|
||||
"\nint main()\n{\n;\n\nreturn 0;\n}\n", visitor.Builder.Build());
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user