From 26d10cfef0c8b085c0c5c873fee57e85a3e88cc4 Mon Sep 17 00:00:00 2001 From: Clemens-Dautermann Date: Wed, 19 Aug 2020 22:55:28 +0200 Subject: [PATCH] Code generation and output file gen --- .../.idea.Compiler/.idea/contentModel.xml | 3 + .../.idea/.idea.Compiler/.idea/workspace.xml | 109 +++++++++++------- Compiler/Compiler.cs | 92 ++++++++++++--- Compiler/Generator/Generator.cs | 48 ++++++++ Compiler/Parser/Nodes/NodeType.cs | 4 +- Compiler/Parser/Nodes/ReturnNode.cs | 2 +- Compiler/Parser/Parser.cs | 4 +- test.s | 4 - 8 files changed, 197 insertions(+), 69 deletions(-) create mode 100644 Compiler/Generator/Generator.cs delete mode 100644 test.s diff --git a/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml b/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml index 6dcee0f..89a15d2 100644 --- a/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml +++ b/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml @@ -7,6 +7,9 @@ + + + diff --git a/Compiler/.idea/.idea.Compiler/.idea/workspace.xml b/Compiler/.idea/.idea.Compiler/.idea/workspace.xml index f144cc8..4371fd7 100644 --- a/Compiler/.idea/.idea.Compiler/.idea/workspace.xml +++ b/Compiler/.idea/.idea.Compiler/.idea/workspace.xml @@ -20,14 +20,27 @@ + + + + + + + + + @@ -80,12 +93,15 @@ @@ -148,6 +164,7 @@ + @@ -177,98 +194,102 @@ + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + diff --git a/Compiler/Compiler.cs b/Compiler/Compiler.cs index c2a760e..d24c561 100644 --- a/Compiler/Compiler.cs +++ b/Compiler/Compiler.cs @@ -1,30 +1,75 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; +using System.Threading; using Compiler.Lexer; -using Compiler.Parser; using Compiler.Parser.Nodes; namespace Compiler { public static class Compiler { - public static void Main() + public static void Main(string[] args) { - string[] validFiles = Directory.GetFiles("../../../../tests/week_1/valid"); - string[] invalidFiles = Directory.GetFiles("../../../../tests/week_1/invalid"); - - foreach (string filepath in validFiles) + if (args.Length != 1) { - List tokens = TestLexer(filepath, 0); - TestParser(tokens, filepath, 1); + Console.WriteLine("Usage: Compiler "); } - - foreach (string filepath in invalidFiles) + else { - List tokens = TestLexer(filepath, 0); - TestParser(tokens, filepath, 1); + string outputPath = args[0].Substring(0, args[0].LastIndexOf("/")); + + Compile(args[0], $"{outputPath}/assembly.s"); + Console.WriteLine($"Compiled to {outputPath}/assembly.s"); + + ProcessStartInfo startInfo = new ProcessStartInfo() + {FileName = "gcc", Arguments = $"{outputPath}/assembly.s -o {outputPath}/program"}; + Process proc = new Process() {StartInfo = startInfo,}; + proc.Start(); + + while (!proc.HasExited) + { + Thread.Sleep(1); + } + Console.WriteLine($"Assembled to {outputPath}/program"); + File.Delete($"{outputPath}/assembly.s"); + Console.WriteLine("Deleted assembly.s file. Done!"); + } + } + + + static void Compile(string inputPath, string outputPath) + { + //Lexing + Lexer.Lexer lexer = new Lexer.Lexer(); + + + StreamReader file = new StreamReader(inputPath); + string contents = file.ReadToEnd(); + + List tokens = lexer.Lex(contents); + Console.WriteLine($"Lexed {inputPath.Split("/").Last()}."); + + //Parsing + Parser.Parser p = new Parser.Parser(tokens); + + try + { + Node programNode = p.Parse(NodeType.ProgramNode); + Console.WriteLine($"Parsed \"{inputPath.Split("/").Last()}\""); + + //Generating + Generator.Generator generator = new Generator.Generator(); + string program = generator.Generate(programNode); + + File.WriteAllText(outputPath, program); + } + catch (Exception e) + { + Console.WriteLine($"Error in file \"{inputPath.Split("/").Last()}\""); + Console.WriteLine(e.Message); } } @@ -37,6 +82,20 @@ namespace Compiler } } + 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 TestLexer(string path, int debugLevel) { Lexer.Lexer lexer = new Lexer.Lexer(); @@ -50,20 +109,17 @@ namespace Compiler if (debugLevel > 0) { - Console.WriteLine("-----------" + path + "-----------"); foreach (Token token in tokens) { Console.WriteLine(token.ToString()); } - - Console.WriteLine("--------------------------------------"); } return tokens; } - static void TestParser(List tokenList, string path, int debugLevel) + static Node TestParser(List tokenList, string path, int debugLevel) { Parser.Parser p = new Parser.Parser(tokenList); @@ -75,12 +131,16 @@ namespace Compiler { PrettyPrint(programNode, ""); } + + return programNode; } catch (Exception e) { Console.WriteLine("Error in file \"" + path.Split("/").Last() + "\""); Console.WriteLine(e.Message); } + + return null; } } } \ No newline at end of file diff --git a/Compiler/Generator/Generator.cs b/Compiler/Generator/Generator.cs new file mode 100644 index 0000000..c3337b0 --- /dev/null +++ b/Compiler/Generator/Generator.cs @@ -0,0 +1,48 @@ +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 = $"movl ${Generate(rootNode.Children[0])}, %eax \n" + + "ret\n"; + break; + case NodeType.ExpressionNode: + s = ((ConstantNode) rootNode).value.ToString(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return s; + } + } +} \ No newline at end of file diff --git a/Compiler/Parser/Nodes/NodeType.cs b/Compiler/Parser/Nodes/NodeType.cs index 028b427..a60cebd 100644 --- a/Compiler/Parser/Nodes/NodeType.cs +++ b/Compiler/Parser/Nodes/NodeType.cs @@ -1,10 +1,10 @@ -namespace Compiler.Parser +namespace Compiler.Parser.Nodes { public enum NodeType { ProgramNode, FunctionNode, - StatementNode, + ReturnStatementNode, ExpressionNode } } \ No newline at end of file diff --git a/Compiler/Parser/Nodes/ReturnNode.cs b/Compiler/Parser/Nodes/ReturnNode.cs index 1ff24bc..ba6dace 100644 --- a/Compiler/Parser/Nodes/ReturnNode.cs +++ b/Compiler/Parser/Nodes/ReturnNode.cs @@ -6,7 +6,7 @@ namespace Compiler.Parser.Nodes public ReturnNode() { - this.NodeType = NodeType.StatementNode; + this.NodeType = NodeType.ReturnStatementNode; } } } \ No newline at end of file diff --git a/Compiler/Parser/Parser.cs b/Compiler/Parser/Parser.cs index cff73fe..ee3a5d5 100644 --- a/Compiler/Parser/Parser.cs +++ b/Compiler/Parser/Parser.cs @@ -80,14 +80,14 @@ namespace Compiler.Parser CheckFirstTokenAndRemove(TokenType.OpenBraceToken); //add returned child node to AST - n.Children.Add(Parse(NodeType.StatementNode)); + n.Children.Add(Parse(NodeType.ReturnStatementNode)); //remove trailing } CheckFirstTokenAndRemove(TokenType.CloseBraceToken); break; - case NodeType.StatementNode: + case NodeType.ReturnStatementNode: //TODO: This Type of return/statement node will probably need fixing later n = new ReturnNode(); diff --git a/test.s b/test.s deleted file mode 100644 index bdee87d..0000000 --- a/test.s +++ /dev/null @@ -1,4 +0,0 @@ - .globl main -main: - movl $15, %eax - ret