diff --git a/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml b/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml index ecd131e..fe83073 100644 --- a/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml +++ b/Compiler/.idea/.idea.Compiler/.idea/contentModel.xml @@ -7,8 +7,10 @@ + + diff --git a/Compiler/.idea/.idea.Compiler/.idea/workspace.xml b/Compiler/.idea/.idea.Compiler/.idea/workspace.xml index 578830b..252fb4d 100644 --- a/Compiler/.idea/.idea.Compiler/.idea/workspace.xml +++ b/Compiler/.idea/.idea.Compiler/.idea/workspace.xml @@ -20,12 +20,13 @@ + + + + - - - - + @@ -169,7 +173,7 @@ - + @@ -227,22 +231,22 @@ - + - - + + - - + + - - + + - + @@ -311,10 +315,10 @@ - + - + @@ -331,14 +335,14 @@ - + - - + + - + @@ -348,23 +352,4 @@ - - - - - file://$PROJECT_DIR$/Compiler.cs - 138 - - - - - - - - - - \ No newline at end of file diff --git a/Compiler/Compiler.cs b/Compiler/Compiler.cs index 1d66f96..0b2a1f9 100644 --- a/Compiler/Compiler.cs +++ b/Compiler/Compiler.cs @@ -25,30 +25,7 @@ namespace Compiler } else { - 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 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 tokens = TestLexer(file, 0); - TestParser(tokens, file, 1); + DevFunctions.DevMode(); } } } @@ -57,7 +34,7 @@ namespace Compiler { bool debug = false; 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) { @@ -134,91 +111,5 @@ namespace Compiler 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 TestLexer(string path, int debugLevel) - { - Lexer.Lexer lexer = new Lexer.Lexer(); - - - StreamReader file = new StreamReader(path); - string contents = file.ReadToEnd(); - - List 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 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; - } } } \ No newline at end of file diff --git a/Compiler/DevFunctions.cs b/Compiler/DevFunctions.cs new file mode 100644 index 0000000..86280b2 --- /dev/null +++ b/Compiler/DevFunctions.cs @@ -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 TestLexer(string path, int debugLevel) + { + Lexer.Lexer lexer = new Lexer.Lexer(); + + + StreamReader file = new StreamReader(path); + string contents = file.ReadToEnd(); + + List 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 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 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 tokens = TestLexer(file, 0); + Node programNode = TestParser(tokens, file, 0); + TestGenerator(programNode, 1); + } + */ + } + } + } +} \ No newline at end of file diff --git a/Compiler/Generator/Generator.cs b/Compiler/Generator/Generator.cs index c3337b0..84c2c4e 100644 --- a/Compiler/Generator/Generator.cs +++ b/Compiler/Generator/Generator.cs @@ -32,14 +32,40 @@ namespace Compiler.Generator $"{functionBody}"; break; case NodeType.ReturnStatementNode: - s = $"movl ${Generate(rootNode.Children[0])}, %eax \n" + + s = $"{Generate(rootNode.Children[0])}" + "ret\n"; break; 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; default: - throw new ArgumentOutOfRangeException(); + throw new NotSpecifiedException(rootNode.NodeType); } return s; diff --git a/Compiler/Generator/NotSpecifiedException.cs b/Compiler/Generator/NotSpecifiedException.cs new file mode 100644 index 0000000..e9e5990 --- /dev/null +++ b/Compiler/Generator/NotSpecifiedException.cs @@ -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."; + } + } +} \ No newline at end of file diff --git a/test b/test new file mode 100755 index 0000000..e69de29