2024-05-04 11:56:06 +08:00
|
|
|
|
using System.Globalization;
|
2024-05-12 22:36:17 +08:00
|
|
|
|
using Canon.Core.Abstractions;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
using Canon.Core.CodeGenerators;
|
|
|
|
|
using Canon.Core.Enums;
|
2024-05-12 20:28:56 +08:00
|
|
|
|
using Canon.Core.GrammarParser;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
using Canon.Core.LexicalParser;
|
|
|
|
|
using Canon.Core.SyntaxNodes;
|
2024-05-12 14:29:18 +08:00
|
|
|
|
using BasicType = Canon.Core.Enums.BasicType;
|
2024-05-12 20:28:56 +08:00
|
|
|
|
using Expression = Canon.Core.SyntaxNodes.Expression;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
namespace Canon.Core.SemanticParser;
|
|
|
|
|
|
2024-05-12 22:36:17 +08:00
|
|
|
|
public class CodeGeneratorVisitor(ICompilerLogger? logger = null) : TypeCheckVisitor(logger)
|
2024-05-04 11:56:06 +08:00
|
|
|
|
{
|
|
|
|
|
public CCodeBuilder Builder { get; } = new();
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(ProgramHead programHead)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(programHead);
|
|
|
|
|
|
|
|
|
|
Builder.AddLine("#include <stdio.h>");
|
|
|
|
|
Builder.AddLine("#include <stdbool.h>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(ProgramBody programBody)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(programBody);
|
|
|
|
|
|
|
|
|
|
programBody.CompoundStatement.IsMain = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(ConstDeclaration constDeclaration)
|
|
|
|
|
{
|
2024-05-14 14:10:42 +08:00
|
|
|
|
base.PostVisit(constDeclaration);
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
(IdentifierSemanticToken token, ConstValue constValue) = constDeclaration.ConstValue;
|
|
|
|
|
|
|
|
|
|
if (SymbolTable.TryGetSymbol(token.IdentifierName, out Symbol? symbol))
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine(
|
|
|
|
|
$"const {GenerateBasicTypeString(symbol.SymbolType)} {token.IdentifierName} = {constValue.ValueString};");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(ConstValue constValue)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(constValue);
|
|
|
|
|
|
|
|
|
|
constValue.OnNumberGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string numberValue = e.IsNegative ? "-" : "+";
|
|
|
|
|
|
|
|
|
|
if (constValue.ConstType == PascalBasicType.Integer)
|
|
|
|
|
{
|
|
|
|
|
numberValue += e.Token.ParseAsInteger().ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (constValue.ConstType == PascalBasicType.Real)
|
|
|
|
|
{
|
|
|
|
|
numberValue += e.Token.ParseAsReal().ToString(CultureInfo.CurrentCulture);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constValue.ValueString = numberValue;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constValue.OnCharacterGenerator += (_, e) => { constValue.ValueString = $"'{e.Token.LiteralValue}'"; };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(VarDeclaration varDeclaration)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(varDeclaration);
|
|
|
|
|
|
|
|
|
|
varDeclaration.IdentifierList.IsVariableDefinition = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(VarDeclaration varDeclaration)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(varDeclaration);
|
|
|
|
|
|
|
|
|
|
if (varDeclaration.IdentifierList.DefinitionType is PascalBasicType)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"{GenerateBasicTypeString(varDeclaration.IdentifierList.DefinitionType)} " +
|
|
|
|
|
$"{varDeclaration.Token.IdentifierName};");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (varDeclaration.IdentifierList.DefinitionType is PascalArrayType)
|
|
|
|
|
{
|
|
|
|
|
(string basicValue, string periodValue) = GenerateArrayTypeString(
|
|
|
|
|
varDeclaration.IdentifierList.DefinitionType);
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"{basicValue} {varDeclaration.Token.IdentifierName}{periodValue};");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(IdentifierList identifierList)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(identifierList);
|
|
|
|
|
|
|
|
|
|
identifierList.OnIdentifierGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (identifierList.IsVariableDefinition)
|
|
|
|
|
{
|
|
|
|
|
e.IdentifierList.IsVariableDefinition = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(IdentifierList identifierList)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(identifierList);
|
|
|
|
|
|
|
|
|
|
identifierList.OnIdentifierGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (!identifierList.IsVariableDefinition)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (identifierList.DefinitionType is PascalArrayType)
|
|
|
|
|
{
|
|
|
|
|
(string basicTypeString, string periodString) = GenerateArrayTypeString(identifierList.DefinitionType);
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"{basicTypeString} {e.IdentifierToken.IdentifierName}{periodString};");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (identifierList.DefinitionType is PascalBasicType)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"{GenerateBasicTypeString(identifierList.DefinitionType)} " +
|
|
|
|
|
$"{e.IdentifierToken.IdentifierName};");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(CompoundStatement compoundStatement)
|
|
|
|
|
{
|
|
|
|
|
if (compoundStatement.IsMain)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine("int main()");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Builder.BeginScope();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(CompoundStatement compoundStatement)
|
|
|
|
|
{
|
|
|
|
|
if (compoundStatement.IsMain)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine("return 0;");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Builder.EndScope();
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
public override void PreVisit(Factor factor)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(factor);
|
|
|
|
|
|
|
|
|
|
factor.OnParethnesisGenerator += (_, e) => { e.Expression.IsCondition = factor.IsCondition; };
|
|
|
|
|
|
|
|
|
|
factor.OnNotGenerator += (_, e) => { e.Factor.IsCondition = factor.IsCondition; };
|
|
|
|
|
|
|
|
|
|
factor.OnUminusGenerator += (_, e) => { e.Factor.IsCondition = factor.IsCondition; };
|
|
|
|
|
|
|
|
|
|
factor.OnPlusGenerator += (_, e) => { e.Factor.IsCondition = factor.IsCondition; };
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
public override void PostVisit(Factor factor)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(factor);
|
|
|
|
|
|
|
|
|
|
factor.OnNumberGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
switch (e.Token.NumberType)
|
|
|
|
|
{
|
|
|
|
|
case NumberType.Integer:
|
|
|
|
|
Builder.AddLine($"int {temporaryName} = {e.Token.ParseAsInteger()};");
|
|
|
|
|
break;
|
|
|
|
|
case NumberType.Real:
|
|
|
|
|
Builder.AddLine($"double {temporaryName} = {e.Token.ParseAsReal()};");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
factor.VariableName = temporaryName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
factor.OnBooleanGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
string value = e.Value ? "true" : "false";
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"bool {temporaryName} = {value};");
|
|
|
|
|
factor.VariableName = temporaryName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
factor.OnVariableGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (SymbolTable.TryGetSymbol(e.Variable.VariableName, out Symbol? symbol))
|
|
|
|
|
{
|
|
|
|
|
// 处理不带括号调用无参函数的问题
|
|
|
|
|
if (symbol.SymbolType is PascalFunctionType { Parameters.Count: 0 } functionType)
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"{GenerateBasicTypeString(functionType.ReturnType)} {temporaryName} = " +
|
|
|
|
|
$"{symbol.SymbolName}_pascal_procedure();");
|
|
|
|
|
factor.VariableName = temporaryName;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
factor.VariableName = e.Variable.VariableName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
factor.OnParethnesisGenerator += (_, e) => { factor.VariableName = e.Expression.VariableName; };
|
|
|
|
|
|
|
|
|
|
factor.OnNotGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine(
|
|
|
|
|
$"{GenerateBasicTypeString(factor.VariableType)} {temporaryName} = ~{e.Factor.VariableName};");
|
|
|
|
|
factor.VariableName = temporaryName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
factor.OnPlusGenerator += (_, e) => { factor.VariableName = e.Factor.VariableName; };
|
|
|
|
|
|
|
|
|
|
factor.OnUminusGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine(
|
|
|
|
|
$"{GenerateBasicTypeString(factor.VariableType)} {temporaryName} = -{e.Factor.VariableName};");
|
|
|
|
|
factor.VariableName = temporaryName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
factor.OnProcedureCallGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"{GenerateBasicTypeString(factor.VariableType)} {temporaryName}= " +
|
|
|
|
|
$"{GenerateProcedureCall(e.ProcedureName.IdentifierName, e.Parameters)};");
|
|
|
|
|
factor.VariableName = temporaryName;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(Variable variable)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(variable);
|
|
|
|
|
|
|
|
|
|
if (!SymbolTable.TryGetSymbol(variable.Identifier.IdentifierName, out Symbol? symbol))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PascalType type = symbol.SymbolType;
|
|
|
|
|
|
|
|
|
|
if (type is PascalArrayType)
|
|
|
|
|
{
|
|
|
|
|
string indexValue = string.Empty;
|
|
|
|
|
foreach (Expression expression in variable.VarPart.Expressions)
|
|
|
|
|
{
|
|
|
|
|
PascalArrayType arrayType = type.Convert<PascalArrayType>();
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"int {temporaryName} = {expression.VariableName} - {arrayType.Begin};");
|
|
|
|
|
|
|
|
|
|
indexValue += $"[{temporaryName}]";
|
|
|
|
|
type = arrayType.ElementType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
variable.VariableName = variable.Identifier.IdentifierName + indexValue;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
// 虽然这里这样可能会生成来类似于 &*x 的代码
|
|
|
|
|
// 但是可以正常运行
|
|
|
|
|
variable.VariableName =
|
2024-05-12 14:29:18 +08:00
|
|
|
|
symbol.SymbolType.IsReference
|
|
|
|
|
? $"*{variable.Identifier.IdentifierName}"
|
|
|
|
|
: variable.Identifier.IdentifierName;
|
2024-05-10 16:45:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
private record CircuitLabel(string Circuit, string End);
|
|
|
|
|
|
|
|
|
|
private readonly Stack<CircuitLabel> _andCircuitLabels = [];
|
|
|
|
|
|
|
|
|
|
private readonly Stack<CircuitLabel> _orCircuitLabels = [];
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
public override void PreVisit(Term term)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(term);
|
|
|
|
|
|
|
|
|
|
term.OnMultiplyGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.Left.IsCondition = term.IsCondition;
|
|
|
|
|
e.Right.IsCondition = term.IsCondition;
|
2024-05-12 20:28:56 +08:00
|
|
|
|
|
|
|
|
|
if (e.Operator.OperatorToken == new Terminator(KeywordType.And))
|
|
|
|
|
{
|
|
|
|
|
_andCircuitLabels.Push(new CircuitLabel($"and_circult_{_labelCount}",
|
|
|
|
|
$"and_end_{_labelCount}"));
|
|
|
|
|
_labelCount += 1;
|
|
|
|
|
}
|
2024-05-10 16:45:21 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
term.OnFactorGenerator += (_, e) => { e.Factor.IsCondition = term.IsCondition; };
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
private string? _termVariableName;
|
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
public override void PostVisit(Term term)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(term);
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
term.OnFactorGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
term.VariableName = e.Factor.VariableName;
|
|
|
|
|
_termVariableName = term.VariableName;
|
|
|
|
|
};
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
term.OnMultiplyGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
if (e.Operator.OperatorToken == new Terminator(KeywordType.And))
|
|
|
|
|
{
|
|
|
|
|
// 处理and的短路代码
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
bool {temporaryName} = {e.Left.VariableName} && {e.Right.VariableName};
|
|
|
|
|
goto {_andCircuitLabels.Peek().End};
|
|
|
|
|
{_andCircuitLabels.Peek().Circuit}:;
|
|
|
|
|
{temporaryName} = false;
|
|
|
|
|
{_andCircuitLabels.Peek().End}:;
|
|
|
|
|
""");
|
|
|
|
|
|
|
|
|
|
_andCircuitLabels.Pop();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine(
|
|
|
|
|
$"{GenerateBasicTypeString(term.VariableType)} {temporaryName} = " +
|
|
|
|
|
$"{e.Left.VariableName} {GenerateMultipleOperator(e.Operator)} {e.Right.VariableName};");
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
term.VariableName = temporaryName;
|
2024-05-12 20:28:56 +08:00
|
|
|
|
_termVariableName = temporaryName;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
public override void PreVisit(SimpleExpression simpleExpression)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(simpleExpression);
|
|
|
|
|
|
|
|
|
|
simpleExpression.OnAddGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.Left.IsCondition = simpleExpression.IsCondition;
|
|
|
|
|
e.Right.IsCondition = simpleExpression.IsCondition;
|
2024-05-12 20:28:56 +08:00
|
|
|
|
|
|
|
|
|
if (e.Operator.OperatorToken == new Terminator(KeywordType.Or))
|
|
|
|
|
{
|
|
|
|
|
_orCircuitLabels.Push(new CircuitLabel($"or_circuit_{_labelCount}",
|
|
|
|
|
$"or_end_circuit_{_labelCount}"));
|
|
|
|
|
_labelCount += 1;
|
|
|
|
|
}
|
2024-05-10 16:45:21 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
simpleExpression.OnTermGenerator += (_, e) => { e.Term.IsCondition = simpleExpression.IsCondition; };
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
private string? _simpleExpressionVairableName;
|
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
public override void PostVisit(SimpleExpression simpleExpression)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(simpleExpression);
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
simpleExpression.OnTermGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
simpleExpression.VariableName = e.Term.VariableName;
|
|
|
|
|
_simpleExpressionVairableName = simpleExpression.VariableName;
|
|
|
|
|
};
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
simpleExpression.OnAddGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
2024-05-12 20:28:56 +08:00
|
|
|
|
if (e.Operator.OperatorToken == new Terminator(KeywordType.Or))
|
|
|
|
|
{
|
|
|
|
|
// or的短路代码
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
bool {temporaryName};
|
|
|
|
|
{temporaryName} = {e.Left.VariableName} || {e.Right.VariableName};
|
|
|
|
|
goto {_orCircuitLabels.Peek().End};
|
|
|
|
|
{_orCircuitLabels.Peek().Circuit}:;
|
|
|
|
|
{temporaryName} = true;
|
|
|
|
|
{_orCircuitLabels.Peek().End}:;
|
|
|
|
|
""");
|
|
|
|
|
|
|
|
|
|
_orCircuitLabels.Pop();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine(
|
|
|
|
|
$"{GenerateBasicTypeString(simpleExpression.VariableType)} {temporaryName} = " +
|
|
|
|
|
$"{e.Left.VariableName} {GenerateAddOperator(e.Operator)} {e.Right.VariableName};");
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
simpleExpression.VariableName = temporaryName;
|
2024-05-12 20:28:56 +08:00
|
|
|
|
_simpleExpressionVairableName = temporaryName;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 13:52:11 +08:00
|
|
|
|
public override void PreVisit(Expression expression)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(expression);
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
expression.OnSimpleExpressionGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.SimpleExpression.IsCondition = expression.IsCondition;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
expression.OnRelationGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.Left.IsCondition = expression.IsCondition;
|
|
|
|
|
e.Right.IsCondition = expression.IsCondition;
|
|
|
|
|
};
|
2024-05-10 13:52:11 +08:00
|
|
|
|
if (expression.IsWhileCondition)
|
|
|
|
|
{
|
|
|
|
|
GenerateWhileLabel();
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
{_whileBeginLabels.Peek()}:;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-10 16:45:21 +08:00
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
public override void PostVisit(Expression expression)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(expression);
|
|
|
|
|
|
|
|
|
|
expression.OnSimpleExpressionGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
expression.VariableName = e.SimpleExpression.VariableName;
|
|
|
|
|
|
|
|
|
|
HandleExpression(expression);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
expression.OnRelationGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
string temporaryName = GenerateTemporaryVariable();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"{GenerateBasicTypeString(expression.VariableType)} {temporaryName} = " +
|
|
|
|
|
$"{e.Left.VariableName} {GenerateRelationOperator(e.Operator)} {e.Right.VariableName};");
|
|
|
|
|
expression.VariableName = temporaryName;
|
|
|
|
|
|
|
|
|
|
HandleExpression(expression);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandleExpression(Expression expression)
|
|
|
|
|
{
|
|
|
|
|
if (expression.IsIfCondition)
|
|
|
|
|
{
|
|
|
|
|
_ifConditionNames.Push(expression.VariableName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expression.IsForConditionBegin)
|
|
|
|
|
{
|
|
|
|
|
_forBeginConditions.Push(expression.VariableName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expression.IsForConditionEnd)
|
|
|
|
|
{
|
|
|
|
|
_forEndConditions.Push(expression.VariableName);
|
|
|
|
|
}
|
2024-05-10 13:52:11 +08:00
|
|
|
|
|
|
|
|
|
if (expression.IsWhileCondition)
|
|
|
|
|
{
|
|
|
|
|
_whileConditionNames.Push(expression.VariableName);
|
|
|
|
|
}
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 存储IF语句中条件变量的名称
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _ifConditionNames = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// IF语句中成功分支的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _ifTrueLabels = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// IF语句中失败分支的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _ifFalseLabels = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// IF语句中结束的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _ifEndLabels = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// FOR语句中的循环变量名称
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _forVariables = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// FOR语句中的循环变量的初始值
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _forBeginConditions = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// FOR语句中循环变量的判断值
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _forEndConditions = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// FOR语句开始的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _forLabels = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// FOR语句条件判断部分的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _forConditionLabels = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// FOR语句结束的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _forEndLabels = new();
|
|
|
|
|
|
2024-05-10 13:52:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// WHILE语句条件变量的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _whileConditionNames = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// WHILE语句开始的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _whileBeginLabels = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// WHILE语句结束的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly Stack<string> _whileEndLabels = new();
|
|
|
|
|
|
2024-05-04 11:56:06 +08:00
|
|
|
|
public override void PreVisit(Statement statement)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(statement);
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
statement.OnIfGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.Condition.IsIfCondition = true;
|
|
|
|
|
e.Condition.IsCondition = true;
|
|
|
|
|
};
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
statement.OnForGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.Begin.IsForConditionBegin = true;
|
|
|
|
|
e.End.IsForConditionEnd = true;
|
2024-05-10 13:52:11 +08:00
|
|
|
|
e.Do.IsForNode = true;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
_forVariables.Push(e.Iterator.IdentifierName);
|
|
|
|
|
};
|
2024-05-10 13:52:11 +08:00
|
|
|
|
|
|
|
|
|
statement.OnWhileGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
e.Do.IsWhileNode = true;
|
|
|
|
|
e.Condition.IsWhileCondition = true;
|
|
|
|
|
};
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(Statement statement)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(statement);
|
|
|
|
|
|
|
|
|
|
statement.OnAssignGenerator += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"{e.Variable.VariableName} = {e.Expression.VariableName};");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
statement.OnForGenerator += (_, _) =>
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
{_forVariables.Peek()} = {_forVariables.Peek()} + 1;
|
|
|
|
|
goto {_forConditionLabels.Peek()};
|
|
|
|
|
{_forEndLabels.Peek()}:;
|
|
|
|
|
""");
|
|
|
|
|
|
|
|
|
|
_forLabels.Pop();
|
|
|
|
|
_forConditionLabels.Pop();
|
|
|
|
|
_forEndLabels.Pop();
|
|
|
|
|
_forVariables.Pop();
|
|
|
|
|
_forBeginConditions.Pop();
|
|
|
|
|
_forEndConditions.Pop();
|
|
|
|
|
};
|
2024-05-10 13:52:11 +08:00
|
|
|
|
|
|
|
|
|
statement.OnWhileGenerator += (_, _) =>
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
goto {_whileBeginLabels.Peek()};
|
|
|
|
|
{_whileEndLabels.Peek()}:;
|
|
|
|
|
""");
|
|
|
|
|
_whileBeginLabels.Pop();
|
|
|
|
|
_whileEndLabels.Pop();
|
|
|
|
|
_whileConditionNames.Pop();
|
|
|
|
|
};
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(ElsePart elsePart)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(elsePart);
|
|
|
|
|
|
|
|
|
|
// 这是成功分支跳过Else的语句
|
|
|
|
|
Builder.AddLine($"goto {_ifEndLabels.Peek()};");
|
|
|
|
|
Builder.AddLine($"{_ifFalseLabels.Peek()}:;");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(ElsePart elsePart)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(elsePart);
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"{_ifEndLabels.Peek()}:;");
|
|
|
|
|
_ifConditionNames.Pop();
|
|
|
|
|
_ifTrueLabels.Pop();
|
|
|
|
|
_ifFalseLabels.Pop();
|
|
|
|
|
_ifEndLabels.Pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(ProcedureCall procedureCall)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(procedureCall);
|
|
|
|
|
|
|
|
|
|
Builder.AddLine(GenerateProcedureCall(procedureCall.ProcedureId.IdentifierName, procedureCall.Parameters) +
|
|
|
|
|
";");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(SubprogramHead subprogramHead)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(subprogramHead);
|
|
|
|
|
|
|
|
|
|
subprogramHead.OnProcedureGenerator += (_, _) =>
|
|
|
|
|
{
|
|
|
|
|
GenerateProcedureHead(subprogramHead.SubprogramName.IdentifierName);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
subprogramHead.OnFunctionGenerator += (_, _) =>
|
|
|
|
|
{
|
|
|
|
|
GenerateProcedureHead(subprogramHead.SubprogramName.IdentifierName);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Symbol? _function;
|
|
|
|
|
|
|
|
|
|
private void GenerateProcedureHead(string procedureId)
|
|
|
|
|
{
|
|
|
|
|
if (!SymbolTable.TryGetParent(out SymbolTable? parent))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!parent.TryGetSymbol(procedureId, out Symbol? symbol))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (symbol.SymbolType is not PascalFunctionType functionType)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_function = symbol;
|
|
|
|
|
string result =
|
|
|
|
|
$"{GenerateBasicTypeString(functionType.ReturnType)} {procedureId}_pascal_procedure(";
|
|
|
|
|
|
|
|
|
|
// 控制格式
|
|
|
|
|
bool isStart = true;
|
|
|
|
|
|
|
|
|
|
foreach (PascalParameterType parameter in functionType.Parameters)
|
|
|
|
|
{
|
|
|
|
|
string value = string.Empty;
|
|
|
|
|
|
|
|
|
|
if (parameter.ParameterType is PascalBasicType)
|
|
|
|
|
{
|
2024-05-12 14:29:18 +08:00
|
|
|
|
value = $"{GenerateBasicTypeString(parameter.ParameterType)} {parameter.ParameterName}";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parameter.ParameterType is PascalArrayType)
|
|
|
|
|
{
|
|
|
|
|
value = $"{GenerateArrayTypeString(parameter.ParameterType)} {parameter.ParameterName}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isStart)
|
|
|
|
|
{
|
|
|
|
|
result += value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result += ", " + value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isStart = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result += ")";
|
|
|
|
|
|
|
|
|
|
Builder.AddLine(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreVisit(SubprogramBody subprogramBody)
|
|
|
|
|
{
|
|
|
|
|
base.PreVisit(subprogramBody);
|
|
|
|
|
|
|
|
|
|
Builder.BeginScope();
|
|
|
|
|
|
|
|
|
|
if (_function is null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PascalFunctionType functionType = _function.SymbolType.Convert<PascalFunctionType>();
|
|
|
|
|
|
|
|
|
|
if (functionType.ReturnType != PascalBasicType.Void)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"{GenerateBasicTypeString(functionType.ReturnType)} {_function.SymbolName};");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(SubprogramBody subprogramBody)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(subprogramBody);
|
|
|
|
|
|
|
|
|
|
if (_function is null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PascalFunctionType functionType = _function.SymbolType.Convert<PascalFunctionType>();
|
|
|
|
|
|
|
|
|
|
if (functionType.ReturnType != PascalBasicType.Void)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"return {_function.SymbolName};");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Builder.EndScope();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PostVisit(TerminatedSyntaxNode terminatedSyntaxNode)
|
|
|
|
|
{
|
|
|
|
|
base.PostVisit(terminatedSyntaxNode);
|
|
|
|
|
|
|
|
|
|
if (terminatedSyntaxNode.Token.TokenType == SemanticTokenType.Keyword)
|
|
|
|
|
{
|
|
|
|
|
KeywordType keywordType = terminatedSyntaxNode.Token.Convert<KeywordSemanticToken>().KeywordType;
|
|
|
|
|
|
|
|
|
|
switch (keywordType)
|
|
|
|
|
{
|
|
|
|
|
case KeywordType.Then:
|
|
|
|
|
GenerateIfLabel();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
if ({_ifConditionNames.Peek()})
|
|
|
|
|
goto {_ifTrueLabels.Peek()};
|
|
|
|
|
else
|
|
|
|
|
goto {_ifFalseLabels.Peek()};
|
|
|
|
|
{_ifTrueLabels.Peek()}:;
|
|
|
|
|
""");
|
|
|
|
|
break;
|
|
|
|
|
case KeywordType.To:
|
|
|
|
|
GenerateForLabel();
|
|
|
|
|
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
{_forVariables.Peek()} = {_forBeginConditions.Peek()};
|
|
|
|
|
{_forConditionLabels.Peek()}:;
|
|
|
|
|
""");
|
|
|
|
|
break;
|
|
|
|
|
case KeywordType.Do:
|
2024-05-10 13:52:11 +08:00
|
|
|
|
if (terminatedSyntaxNode.IsForNode)
|
|
|
|
|
{
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
if ({_forVariables.Peek()} <= {_forEndConditions.Peek()})
|
|
|
|
|
goto {_forLabels.Peek()};
|
|
|
|
|
else
|
|
|
|
|
goto {_forEndLabels.Peek()};
|
|
|
|
|
{_forLabels.Peek()}:;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (terminatedSyntaxNode.IsWhileNode)
|
|
|
|
|
{
|
|
|
|
|
// GenerateWhileLabel();
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
if (!{_whileConditionNames.Peek()})
|
|
|
|
|
goto {_whileEndLabels.Peek()};
|
|
|
|
|
""");
|
|
|
|
|
}
|
2024-05-12 20:28:56 +08:00
|
|
|
|
break;
|
|
|
|
|
case KeywordType.And:
|
|
|
|
|
// 加上and短路的判断代码
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
if (!{_termVariableName})
|
|
|
|
|
goto {_andCircuitLabels.Peek().Circuit};
|
|
|
|
|
""");
|
|
|
|
|
break;
|
|
|
|
|
case KeywordType.Or:
|
|
|
|
|
// 加上or短路的判断代码
|
|
|
|
|
Builder.AddLine($"""
|
|
|
|
|
if ({_simpleExpressionVairableName})
|
|
|
|
|
goto {_orCircuitLabels.Peek().Circuit};
|
|
|
|
|
""");
|
2024-05-04 11:56:06 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GenerateProcedureCall(string procedureId, List<Expression> parameters)
|
|
|
|
|
{
|
|
|
|
|
string isReturn = procedureId == "writeln" || procedureId == "readln" ? "\\n" : string.Empty;
|
|
|
|
|
|
|
|
|
|
if (procedureId == "write" || procedureId == "writeln")
|
|
|
|
|
{
|
2024-05-10 16:45:21 +08:00
|
|
|
|
string result = $"printf(\"{GenerateFormatString(parameters, true) + isReturn}\"";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
|
|
|
|
|
foreach (Expression parameter in parameters)
|
|
|
|
|
{
|
|
|
|
|
result += $", {parameter.VariableName}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result + ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (procedureId == "read" || procedureId == "readln")
|
|
|
|
|
{
|
|
|
|
|
string result = $"scanf(\"{GenerateFormatString(parameters) + isReturn}\"";
|
|
|
|
|
|
|
|
|
|
foreach (Expression parameter in parameters)
|
|
|
|
|
{
|
|
|
|
|
result += $", &{parameter.VariableName}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result + ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!SymbolTable.TryGetSymbol(procedureId, out Symbol? symbol))
|
|
|
|
|
{
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string parameterValue = string.Empty;
|
|
|
|
|
|
|
|
|
|
PascalFunctionType functionType;
|
|
|
|
|
if (symbol.SymbolType is not PascalFunctionType innerType)
|
|
|
|
|
{
|
|
|
|
|
// 处理函数内部的递归调用
|
|
|
|
|
if (!SymbolTable.TryGetParent(out SymbolTable? parent))
|
|
|
|
|
{
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!parent.TryGetSymbol(procedureId, out symbol))
|
|
|
|
|
{
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (symbol.SymbolType is PascalFunctionType outerType)
|
|
|
|
|
{
|
|
|
|
|
functionType = outerType;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
functionType = innerType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ((Expression parameter, PascalParameterType parameterType) in
|
|
|
|
|
parameters.Zip(functionType.Parameters))
|
|
|
|
|
{
|
2024-05-12 14:29:18 +08:00
|
|
|
|
if (parameterType.ParameterType.IsReference)
|
2024-05-04 11:56:06 +08:00
|
|
|
|
{
|
2024-05-12 14:29:18 +08:00
|
|
|
|
parameterValue += $", &{parameter.VariableName}";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
parameterValue += $", {parameter.VariableName}";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parameterValue = parameterValue == string.Empty ? parameterValue : parameterValue[1..];
|
|
|
|
|
return $"{procedureId}_pascal_procedure({parameterValue})";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GenerateFormatString(List<Expression> expressions, bool output = false)
|
|
|
|
|
{
|
|
|
|
|
string value = string.Empty;
|
|
|
|
|
|
|
|
|
|
foreach (Expression expression in expressions)
|
|
|
|
|
{
|
|
|
|
|
if (expression.VariableType == PascalBasicType.Integer)
|
|
|
|
|
{
|
2024-05-10 16:45:21 +08:00
|
|
|
|
value += "%d";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expression.VariableType == PascalBasicType.Real)
|
|
|
|
|
{
|
|
|
|
|
// 这里需要按照输出调整
|
2024-05-10 16:45:21 +08:00
|
|
|
|
// 在输出real的前面需要添加一个空格
|
|
|
|
|
value += output ? "%.6lf" : "%lf";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expression.VariableType == PascalBasicType.Character)
|
|
|
|
|
{
|
2024-05-10 16:45:21 +08:00
|
|
|
|
value += "%c";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 16:45:21 +08:00
|
|
|
|
return value;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GenerateBasicTypeString(PascalType pascalType)
|
|
|
|
|
{
|
2024-05-12 14:29:18 +08:00
|
|
|
|
if (pascalType is not PascalBasicType basicType)
|
2024-05-04 11:56:06 +08:00
|
|
|
|
{
|
2024-05-12 14:29:18 +08:00
|
|
|
|
return string.Empty;
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 14:29:18 +08:00
|
|
|
|
switch (basicType.Type)
|
2024-05-04 11:56:06 +08:00
|
|
|
|
{
|
2024-05-12 14:29:18 +08:00
|
|
|
|
case BasicType.Integer:
|
|
|
|
|
return basicType.IsReference ? "int *" : "int";
|
|
|
|
|
case BasicType.Real:
|
|
|
|
|
return basicType.IsReference ? "double *" : "double";
|
|
|
|
|
case BasicType.Character:
|
|
|
|
|
return basicType.IsReference ? "char *" : "char";
|
|
|
|
|
case BasicType.Boolean:
|
|
|
|
|
return basicType.IsReference ? "bool *" : "bool";
|
2024-05-12 20:28:56 +08:00
|
|
|
|
case BasicType.Void:
|
|
|
|
|
return "void";
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static (string, string) GenerateArrayTypeString(PascalType pascalType)
|
|
|
|
|
{
|
|
|
|
|
string periodString = string.Empty;
|
|
|
|
|
|
|
|
|
|
while (pascalType is PascalArrayType arrayType)
|
|
|
|
|
{
|
|
|
|
|
periodString += $"[{arrayType.End - arrayType.Begin + 1}]";
|
|
|
|
|
|
|
|
|
|
pascalType = arrayType.ElementType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (GenerateBasicTypeString(pascalType), periodString);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GenerateMultipleOperator(MultiplyOperator multiplyOperator)
|
|
|
|
|
{
|
|
|
|
|
if (multiplyOperator.OperatorToken.TokenType == SemanticTokenType.Operator)
|
|
|
|
|
{
|
|
|
|
|
OperatorType operatorType = multiplyOperator.OperatorToken.Convert<OperatorSemanticToken>().OperatorType;
|
|
|
|
|
if (operatorType == OperatorType.Multiply)
|
|
|
|
|
{
|
|
|
|
|
return "*";
|
|
|
|
|
}
|
|
|
|
|
else if (operatorType == OperatorType.Divide)
|
|
|
|
|
{
|
|
|
|
|
//实数除法,需要将操作数强转为double
|
|
|
|
|
return "/(double)";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
KeywordType keywordType = multiplyOperator.OperatorToken.Convert<KeywordSemanticToken>().KeywordType;
|
|
|
|
|
switch (keywordType)
|
|
|
|
|
{
|
|
|
|
|
case KeywordType.And:
|
|
|
|
|
return "&&";
|
|
|
|
|
case KeywordType.Mod:
|
|
|
|
|
return "%";
|
|
|
|
|
case KeywordType.Divide:
|
|
|
|
|
return "/";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GenerateAddOperator(AddOperator addOperator)
|
|
|
|
|
{
|
|
|
|
|
SemanticToken token = addOperator.OperatorToken;
|
|
|
|
|
if (token.TokenType == SemanticTokenType.Operator)
|
|
|
|
|
{
|
|
|
|
|
OperatorType operatorType = token.Convert<OperatorSemanticToken>().OperatorType;
|
|
|
|
|
if (operatorType == OperatorType.Plus)
|
|
|
|
|
{
|
|
|
|
|
return "+";
|
|
|
|
|
}
|
|
|
|
|
else if (operatorType == OperatorType.Minus)
|
|
|
|
|
{
|
|
|
|
|
return "-";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return "||";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GenerateRelationOperator(RelationOperator relationOperator)
|
|
|
|
|
{
|
|
|
|
|
var operatorType = relationOperator.OperatorToken.Convert<OperatorSemanticToken>().OperatorType;
|
|
|
|
|
switch (operatorType)
|
|
|
|
|
{
|
|
|
|
|
case OperatorType.Equal:
|
|
|
|
|
return "==";
|
|
|
|
|
case OperatorType.Greater:
|
|
|
|
|
return ">";
|
|
|
|
|
case OperatorType.Less:
|
|
|
|
|
return "<";
|
|
|
|
|
case OperatorType.GreaterEqual:
|
|
|
|
|
return ">=";
|
|
|
|
|
case OperatorType.LessEqual:
|
|
|
|
|
return "<=";
|
|
|
|
|
case OperatorType.NotEqual:
|
|
|
|
|
return "!=";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private long _temporaryVariableCount;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 产生一个全局唯一的临时变量名
|
|
|
|
|
/// </summary>
|
|
|
|
|
private string GenerateTemporaryVariable()
|
|
|
|
|
{
|
|
|
|
|
string name = $"__temp_{_temporaryVariableCount}";
|
|
|
|
|
_temporaryVariableCount += 1;
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private long _labelCount;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 产生一对IF语句中的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void GenerateIfLabel()
|
|
|
|
|
{
|
|
|
|
|
_ifTrueLabels.Push($"if_true_{_labelCount}");
|
|
|
|
|
_ifFalseLabels.Push($"if_false_{_labelCount}");
|
|
|
|
|
_ifEndLabels.Push($"_if_end_{_labelCount}");
|
|
|
|
|
|
|
|
|
|
_labelCount += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 产生FOR语句中的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void GenerateForLabel()
|
|
|
|
|
{
|
|
|
|
|
_forLabels.Push($"for_{_labelCount}");
|
|
|
|
|
_forConditionLabels.Push($"for_condition_{_labelCount}");
|
|
|
|
|
_forEndLabels.Push($"for_end_{_labelCount}");
|
|
|
|
|
|
|
|
|
|
_labelCount += 1;
|
|
|
|
|
}
|
2024-05-10 13:52:11 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 产生WHILE语句中的标签
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void GenerateWhileLabel()
|
|
|
|
|
{
|
|
|
|
|
_whileBeginLabels.Push($"while_{_labelCount}");
|
|
|
|
|
_whileConditionNames.Push($"while_condition_{_labelCount}");
|
|
|
|
|
_whileEndLabels.Push($"while_end_{_labelCount}");
|
|
|
|
|
|
|
|
|
|
_labelCount += 1;
|
|
|
|
|
}
|
2024-05-04 11:56:06 +08:00
|
|
|
|
}
|