feat: 针对C的代码生成 (#50)
Co-authored-by: Lan_G <2911328695@qq.com> Reviewed-on: PostGuard/Canon#50
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +12,22 @@ public class AddOperator : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new AddOperator { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
var operatorType = Children[0].Convert<TerminatedSyntaxNode>().Token.
|
||||
Convert<OperatorSemanticToken>().OperatorType;
|
||||
if (operatorType == OperatorType.Plus)
|
||||
{
|
||||
builder.AddString(" +");
|
||||
}
|
||||
else if (operatorType == OperatorType.Minus)
|
||||
{
|
||||
builder.AddString(" -");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" ||");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,7 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SemanticParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +13,50 @@ public class BasicType : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new BasicType { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
var keywordType = Children[0].Convert<TerminatedSyntaxNode>().Token
|
||||
.Convert<KeywordSemanticToken>().KeywordType;
|
||||
|
||||
switch (keywordType)
|
||||
{
|
||||
case KeywordType.Integer:
|
||||
builder.AddString(" int");
|
||||
break;
|
||||
case KeywordType.Real:
|
||||
builder.AddString(" double");
|
||||
break;
|
||||
case KeywordType.Boolean:
|
||||
builder.AddString(" bool");
|
||||
break;
|
||||
case KeywordType.Character:
|
||||
builder.AddString(" char");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///尝试获取Pascal的基本类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public PascalType TryGetPascalType()
|
||||
{
|
||||
var keywordType = Children[0].Convert<TerminatedSyntaxNode>().Token
|
||||
.Convert<KeywordSemanticToken>().KeywordType;
|
||||
|
||||
switch (keywordType)
|
||||
{
|
||||
case KeywordType.Integer:
|
||||
return PascalBasicType.Integer;
|
||||
case KeywordType.Real:
|
||||
return PascalBasicType.Real;
|
||||
case KeywordType.Boolean:
|
||||
return PascalBasicType.Boolean;
|
||||
case KeywordType.Character:
|
||||
return PascalBasicType.Character;
|
||||
}
|
||||
|
||||
return PascalBasicType.Void;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -12,4 +13,16 @@ public class CompoundStatement : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new CompoundStatement { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var statement in Statements.Reverse())
|
||||
{
|
||||
if (statement.Children.Count > 0)
|
||||
{
|
||||
statement.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
@@ -40,4 +41,38 @@ public class ConstDeclarations : NonTerminatedSyntaxNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var pair in ConstValues.Reverse())
|
||||
{
|
||||
builder.AddString(" const");
|
||||
//获取常量类型
|
||||
var token = pair.Item2.Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
var tokenType = token.TokenType;
|
||||
if (tokenType == SemanticTokenType.Number)
|
||||
{
|
||||
if (token.Convert<NumberSemanticToken>().NumberType == NumberType.Integer)
|
||||
{
|
||||
builder.AddString(" int ");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" double ");
|
||||
}
|
||||
}
|
||||
else if (tokenType == SemanticTokenType.Character)
|
||||
{
|
||||
builder.AddString(" char ");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" bool ");
|
||||
}
|
||||
|
||||
builder.AddString(pair.Item1.IdentifierName + " =");
|
||||
pair.Item2.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +11,24 @@ public class ConstValue : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new ConstValue { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//获取常量值
|
||||
var token = Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
//constValue -> 'letter'
|
||||
if (token.TokenType == SemanticTokenType.Character)
|
||||
{
|
||||
builder.AddString(" '" + token.LiteralValue + "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" ");
|
||||
// constValue -> +num | -num | num
|
||||
foreach (var c in Children)
|
||||
{
|
||||
builder.AddString(c.Convert<TerminatedSyntaxNode>().Token.LiteralValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +11,14 @@ public class ElsePart : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new ElsePart { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
if (Children.Count > 0)
|
||||
{
|
||||
builder.AddString(" else{");
|
||||
Children[1].GenerateCCode(builder);
|
||||
builder.AddString(" }");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +11,12 @@ public class Expression : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new Expression { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
child.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -51,4 +52,22 @@ public class ExpressionList : NonTerminatedSyntaxNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//用逗号分隔输出的expression
|
||||
using var enumerator = Expressions.GetEnumerator();
|
||||
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
enumerator.Current.GenerateCCode(builder);
|
||||
}
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
builder.AddString(", ");
|
||||
enumerator.Current.GenerateCCode(builder);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +12,56 @@ public class Factor : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new Factor { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
if (Children.Count == 1)
|
||||
{
|
||||
//factor -> num
|
||||
if (Children[0].IsTerminated)
|
||||
{
|
||||
var token = Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
if (token.TokenType == SemanticTokenType.Number)
|
||||
{
|
||||
builder.AddString(" " + token.LiteralValue);
|
||||
}
|
||||
}
|
||||
// factor -> variable
|
||||
else
|
||||
{
|
||||
Children[0].GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
//factor -> ( expression )
|
||||
else if (Children.Count == 3)
|
||||
{
|
||||
builder.AddString(" (");
|
||||
Children[1].GenerateCCode(builder);
|
||||
builder.AddString(")");
|
||||
}
|
||||
//factor -> id ( expression )
|
||||
else if (Children.Count == 4)
|
||||
{
|
||||
builder.AddString(" " + Children[0].Convert<TerminatedSyntaxNode>().Token.
|
||||
Convert<IdentifierSemanticToken>().IdentifierName);
|
||||
builder.AddString("(");
|
||||
Children[2].GenerateCCode(builder);
|
||||
builder.AddString(")");
|
||||
}
|
||||
else
|
||||
{ //factor -> not factor
|
||||
builder.AddString(" (");
|
||||
if (Children[0].Convert<TerminatedSyntaxNode>().Token.TokenType == SemanticTokenType.Keyword)
|
||||
{
|
||||
builder.AddString("!");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString("-");
|
||||
}
|
||||
|
||||
Children[1].GenerateCCode(builder);
|
||||
builder.AddString(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
@@ -55,4 +56,20 @@ public class IdentifierList : NonTerminatedSyntaxNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//用逗号分隔输出的expression
|
||||
using var enumerator = Identifiers.Reverse().GetEnumerator();
|
||||
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
builder.AddString(" " + enumerator.Current.IdentifierName);
|
||||
}
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
builder.AddString(", " + enumerator.Current.IdentifierName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.SemanticParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -48,4 +50,5 @@ public class IdentifierVarPart : NonTerminatedSyntaxNode
|
||||
|
||||
return new IdentifierVarPart { Children = children, Exist = exist };
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +12,39 @@ public class MultiplyOperator : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new MultiplyOperator { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
var token = Children[0].Convert<TerminatedSyntaxNode>().Token;
|
||||
if (token.TokenType == SemanticTokenType.Operator)
|
||||
{
|
||||
var operatorType = token.Convert<OperatorSemanticToken>().OperatorType;
|
||||
if (operatorType == OperatorType.Multiply)
|
||||
{
|
||||
builder.AddString(" *");
|
||||
}
|
||||
else if (operatorType == OperatorType.Divide)
|
||||
{
|
||||
//实数除法,需要将操作数强转为float
|
||||
builder.AddString(" /(double)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var keywordType = token.Convert<KeywordSemanticToken>().KeywordType;
|
||||
if (keywordType == KeywordType.And)
|
||||
{
|
||||
builder.AddString(" &&");
|
||||
}
|
||||
else if (keywordType == KeywordType.Mod)
|
||||
{
|
||||
builder.AddString(" %");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" /");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
@@ -29,4 +30,26 @@ public class ProcedureCall : NonTerminatedSyntaxNode
|
||||
yield return expression;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
builder.AddString(ProcedureId.IdentifierName + "(");
|
||||
|
||||
//用逗号分隔输出的expression
|
||||
using (var enumerator = Arguments.GetEnumerator())
|
||||
{
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
enumerator.Current.GenerateCCode(builder);
|
||||
}
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
builder.AddString(", ");
|
||||
enumerator.Current.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
|
||||
builder.AddString(")");
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -30,4 +31,17 @@ public class ProgramBody : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new ProgramBody { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//全局常量,变量
|
||||
ConstDeclarations.GenerateCCode(builder);
|
||||
VarDeclarations.GenerateCCode(builder);
|
||||
//子函数声明
|
||||
SubprogramDeclarations.GenerateCCode(builder);
|
||||
//main函数
|
||||
builder.AddString(" int main(){");
|
||||
CompoundStatement.GenerateCCode(builder);
|
||||
builder.AddString(" return 0;}");
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ public class ProgramStruct : NonTerminatedSyntaxNode
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
builder.AddString("#include <PascalCoreLib.h>");
|
||||
builder.AddString("#include <PascalCoreLib.h> #include <stdbool.h>");
|
||||
Body.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +12,31 @@ public class RelationOperator : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new RelationOperator { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
var operatorType = Children[0].Convert<TerminatedSyntaxNode>().Token.
|
||||
Convert<OperatorSemanticToken>().OperatorType;
|
||||
switch (operatorType)
|
||||
{
|
||||
case OperatorType.Equal:
|
||||
builder.AddString(" ==");
|
||||
break;
|
||||
case OperatorType.Greater:
|
||||
builder.AddString(" >");
|
||||
break;
|
||||
case OperatorType.Less:
|
||||
builder.AddString(" <");
|
||||
break;
|
||||
case OperatorType.GreaterEqual:
|
||||
builder.AddString(" >=");
|
||||
break;
|
||||
case OperatorType.LessEqual:
|
||||
builder.AddString(" <=");
|
||||
break;
|
||||
case OperatorType.NotEqual:
|
||||
builder.AddString(" !=");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +11,12 @@ public class SimpleExpression : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new SimpleExpression { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
child.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +12,47 @@ public class Statement : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new Statement { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
if (Children.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// statement -> procedureCall | compoundStatement
|
||||
if (Children.Count == 1)
|
||||
{
|
||||
Children[0].GenerateCCode(builder);
|
||||
}
|
||||
//statement -> variable assign expression
|
||||
else if (Children.Count == 3)
|
||||
{
|
||||
Children[0].GenerateCCode(builder);
|
||||
builder.AddString(" =");
|
||||
Children[2].GenerateCCode(builder);
|
||||
}
|
||||
//if expression then statement else_part
|
||||
else if (Children.Count == 5)
|
||||
{
|
||||
builder.AddString(" if(");
|
||||
Children[1].GenerateCCode(builder);
|
||||
builder.AddString("){");
|
||||
Children[3].GenerateCCode(builder);
|
||||
builder.AddString("; }");
|
||||
Children[4].GenerateCCode(builder);
|
||||
}
|
||||
//for id assign expression to expression do statement
|
||||
else
|
||||
{
|
||||
string idName = Children[1].Convert<TerminatedSyntaxNode>().Token.Convert<IdentifierSemanticToken>()
|
||||
.IdentifierName;
|
||||
builder.AddString(" for(" + idName + " =");
|
||||
Children[3].GenerateCCode(builder);
|
||||
builder.AddString("; " + idName + " <=");
|
||||
Children[5].GenerateCCode(builder);
|
||||
builder.AddString("; " + idName + "++){");
|
||||
Children[7].GenerateCCode(builder);
|
||||
builder.AddString("; }");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -48,4 +49,16 @@ public class StatementList : NonTerminatedSyntaxNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var statement in Statements.Reverse())
|
||||
{
|
||||
if (statement.Children.Count > 0)
|
||||
{
|
||||
statement.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -20,4 +21,14 @@ public class Subprogram : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new Subprogram { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//子函数头
|
||||
Head.GenerateCCode(builder);
|
||||
//子函数体
|
||||
builder.AddString("{");
|
||||
Body.GenerateCCode(builder);
|
||||
builder.AddString("}");
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -25,4 +26,11 @@ public class SubprogramBody : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new SubprogramBody() { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
ConstDeclarations.GenerateCCode(builder);
|
||||
VarDeclarations.GenerateCCode(builder);
|
||||
CompoundStatement.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -31,4 +32,12 @@ public class SubprogramDeclarations : NonTerminatedSyntaxNode
|
||||
declarations = declarations.Children[0].Convert<SubprogramDeclarations>();
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var subprogram in Subprograms)
|
||||
{
|
||||
subprogram.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
@@ -42,4 +43,28 @@ public class SubprogramHead : NonTerminatedSyntaxNode
|
||||
|
||||
return new SubprogramHead { Children = children, IsProcedure = isProcedure };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//可能要用到符号表
|
||||
if (IsProcedure)
|
||||
{
|
||||
builder.AddString("void ");
|
||||
}
|
||||
else
|
||||
{
|
||||
//返回类型暂时未知
|
||||
builder.AddString("int ");
|
||||
}
|
||||
|
||||
builder.AddString(SubprogramName.LiteralValue);
|
||||
|
||||
builder.AddString("(");
|
||||
foreach (var param in Parameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
builder.AddString(")");
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +11,12 @@ public class Term : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new Term { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
child.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -10,4 +11,18 @@ public class TypeSyntaxNode : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new TypeSyntaxNode { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//type -> basic_type
|
||||
if (Children.Count == 1)
|
||||
{
|
||||
Children[0].GenerateCCode(builder);
|
||||
}
|
||||
//type -> array [ period ]of basic_type
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -20,4 +21,10 @@ public class ValueParameter : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new ValueParameter { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//可能涉及符号表访问
|
||||
builder.AddString("valueParam ");
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.SemanticParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -39,4 +41,49 @@ public class VarDeclarations : NonTerminatedSyntaxNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
foreach (var pair in Variables.Reverse())
|
||||
{
|
||||
//BasicType定义
|
||||
if (pair.Item2.Children.Count == 1)
|
||||
{
|
||||
//输出类型
|
||||
pair.Item2.GenerateCCode(builder);
|
||||
//输出idList
|
||||
pair.Item1.GenerateCCode(builder);
|
||||
builder.AddString(";");
|
||||
}
|
||||
//array定义
|
||||
else
|
||||
{
|
||||
//构造出C语言形式的数组下标定义
|
||||
string arrayPeriod = "";
|
||||
var ranges = pair.Item2.Children[2]
|
||||
.Convert<Period>().Ranges;
|
||||
PascalType pascalType = pair.Item2.Children[5].Convert<BasicType>().TryGetPascalType();
|
||||
|
||||
foreach (var range in ranges)
|
||||
{
|
||||
int low = int.Parse(range.Item1.LiteralValue);
|
||||
int high = int.Parse(range.Item2.LiteralValue);
|
||||
arrayPeriod = "[" + System.Convert.ToString(high-low+1) + "]" + arrayPeriod;
|
||||
pascalType = new PascalArrayType(pascalType, low, high); //嵌套地构造出多维数组
|
||||
}
|
||||
|
||||
//依次定义每一个符号
|
||||
foreach (var id in pair.Item1.Identifiers.Reverse())
|
||||
{
|
||||
pair.Item2.Children[5].GenerateCCode(builder);
|
||||
builder.AddString(" " + id.IdentifierName + arrayPeriod + ";");
|
||||
//写入符号表
|
||||
builder.SymbolTable.TryAddSymbol(new Symbol()
|
||||
{
|
||||
SymbolName = id.IdentifierName, SymbolType = pascalType, Reference = false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -12,4 +13,9 @@ public class VarParameter : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new VarParameter { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
ValueParameter.GenerateCCode(builder);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.CodeGenerators;
|
||||
using Canon.Core.Enums;
|
||||
using Canon.Core.LexicalParser;
|
||||
using Canon.Core.SemanticParser;
|
||||
|
||||
namespace Canon.Core.SyntaxNodes;
|
||||
|
||||
@@ -17,4 +19,44 @@ public class Variable : NonTerminatedSyntaxNode
|
||||
{
|
||||
return new Variable { Children = children };
|
||||
}
|
||||
|
||||
public override void GenerateCCode(CCodeBuilder builder)
|
||||
{
|
||||
//判断是否为引用变量
|
||||
builder.SymbolTable.TryGetSymbol(Identifier.IdentifierName, out var symbol);
|
||||
if (symbol is not null && symbol.Reference)
|
||||
{
|
||||
builder.AddString(" (*" + Identifier.IdentifierName + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddString(" " + Identifier.IdentifierName);
|
||||
}
|
||||
|
||||
//处理idVarPart(数组下标部分)
|
||||
var idVarPart = Children[1].Convert<IdentifierVarPart>();
|
||||
if (idVarPart.Exist)
|
||||
{
|
||||
PascalArrayType pascalArrayType = (PascalArrayType)symbol.SymbolType;
|
||||
var positions = idVarPart.Positions;
|
||||
|
||||
foreach (var pos in positions.Reverse())
|
||||
{
|
||||
builder.AddString("[");
|
||||
pos.GenerateCCode(builder);
|
||||
//pascal下标减去左边界,从而映射到C语言的下标
|
||||
builder.AddString(" - " + System.Convert.ToString(pascalArrayType.Begin) + "]");
|
||||
|
||||
try
|
||||
{
|
||||
pascalArrayType = (PascalArrayType)pascalArrayType.ElementType;
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
//do nothing
|
||||
//因为最后一层嵌套类型,必然不是PascalArrayType, 而是BasicType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user