code generations for unary operators

This commit is contained in:
Clemens-Dautermann 2020-08-21 00:18:21 +02:00
parent 07079366b8
commit e6b20b5aa9
7 changed files with 202 additions and 153 deletions

View file

@ -7,8 +7,10 @@
<e p="Compiler.cs" t="Include" /> <e p="Compiler.cs" t="Include" />
<e p="Compiler.csproj" t="IncludeRecursive" /> <e p="Compiler.csproj" t="IncludeRecursive" />
<e p="Compiler.sln" t="IncludeFlat" /> <e p="Compiler.sln" t="IncludeFlat" />
<e p="DevFunctions.cs" t="Include" />
<e p="Generator" t="Include"> <e p="Generator" t="Include">
<e p="Generator.cs" t="Include" /> <e p="Generator.cs" t="Include" />
<e p="NotSpecifiedException.cs" t="Include" />
</e> </e>
<e p="Lexer" t="Include"> <e p="Lexer" t="Include">
<e p="Lexer.cs" t="Include" /> <e p="Lexer.cs" t="Include" />

View file

@ -20,12 +20,13 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="a54bb6de-191c-4bd1-91ab-3953adfc5dfb" name="Default Changelist" comment=""> <list default="true" id="a54bb6de-191c-4bd1-91ab-3953adfc5dfb" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/DevFunctions.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Generator/NotSpecifiedException.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../test" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Compiler/.idea/contentModel.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Compiler/.idea/contentModel.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.Compiler/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Compiler/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/.idea.Compiler/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.Compiler/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Compiler.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Compiler.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Compiler.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Compiler.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Parser/Nodes/ConstantNode.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Parser/Nodes/ConstantNode.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Generator/Generator.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Generator/Generator.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Parser/Nodes/NodeType.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Parser/Nodes/NodeType.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Parser/Nodes/UnaryOperatorNode.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Parser/Nodes/UnaryOperatorNode.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Parser/Parser.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Parser/Parser.cs" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -95,7 +96,6 @@
<option value="$PROJECT_DIR$/Parser/Exceptions/UnexpectedTokenException.cs" /> <option value="$PROJECT_DIR$/Parser/Exceptions/UnexpectedTokenException.cs" />
<option value="$PROJECT_DIR$/t.tt" /> <option value="$PROJECT_DIR$/t.tt" />
<option value="$PROJECT_DIR$/Parser/Nodes/ReturnNode.cs" /> <option value="$PROJECT_DIR$/Parser/Nodes/ReturnNode.cs" />
<option value="$PROJECT_DIR$/Generator/Generator.cs" />
<option value="$PROJECT_DIR$/Lexer/TokenType.cs" /> <option value="$PROJECT_DIR$/Lexer/TokenType.cs" />
<option value="$PROJECT_DIR$/Lexer/Lexer.cs" /> <option value="$PROJECT_DIR$/Lexer/Lexer.cs" />
<option value="$PROJECT_DIR$/../grammar" /> <option value="$PROJECT_DIR$/../grammar" />
@ -106,6 +106,10 @@
<option value="$PROJECT_DIR$/Parser/Nodes/ConstantNode.cs" /> <option value="$PROJECT_DIR$/Parser/Nodes/ConstantNode.cs" />
<option value="$PROJECT_DIR$/Parser/Parser.cs" /> <option value="$PROJECT_DIR$/Parser/Parser.cs" />
<option value="$PROJECT_DIR$/Compiler.cs" /> <option value="$PROJECT_DIR$/Compiler.cs" />
<option value="$PROJECT_DIR$/Generator/NotSpecifiedException.cs" />
<option value="$PROJECT_DIR$/../test.s" />
<option value="$PROJECT_DIR$/DevFunctions.cs" />
<option value="$PROJECT_DIR$/Generator/Generator.cs" />
</list> </list>
</option> </option>
</component> </component>
@ -169,7 +173,7 @@
<workItem from="1597695400525" duration="4873000" /> <workItem from="1597695400525" duration="4873000" />
<workItem from="1597863017034" duration="9651000" /> <workItem from="1597863017034" duration="9651000" />
<workItem from="1597932102881" duration="4296000" /> <workItem from="1597932102881" duration="4296000" />
<workItem from="1597952695048" duration="3054000" /> <workItem from="1597952695048" duration="9189000" />
</task> </task>
<servers /> <servers />
</component> </component>
@ -227,22 +231,22 @@
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state width="1868" height="383" key="GridCell.Tab.-1.right/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597955238557" /> <state width="1868" height="383" key="GridCell.Tab.-1.right/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597955238557" />
<state width="1868" height="512" key="GridCell.Tab.0.bottom" timestamp="1597955691042"> <state width="908" height="298" key="GridCell.Tab.0.bottom" timestamp="1597956915348">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state width="1868" height="512" key="GridCell.Tab.0.bottom/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597955691042" /> <state width="908" height="298" key="GridCell.Tab.0.bottom/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597956915348" />
<state width="1868" height="512" key="GridCell.Tab.0.center" timestamp="1597955691042"> <state width="908" height="298" key="GridCell.Tab.0.center" timestamp="1597956915348">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state width="1868" height="512" key="GridCell.Tab.0.center/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597955691042" /> <state width="908" height="298" key="GridCell.Tab.0.center/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597956915348" />
<state width="1868" height="512" key="GridCell.Tab.0.left" timestamp="1597955691042"> <state width="908" height="298" key="GridCell.Tab.0.left" timestamp="1597956915348">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state width="1868" height="512" key="GridCell.Tab.0.left/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597955691042" /> <state width="908" height="298" key="GridCell.Tab.0.left/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597956915348" />
<state width="1868" height="512" key="GridCell.Tab.0.right" timestamp="1597955691042"> <state width="908" height="298" key="GridCell.Tab.0.right" timestamp="1597956915348">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state width="1868" height="512" key="GridCell.Tab.0.right/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597955691042" /> <state width="908" height="298" key="GridCell.Tab.0.right/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597956915348" />
<state width="1868" height="383" key="GridCell.Tab.1.bottom" timestamp="1597955439042"> <state width="1868" height="383" key="GridCell.Tab.1.bottom" timestamp="1597955439042">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
@ -311,10 +315,10 @@
<screen x="0" y="0" width="1920" height="1080" /> <screen x="0" y="0" width="1920" height="1080" />
</state> </state>
<state x="631" y="291" width="806" height="524" key="Rider.ProjectTemplateDialog.Size/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597872082099" /> <state x="631" y="291" width="806" height="524" key="Rider.ProjectTemplateDialog.Size/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597872082099" />
<state x="2333" y="20" width="709" height="485" key="RiderGenerateDialog" timestamp="1597935008077"> <state x="2321" y="-64" width="709" height="485" key="RiderGenerateDialog" timestamp="1597956793201">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state x="2333" y="20" width="709" height="485" key="RiderGenerateDialog/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597935008077" /> <state x="2321" y="-64" width="709" height="485" key="RiderGenerateDialog/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597956793201" />
<state x="2525" y="135" width="1031" height="724" key="SettingsEditor" timestamp="1597932248704"> <state x="2525" y="135" width="1031" height="724" key="SettingsEditor" timestamp="1597932248704">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
@ -331,14 +335,14 @@
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state x="2182" y="199" width="432" height="650" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597510086756" /> <state x="2182" y="199" width="432" height="650" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597510086756" />
<state x="0" y="557" width="960" height="523" key="dock-window-1" timestamp="1597952828875"> <state x="0" y="557" width="1920" height="523" key="dock-window-1" timestamp="1597960555163">
<screen x="0" y="0" width="1920" height="1080" /> <screen x="0" y="0" width="1920" height="1080" />
</state> </state>
<state x="0" y="557" width="960" height="523" key="dock-window-1/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597952828875" /> <state x="0" y="557" width="1920" height="523" key="dock-window-1/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597960555163" />
<state x="2880" y="0" width="960" height="1080" key="dock-window-2" timestamp="1597934748776"> <state x="3200" y="0" width="640" height="1080" key="dock-window-2" timestamp="1597959520918">
<screen x="1920" y="0" width="1920" height="1080" /> <screen x="1920" y="0" width="1920" height="1080" />
</state> </state>
<state x="2880" y="0" width="960" height="1080" key="dock-window-2/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597934748776" /> <state x="3200" y="0" width="640" height="1080" key="dock-window-2/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597959520918" />
<state x="0" y="557" width="1920" height="523" key="dock-window-3" timestamp="1597934748776"> <state x="0" y="557" width="1920" height="523" key="dock-window-3" timestamp="1597934748776">
<screen x="0" y="0" width="1920" height="1080" /> <screen x="0" y="0" width="1920" height="1080" />
</state> </state>
@ -348,23 +352,4 @@
</state> </state>
<state x="2543" y="239" width="672" height="678" key="search.everywhere.popup/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597698616567" /> <state x="2543" y="239" width="672" height="678" key="search.everywhere.popup/1920.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1597698616567" />
</component> </component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/Compiler.cs</url>
<line>138</line>
<properties documentPath="$PROJECT_DIR$/Compiler.cs" initialLine="138">
<startOffsets>
<option value="4241" />
</startOffsets>
<endOffsets>
<option value="4242" />
</endOffsets>
</properties>
<option name="timeStamp" value="3" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>
</project> </project>

