74 lines
No EOL
2.7 KiB
C#
74 lines
No EOL
2.7 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Compiler.Parser;
|
|
using Compiler.Parser.Nodes;
|
|
|
|
namespace Compiler.Generator
|
|
{
|
|
public class Generator
|
|
{
|
|
public string Generate(Node rootNode)
|
|
{
|
|
string s = "";
|
|
switch (rootNode.NodeType)
|
|
{
|
|
case NodeType.ProgramNode:
|
|
foreach (Node rootNodeChild in rootNode.Children)
|
|
{
|
|
s += Generate(rootNodeChild);
|
|
}
|
|
|
|
break;
|
|
case NodeType.FunctionNode:
|
|
string identifier = ((FunctionNode) rootNode).Name;
|
|
string functionBody = "";
|
|
foreach (Node rootNodeChild in rootNode.Children)
|
|
{
|
|
functionBody += Generate(rootNodeChild);
|
|
}
|
|
|
|
s = $".globl {identifier}\n" +
|
|
$"{identifier}:\n" +
|
|
$"{functionBody}";
|
|
break;
|
|
case NodeType.ReturnStatementNode:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"ret\n";
|
|
break;
|
|
case NodeType.ExpressionNode:
|
|
s = Generate(rootNode.Children[0]);
|
|
break;
|
|
case NodeType.ConstantNode:
|
|
s = $"movl ${((ConstantNode) rootNode).value.ToString()}, %eax\n";
|
|
break;
|
|
case NodeType.UnaryOperatorNode:
|
|
switch (((UnaryOperatorNode) rootNode).OperatorType)
|
|
{
|
|
case OperatorType.Negation:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"neg %eax\n";
|
|
break;
|
|
case OperatorType.BitwiseComplement:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"not %eax\n";
|
|
break;
|
|
case OperatorType.LogicalNegation:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"cmpl $0, %eax\n" +
|
|
"movl $0, %eax\n" + //xorl %eax, %eax should also work, but doesn't
|
|
"sete %al\n";
|
|
break;
|
|
default:
|
|
throw new NotSpecifiedException(NodeType.UnaryOperatorNode,
|
|
((UnaryOperatorNode) rootNode).OperatorType);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
throw new NotSpecifiedException(rootNode.NodeType);
|
|
}
|
|
|
|
return s;
|
|
}
|
|
}
|
|
} |