feat: 针对C的代码生成 (#50)
Co-authored-by: Lan_G <2911328695@qq.com> Reviewed-on: PostGuard/Canon#50
This commit is contained in:
@@ -4,6 +4,7 @@ using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.GeneratedParserTests;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CCodeGeneratorTests;
|
||||
|
||||
@@ -11,6 +12,12 @@ public class BasicTests
|
||||
{
|
||||
private readonly IGrammarParser _parser = GeneratedGrammarParser.Instance;
|
||||
private readonly ILexer _lexer = new Lexer();
|
||||
private readonly ITestOutputHelper _outputHelper;
|
||||
|
||||
public BasicTests(ITestOutputHelper outputHelper)
|
||||
{
|
||||
_outputHelper = outputHelper;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgramStructTest()
|
||||
@@ -28,6 +35,8 @@ public class BasicTests
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
Assert.Equal("#include <PascalCoreLib.h>", builder.Build());
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> int main(){statement; return 0;}", result);
|
||||
}
|
||||
}
|
||||
|
90
Canon.Tests/CCodeGeneratorTests/DeclarationsTests.cs
Normal file
90
Canon.Tests/CCodeGeneratorTests/DeclarationsTests.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.GeneratedParserTests;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CCodeGeneratorTests;
|
||||
|
||||
public class DeclarationsTest
|
||||
{
|
||||
private readonly IGrammarParser _parser = GeneratedGrammarParser.Instance;
|
||||
private readonly ILexer _lexer = new Lexer();
|
||||
private readonly ITestOutputHelper _outputHelper;
|
||||
|
||||
public DeclarationsTest(ITestOutputHelper outputHelper)
|
||||
{
|
||||
_outputHelper = outputHelper;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VarDeclarationsTest()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program varTest;
|
||||
var a, b, c, d: integer; m, n: real; k: boolean;
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> char a; int main(){statement; return 0; }", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstDeclarationsTest()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program varTest;
|
||||
const a = 1; b = 2; c = 3; d = 2.5;
|
||||
begin
|
||||
end.
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> int main(){statement; return 0; }", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ArrayDeclarationsTest()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program arrayTest;
|
||||
var a, b, c: array[1..6,5..8] of integer;
|
||||
d: integer;
|
||||
begin
|
||||
a[2,3] := 10086;
|
||||
d:=6;
|
||||
end.
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> int main(){statement; return 0; }", result);
|
||||
}
|
||||
}
|
47
Canon.Tests/CCodeGeneratorTests/ExpressionTests.cs
Normal file
47
Canon.Tests/CCodeGeneratorTests/ExpressionTests.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.GeneratedParserTests;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CCodeGeneratorTests;
|
||||
|
||||
public class ExpressionTests
|
||||
{
|
||||
private readonly IGrammarParser _parser = GeneratedGrammarParser.Instance;
|
||||
private readonly ILexer _lexer = new Lexer();
|
||||
private readonly ITestOutputHelper _outputHelper;
|
||||
|
||||
public ExpressionTests(ITestOutputHelper outputHelper)
|
||||
{
|
||||
_outputHelper = outputHelper;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExpressionTest1()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program varTest;
|
||||
var a, b, c, d: integer; m, n: real; k: boolean;
|
||||
begin
|
||||
a := 1;
|
||||
b := a + 6 * 9 + (a + 9) * 1 - (4 + a) * 5 / 1;
|
||||
m := b / 3;
|
||||
d := 9 mod 1;
|
||||
end.
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> char a; int main(){statement; return 0; }", result);
|
||||
}
|
||||
}
|
111
Canon.Tests/CCodeGeneratorTests/StatementTests.cs
Normal file
111
Canon.Tests/CCodeGeneratorTests/StatementTests.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using Canon.Core.Abstractions;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SyntaxNodes;
|
||||
using Canon.Tests.GeneratedParserTests;
|
||||
using Canon.Tests.Utils;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Canon.Tests.CCodeGeneratorTests;
|
||||
|
||||
public class StatementTests
|
||||
{
|
||||
private readonly IGrammarParser _parser = GeneratedGrammarParser.Instance;
|
||||
private readonly ILexer _lexer = new Lexer();
|
||||
private readonly ITestOutputHelper _outputHelper;
|
||||
|
||||
public StatementTests(ITestOutputHelper outputHelper)
|
||||
{
|
||||
_outputHelper = outputHelper;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VariableAssignTest()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program varAssignTest;
|
||||
var a, b: integer;
|
||||
begin
|
||||
a := 1;
|
||||
b := a;
|
||||
a := b;
|
||||
end.
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> #include <stdbool.h> " +
|
||||
"int a, b; int main(){ a = 1; b = a; a = b; return 0;}", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IfTest()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program main;
|
||||
var
|
||||
a,b:integer;
|
||||
begin
|
||||
if a = 5 then
|
||||
begin
|
||||
if b = 3 then
|
||||
b := b + 1
|
||||
else
|
||||
b := b + 2
|
||||
end
|
||||
else
|
||||
a := 2
|
||||
end.
|
||||
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> #include <stdbool.h> int a, b; " +
|
||||
"int main(){ a = 1; if( a == 1){ a = a + 1; } else{ b = a + 2 }; return 0;}", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ForLoopTest()
|
||||
{
|
||||
CCodeBuilder builder = new();
|
||||
|
||||
const string program = """
|
||||
program ForLoopTest;
|
||||
var a, b, c: integer;
|
||||
begin
|
||||
b := 1;
|
||||
for a := b * 5 + 1 to 99 do
|
||||
begin
|
||||
c := a + 1;
|
||||
b := a mod (a + c);
|
||||
b := a + 1 - 1 * 1;
|
||||
end;
|
||||
end.
|
||||
""";
|
||||
|
||||
IEnumerable<SemanticToken> tokens = _lexer.Tokenize(new StringSourceReader(program));
|
||||
|
||||
ProgramStruct root = _parser.Analyse(tokens);
|
||||
root.GenerateCCode(builder);
|
||||
|
||||
string result = builder.Build();
|
||||
_outputHelper.WriteLine(result);
|
||||
Assert.Equal("#include <PascalCoreLib.h> #include <stdbool.h> int a, b; " +
|
||||
"int main(){ a = 1; if( a == 1){ a = a + 1; } else{ b = a + 2 }; return 0;}", result);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user