View file

@ -25,30 +25,7 @@ namespace Compiler
} }
else else
{ {
DevMode(); DevFunctions.DevMode();
}
}
}
static void DevMode()
{
for (int i = 1; i <= 2; i++)
{
Console.WriteLine($"---------------------valid, stage {i}-------------------------------");
foreach (string file in Directory.GetFiles($"/home/clemens/repositorys/lcc/stage_{i}/valid"))
{
Console.WriteLine("-------------");
List<Token> tokens = TestLexer(file, 0);
TestParser(tokens, file, 1);
}
Console.WriteLine($"---------------------invalid, stage {i}-------------------------------");
foreach (string file in Directory.GetFiles($"/home/clemens/repositorys/lcc/stage_{i}/invalid"))
{
Console.WriteLine("-------------");
List<Token> tokens = TestLexer(file, 0);
TestParser(tokens, file, 1);
} }
} }
} }
@ -57,7 +34,7 @@ namespace Compiler
{ {
bool debug = false; bool debug = false;
string inputFileName = args[0].Split("/").Last(); string inputFileName = args[0].Split("/").Last();
string outputPath = args[0].Substring(0, args[0].LastIndexOf("/")); string outputPath = args[0].Substring(0, args[0].LastIndexOf("/", StringComparison.Ordinal));
if (args.Length == 2) if (args.Length == 2)
{ {
@ -134,91 +111,5 @@ namespace Compiler
Console.WriteLine(e.Message); Console.WriteLine(e.Message);
} }
} }
static void PrettyPrint(Node root, string indent)
{
switch (root.NodeType)
{
case NodeType.FunctionNode:
Console.WriteLine(indent + root.NodeType + ":" + ((FunctionNode) root).Name);
break;
case NodeType.ConstantNode:
Console.WriteLine(indent + root.NodeType + ":" + ((ConstantNode) root).value);
break;
case NodeType.UnaryOperatorNode:
Console.WriteLine(indent + root.NodeType + ":" + ((UnaryOperatorNode) root).OperatorType);
break;
default:
Console.WriteLine(indent + root.NodeType);
break;
}
foreach (Node child in root.Children)
{
PrettyPrint(child, indent + " ");
}
}
static void TestGenerator(Node root, string destinationPath, int debugLevel)
{
if (root != null)
{
Generator.Generator gen = new Generator.Generator();
string asm = gen.Generate(root);
if (debugLevel > 0)
{
Console.Write(asm);
}
}
}
static List<Token> TestLexer(string path, int debugLevel)
{
Lexer.Lexer lexer = new Lexer.Lexer();
StreamReader file = new StreamReader(path);
string contents = file.ReadToEnd();
List<Token> tokens = lexer.Lex(contents);
Console.WriteLine("Lexed \"" + path.Split("/").Last() + "\"");
if (debugLevel > 0)
{
foreach (Token token in tokens)
{
Console.WriteLine(token.ToString());
}
}
return tokens;
}
static Node TestParser(List<Token> tokenList, string path, int debugLevel)
{
Parser.Parser p = new Parser.Parser(tokenList);
try
{
Node programNode = p.Parse(NodeType.ProgramNode);
Console.WriteLine("Parsed \"" + path.Split("/").Last() + "\"");
if (debugLevel > 0)
{
PrettyPrint(programNode, "");
}
return programNode;
}
catch (Exception e)
{
Console.WriteLine("Error in file \"" + path.Split("/").Last() + "\"");
Console.WriteLine(e.Message);
}
return null;
}
} }
} }

124
Compiler/DevFunctions.cs Normal file
View file

@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Compiler.Lexer;
using Compiler.Parser.Nodes;
namespace Compiler
{
public static class DevFunctions
{
static void PrettyPrint(Node root, string indent)
{
switch (root.NodeType)
{
case NodeType.FunctionNode:
Console.WriteLine(indent + root.NodeType + ":" + ((FunctionNode) root).Name);
break;
case NodeType.ConstantNode:
Console.WriteLine(indent + root.NodeType + ":" + ((ConstantNode) root).value);
break;
case NodeType.UnaryOperatorNode:
Console.WriteLine(indent + root.NodeType + ":" + ((UnaryOperatorNode) root).OperatorType);
break;
default:
Console.WriteLine(indent + root.NodeType);
break;
}
foreach (Node child in root.Children)
{
PrettyPrint(child, indent + " ");
}
}
static void TestGenerator(Node root, int debugLevel)
{
if (root != null)
{
Generator.Generator gen = new Generator.Generator();
string asm = gen.Generate(root);
if (debugLevel > 0)
{
Console.Write(asm);
}
}
}
static List<Token> TestLexer(string path, int debugLevel)
{
Lexer.Lexer lexer = new Lexer.Lexer();
StreamReader file = new StreamReader(path);
string contents = file.ReadToEnd();
List<Token> tokens = lexer.Lex(contents);
Console.WriteLine("Lexed \"" + path.Split("/").Last() + "\"");
if (debugLevel > 0)
{
foreach (Token token in tokens)
{
Console.WriteLine(token.ToString());
}
}
return tokens;
}
static Node TestParser(List<Token> tokenList, string path, int debugLevel)
{
Parser.Parser p = new Parser.Parser(tokenList);
try
{
Node programNode = p.Parse(NodeType.ProgramNode);
Console.WriteLine("Parsed \"" + path.Split("/").Last() + "\"");
if (debugLevel > 0)
{
PrettyPrint(programNode, "");
}
return programNode;
}
catch (Exception e)
{
Console.WriteLine("Error in file \"" + path.Split("/").Last() + "\"");
Console.WriteLine(e.Message);
}
return null;
}
public static void DevMode()
{
for (int i = 1; i <= 2; i++)
{
Console.WriteLine($"---------------------valid, stage {i}-------------------------------");
foreach (string file in Directory.GetFiles($"/home/clemens/repositorys/lcc/stage_{i}/valid"))
{
Console.WriteLine("-------------");
List<Token> tokens = TestLexer(file, 0);
Node programNode = TestParser(tokens, file, 1);
TestGenerator(programNode, 1);
}
/*
Console.WriteLine($"---------------------invalid, stage {i}-------------------------------");
foreach (string file in Directory.GetFiles($"/home/clemens/repositorys/lcc/stage_{i}/invalid"))
{
Console.WriteLine("-------------");
List<Token> tokens = TestLexer(file, 0);
Node programNode = TestParser(tokens, file, 0);
TestGenerator(programNode, 1);
}
*/
}
}
}
}

View file

@ -32,14 +32,40 @@ namespace Compiler.Generator
$"{functionBody}"; $"{functionBody}";
break; break;
case NodeType.ReturnStatementNode: case NodeType.ReturnStatementNode:
s = $"movl ${Generate(rootNode.Children[0])}, %eax \n" + s = $"{Generate(rootNode.Children[0])}" +
"ret\n"; "ret\n";
break; break;
case NodeType.ExpressionNode: case NodeType.ExpressionNode:
s = ((ConstantNode) rootNode).value.ToString(); 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; break;
default: default:
throw new ArgumentOutOfRangeException(); throw new NotSpecifiedException(rootNode.NodeType);
} }
return s; return s;

View file

@ -0,0 +1,21 @@
using System;
using Compiler.Lexer;
using Compiler.Parser.Nodes;
namespace Compiler.Generator
{
public class NotSpecifiedException : Exception
{
public override string Message { get; }
public NotSpecifiedException(NodeType nodeType)
{
Message = $"No code generation for {nodeType} specified.";
}
public NotSpecifiedException(NodeType nodeType, OperatorType operatorType)
{
Message = $"No code generation for {nodeType}:{operatorType} specified.";
}
}
}

0
test Executable file
View file