From 93dd1d5183e6fc77b11bb68656edd4c429a2c460 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Mon, 26 Feb 2024 20:14:03 +0000 Subject: [PATCH 01/12] Switched to pragma --- include/ast.hpp | 5 +---- include/ast_constant.hpp | 5 +---- include/ast_context.hpp | 5 +---- include/ast_direct_declarator.hpp | 5 +---- include/ast_function_definition.hpp | 5 +---- include/ast_identifier.hpp | 5 +---- include/ast_jump_statement.hpp | 5 +---- include/ast_node.hpp | 5 +---- include/ast_type_specifier.hpp | 5 +---- include/cli.h | 5 +---- 10 files changed, 10 insertions(+), 40 deletions(-) diff --git a/include/ast.hpp b/include/ast.hpp index 67c58f8..c269fe4 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -1,5 +1,4 @@ -#ifndef AST_HPP -#define AST_HPP +#pragma once #include #include @@ -15,5 +14,3 @@ #include "ast_context.hpp" extern Node *ParseAST(std::string file_name); - -#endif diff --git a/include/ast_constant.hpp b/include/ast_constant.hpp index df0371d..43bbf30 100644 --- a/include/ast_constant.hpp +++ b/include/ast_constant.hpp @@ -1,5 +1,4 @@ -#ifndef AST_CONSTANT_HPP -#define AST_CONSTANT_HPP +#pragma once #include "ast_node.hpp" @@ -14,5 +13,3 @@ class IntConstant : public Node void EmitRISC(std::ostream &stream, Context &context) const override; void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/ast_context.hpp b/include/ast_context.hpp index f0cad25..6d1ef1c 100644 --- a/include/ast_context.hpp +++ b/include/ast_context.hpp @@ -1,5 +1,4 @@ -#ifndef AST_CONTEXT_HPP -#define AST_CONTEXT_HPP +#pragma once // An object of class Context is passed between AST nodes during compilation. // This can be used to pass around information about what's currently being @@ -8,5 +7,3 @@ class Context { /* TODO decide what goes inside here */ }; - -#endif diff --git a/include/ast_direct_declarator.hpp b/include/ast_direct_declarator.hpp index 55cc8c1..0c1ebe6 100644 --- a/include/ast_direct_declarator.hpp +++ b/include/ast_direct_declarator.hpp @@ -1,5 +1,4 @@ -#ifndef AST_DIRECT_DECLARATOR_HPP -#define AST_DIRECT_DECLARATOR_HPP +#pragma once #include "ast_node.hpp" @@ -17,5 +16,3 @@ class DirectDeclarator : public Node void EmitRISC(std::ostream &stream, Context &context) const override; void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/ast_function_definition.hpp b/include/ast_function_definition.hpp index 506c99c..6cc78f8 100644 --- a/include/ast_function_definition.hpp +++ b/include/ast_function_definition.hpp @@ -1,5 +1,4 @@ -#ifndef AST_FUNCTION_DEFINITION_HPP -#define AST_FUNCTION_DEFINITION_HPP +#pragma once #include "ast_node.hpp" @@ -21,5 +20,3 @@ class FunctionDefinition : public Node void EmitRISC(std::ostream &stream, Context &context) const override; void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/ast_identifier.hpp b/include/ast_identifier.hpp index 3e080bd..ede9609 100644 --- a/include/ast_identifier.hpp +++ b/include/ast_identifier.hpp @@ -1,5 +1,4 @@ -#ifndef AST_IDENTIFIER_HPP -#define AST_IDENTIFIER_HPP +#pragma once #include "ast_node.hpp" @@ -14,5 +13,3 @@ class Identifier : public Node void EmitRISC(std::ostream &stream, Context &context) const override; void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/ast_jump_statement.hpp b/include/ast_jump_statement.hpp index 35fbf84..b845fd3 100644 --- a/include/ast_jump_statement.hpp +++ b/include/ast_jump_statement.hpp @@ -1,5 +1,4 @@ -#ifndef AST_JUMP_STATEMENT_HPP -#define AST_JUMP_STATEMENT_HPP +#pragma once #include "ast_node.hpp" @@ -18,5 +17,3 @@ class ReturnStatement : public Node void EmitRISC(std::ostream &stream, Context &context) const override; void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/ast_node.hpp b/include/ast_node.hpp index b0ebdee..e576cfb 100644 --- a/include/ast_node.hpp +++ b/include/ast_node.hpp @@ -1,5 +1,4 @@ -#ifndef AST_NODE_HPP -#define AST_NODE_HPP +#pragma once #include #include @@ -39,5 +38,3 @@ class NodeList : public Node virtual void EmitRISC(std::ostream &stream, Context &context) const override; virtual void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/ast_type_specifier.hpp b/include/ast_type_specifier.hpp index bda5719..fe93680 100644 --- a/include/ast_type_specifier.hpp +++ b/include/ast_type_specifier.hpp @@ -1,5 +1,4 @@ -#ifndef AST_TYPE_SPECIFIER -#define AST_TYPE_SPECIFIER +#pragma once #include "ast_node.hpp" @@ -14,5 +13,3 @@ class TypeSpecifier : public Node void EmitRISC(std::ostream &stream, Context &context) const override; void Print(std::ostream &stream) const override; }; - -#endif diff --git a/include/cli.h b/include/cli.h index e1ef73a..2e3750d 100644 --- a/include/cli.h +++ b/include/cli.h @@ -1,5 +1,4 @@ -#ifndef LANGPROC_COMPILER_CLI_H -#define LANGPROC_COMPILER_CLI_H +#pragma once #include #include @@ -11,5 +10,3 @@ struct CommandLineArguments }; CommandLineArguments ParseCommandLineArgs(int argc, char **argv); - -#endif From 6463126b7b67500471252e94461cca2fcd128e98 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Thu, 29 Feb 2024 23:03:54 +0000 Subject: [PATCH 02/12] Refactored use of raw pointers to std::unique_ptr, added const-ness, created AST namespace --- debugging/example-backtrace-3.cpp | 4 +- include/ast.hpp | 2 +- include/ast_constant.hpp | 8 +++- include/ast_context.hpp | 3 ++ include/ast_direct_declarator.hpp | 17 ++++---- include/ast_function_definition.hpp | 24 +++++----- include/ast_identifier.hpp | 10 +++-- include/ast_jump_statement.hpp | 16 +++---- include/ast_node.hpp | 37 +++++++--------- include/ast_type_specifier.hpp | 28 +++++++----- src/ast_constant.cpp | 8 +++- src/ast_direct_declarator.cpp | 8 +++- src/ast_function_definition.cpp | 11 +++-- src/ast_identifier.cpp | 8 +++- src/ast_jump_statement.cpp | 8 +++- src/ast_node.cpp | 22 ++++------ src/ast_type_specifier.cpp | 8 ---- src/compiler.cpp | 68 +++++++++++++++-------------- src/lexer.flex | 14 +++--- src/parser.y | 49 +++++++++------------ 20 files changed, 186 insertions(+), 167 deletions(-) delete mode 100644 src/ast_type_specifier.cpp diff --git a/debugging/example-backtrace-3.cpp b/debugging/example-backtrace-3.cpp index 9c44f09..187b239 100644 --- a/debugging/example-backtrace-3.cpp +++ b/debugging/example-backtrace-3.cpp @@ -2,9 +2,9 @@ #include #include -const char *ARRAY_OF_NUMBERS[] = { "1", "2" , "99" }; +const char* ARRAY_OF_NUMBERS[] = { "1", "2" , "99" }; -static int process_arguments(int argc, const char *argv[]) +static int process_arguments(int argc, const char* argv[]) { std::vector numbers(argc - 1); for (int i = 1 ; i < argc ; i++) { diff --git a/include/ast.hpp b/include/ast.hpp index c269fe4..a3d618b 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -13,4 +13,4 @@ #include "ast_constant.hpp" #include "ast_context.hpp" -extern Node *ParseAST(std::string file_name); +extern AST::Node* ParseAST(std::string file_name); diff --git a/include/ast_constant.hpp b/include/ast_constant.hpp index 43bbf30..455bf98 100644 --- a/include/ast_constant.hpp +++ b/include/ast_constant.hpp @@ -2,6 +2,8 @@ #include "ast_node.hpp" +namespace AST { + class IntConstant : public Node { private: @@ -10,6 +12,8 @@ class IntConstant : public Node public: IntConstant(int value) : value_(value) {} - void EmitRISC(std::ostream &stream, Context &context) const override; - void Print(std::ostream &stream) const override; + void EmitRISC(std::ostream& stream, Context& context) const override; + void Print(std::ostream& stream) const override; }; + +} // namespace AST diff --git a/include/ast_context.hpp b/include/ast_context.hpp index 6d1ef1c..e2393ee 100644 --- a/include/ast_context.hpp +++ b/include/ast_context.hpp @@ -1,5 +1,6 @@ #pragma once +namespace AST { // An object of class Context is passed between AST nodes during compilation. // This can be used to pass around information about what's currently being // compiled (e.g. function scope and variable names). @@ -7,3 +8,5 @@ class Context { /* TODO decide what goes inside here */ }; + +} // namespace AST diff --git a/include/ast_direct_declarator.hpp b/include/ast_direct_declarator.hpp index 0c1ebe6..d48611f 100644 --- a/include/ast_direct_declarator.hpp +++ b/include/ast_direct_declarator.hpp @@ -2,17 +2,18 @@ #include "ast_node.hpp" +namespace AST { + class DirectDeclarator : public Node { private: - Node *identifier_; + NodePtr identifier_; public: - DirectDeclarator(Node *identifier) : identifier_(identifier){}; - ~DirectDeclarator() - { - delete identifier_; - }; - void EmitRISC(std::ostream &stream, Context &context) const override; - void Print(std::ostream &stream) const override; + DirectDeclarator(Node* identifier) : identifier_(identifier){}; + + void EmitRISC(std::ostream& stream, Context& context) const override; + void Print(std::ostream& stream) const override; }; + +} // namespace AST diff --git a/include/ast_function_definition.hpp b/include/ast_function_definition.hpp index 6cc78f8..703e527 100644 --- a/include/ast_function_definition.hpp +++ b/include/ast_function_definition.hpp @@ -1,22 +1,22 @@ #pragma once #include "ast_node.hpp" +#include "ast_type_specifier.hpp" + +namespace AST { class FunctionDefinition : public Node { private: - Node *declaration_specifiers_; - Node *declarator_; - Node *compound_statement_; + const TypeSpecifier declaration_specifiers_; + NodePtr declarator_; + NodePtr compound_statement_; public: - FunctionDefinition(Node *declaration_specifiers, Node *declarator, Node *compound_statement) : declaration_specifiers_(declaration_specifiers), declarator_(declarator), compound_statement_(compound_statement){}; - ~FunctionDefinition() - { - delete declaration_specifiers_; - delete declarator_; - delete compound_statement_; - }; - void EmitRISC(std::ostream &stream, Context &context) const override; - void Print(std::ostream &stream) const override; + FunctionDefinition(TypeSpecifier declaration_specifiers, Node* declarator, Node* compound_statement) : declaration_specifiers_(declaration_specifiers), declarator_(declarator), compound_statement_(compound_statement){}; + + void EmitRISC(std::ostream& stream, Context& context) const override; + void Print(std::ostream& stream) const override; }; + +} // namespace AST diff --git a/include/ast_identifier.hpp b/include/ast_identifier.hpp index ede9609..2ec2577 100644 --- a/include/ast_identifier.hpp +++ b/include/ast_identifier.hpp @@ -2,6 +2,8 @@ #include "ast_node.hpp" +namespace AST { + class Identifier : public Node { private: @@ -9,7 +11,9 @@ class Identifier : public Node public: Identifier(std::string identifier) : identifier_(identifier){}; - ~Identifier(){}; - void EmitRISC(std::ostream &stream, Context &context) const override; - void Print(std::ostream &stream) const override; + + void EmitRISC(std::ostream& stream, Context& context) const override; + void Print(std::ostream& stream) const override; }; + +} // namespace AST diff --git a/include/ast_jump_statement.hpp b/include/ast_jump_statement.hpp index b845fd3..4340e8f 100644 --- a/include/ast_jump_statement.hpp +++ b/include/ast_jump_statement.hpp @@ -2,18 +2,18 @@ #include "ast_node.hpp" +namespace AST { + class ReturnStatement : public Node { private: - Node *expression_; + NodePtr expression_; public: - ReturnStatement(Node *expression) : expression_(expression) {} - ~ReturnStatement() - { - delete expression_; - }; + ReturnStatement(Node* expression) : expression_(expression) {} - void EmitRISC(std::ostream &stream, Context &context) const override; - void Print(std::ostream &stream) const override; + void EmitRISC(std::ostream& stream, Context& context) const override; + void Print(std::ostream& stream) const override; }; + +} // namespace AST diff --git a/include/ast_node.hpp b/include/ast_node.hpp index e576cfb..39b3a4e 100644 --- a/include/ast_node.hpp +++ b/include/ast_node.hpp @@ -1,40 +1,35 @@ #pragma once #include +#include #include #include "ast_context.hpp" +namespace AST { + class Node { -protected: - std::vector branches_; - public: - Node(){}; - virtual ~Node(); - virtual void EmitRISC(std::ostream &stream, Context &context) const = 0; - virtual void Print(std::ostream &stream) const = 0; + virtual ~Node() {} + virtual void EmitRISC(std::ostream& stream, Context& context) const = 0; + virtual void Print(std::ostream& stream) const = 0; }; +using NodePtr = std::unique_ptr; + // Represents a list of nodes. class NodeList : public Node { private: - std::vector nodes_; + std::vector nodes_; public: - NodeList(Node *first_node) : nodes_({first_node}) {} - - ~NodeList() - { - for (auto node : nodes_) - { - delete node; - } - } - - void PushBack(Node *item); - virtual void EmitRISC(std::ostream &stream, Context &context) const override; - virtual void Print(std::ostream &stream) const override; + NodeList(Node* first_node) { nodes_.emplace_back(first_node); } + + void PushBack(Node* item); + virtual void EmitRISC(std::ostream& stream, Context& context) const override; + virtual void Print(std::ostream& stream) const override; }; + +} // namespace AST diff --git a/include/ast_type_specifier.hpp b/include/ast_type_specifier.hpp index fe93680..40e373b 100644 --- a/include/ast_type_specifier.hpp +++ b/include/ast_type_specifier.hpp @@ -1,15 +1,23 @@ #pragma once -#include "ast_node.hpp" +#include +#include -class TypeSpecifier : public Node +namespace AST { + +enum class TypeSpecifier { -private: - std::string type_; - -public: - TypeSpecifier(std::string type) : type_(type){}; - ~TypeSpecifier(){}; - void EmitRISC(std::ostream &stream, Context &context) const override; - void Print(std::ostream &stream) const override; + INT }; + +constexpr std::string_view ToString(TypeSpecifier type) +{ + switch (type) + { + case TypeSpecifier::INT: + return "int"; + } + throw std::runtime_error("Unexpected type specifier"); +} + +} diff --git a/src/ast_constant.cpp b/src/ast_constant.cpp index ac47791..7e21695 100644 --- a/src/ast_constant.cpp +++ b/src/ast_constant.cpp @@ -1,11 +1,15 @@ #include "ast_constant.hpp" -void IntConstant::EmitRISC(std::ostream &stream, Context &context) const +namespace AST { + +void IntConstant::EmitRISC(std::ostream& stream, Context& context) const { stream << "li a0, " << value_ << std::endl; } -void IntConstant::Print(std::ostream &stream) const +void IntConstant::Print(std::ostream& stream) const { stream << value_; } + +} // namespace AST diff --git a/src/ast_direct_declarator.cpp b/src/ast_direct_declarator.cpp index 92fe8fc..8c5f7ea 100644 --- a/src/ast_direct_declarator.cpp +++ b/src/ast_direct_declarator.cpp @@ -1,12 +1,16 @@ #include "ast_direct_declarator.hpp" -void DirectDeclarator::EmitRISC(std::ostream &stream, Context &context) const +namespace AST { + +void DirectDeclarator::EmitRISC(std::ostream& stream, Context& context) const { identifier_->EmitRISC(stream, context); stream << ":" << std::endl; } -void DirectDeclarator::Print(std::ostream &stream) const +void DirectDeclarator::Print(std::ostream& stream) const { identifier_->Print(stream); } + +} // namespace AST diff --git a/src/ast_function_definition.cpp b/src/ast_function_definition.cpp index 2eaf6c6..11e1adb 100644 --- a/src/ast_function_definition.cpp +++ b/src/ast_function_definition.cpp @@ -1,6 +1,8 @@ #include "ast_function_definition.hpp" -void FunctionDefinition::EmitRISC(std::ostream &stream, Context &context) const +namespace AST { + +void FunctionDefinition::EmitRISC(std::ostream& stream, Context& context) const { // Emit assembler directives. // TODO: these are just examples ones, make sure you understand @@ -16,10 +18,9 @@ void FunctionDefinition::EmitRISC(std::ostream &stream, Context &context) const } } -void FunctionDefinition::Print(std::ostream &stream) const +void FunctionDefinition::Print(std::ostream& stream) const { - declaration_specifiers_->Print(stream); - stream << " "; + stream << ToString(declaration_specifiers_) << " "; declarator_->Print(stream); stream << "() {" << std::endl; @@ -30,3 +31,5 @@ void FunctionDefinition::Print(std::ostream &stream) const } stream << "}" << std::endl; } + +} diff --git a/src/ast_identifier.cpp b/src/ast_identifier.cpp index cf54d34..b4cd8b0 100644 --- a/src/ast_identifier.cpp +++ b/src/ast_identifier.cpp @@ -1,11 +1,15 @@ #include "ast_identifier.hpp" -void Identifier::EmitRISC(std::ostream &stream, Context &context) const +namespace AST { + +void Identifier::EmitRISC(std::ostream& stream, Context& context) const { stream << identifier_; } -void Identifier::Print(std::ostream &stream) const +void Identifier::Print(std::ostream& stream) const { stream << identifier_; }; + +} diff --git a/src/ast_jump_statement.cpp b/src/ast_jump_statement.cpp index 6a8c499..9799a77 100644 --- a/src/ast_jump_statement.cpp +++ b/src/ast_jump_statement.cpp @@ -1,6 +1,8 @@ #include "ast_jump_statement.hpp" -void ReturnStatement::EmitRISC(std::ostream &stream, Context &context) const +namespace AST { + +void ReturnStatement::EmitRISC(std::ostream& stream, Context& context) const { if (expression_ != nullptr) { @@ -9,7 +11,7 @@ void ReturnStatement::EmitRISC(std::ostream &stream, Context &context) const stream << "ret" << std::endl; } -void ReturnStatement::Print(std::ostream &stream) const +void ReturnStatement::Print(std::ostream& stream) const { stream << "return"; if (expression_ != nullptr) @@ -19,3 +21,5 @@ void ReturnStatement::Print(std::ostream &stream) const } stream << ";" << std::endl; } + +} diff --git a/src/ast_node.cpp b/src/ast_node.cpp index e3ab627..a64fe27 100644 --- a/src/ast_node.cpp +++ b/src/ast_node.cpp @@ -1,21 +1,15 @@ #include "ast_node.hpp" -Node::~Node() -{ - for (auto branch : branches_) - { - delete branch; - } -} +namespace AST { -void NodeList::PushBack(Node *item) +void NodeList::PushBack(Node* item) { - nodes_.push_back(item); + nodes_.emplace_back(item); } -void NodeList::EmitRISC(std::ostream &stream, Context &context) const +void NodeList::EmitRISC(std::ostream& stream, Context& context) const { - for (auto node : nodes_) + for (const auto& node : nodes_) { if (node == nullptr) { @@ -25,9 +19,9 @@ void NodeList::EmitRISC(std::ostream &stream, Context &context) const } } -void NodeList::Print(std::ostream &stream) const +void NodeList::Print(std::ostream& stream) const { - for (auto node : nodes_) + for (const auto& node : nodes_) { if (node == nullptr) { @@ -36,3 +30,5 @@ void NodeList::Print(std::ostream &stream) const node->Print(stream); } } + +} diff --git a/src/ast_type_specifier.cpp b/src/ast_type_specifier.cpp deleted file mode 100644 index 71ba511..0000000 --- a/src/ast_type_specifier.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "ast_type_specifier.hpp" - -void TypeSpecifier::EmitRISC(std::ostream &stream, Context &context) const {} - -void TypeSpecifier::Print(std::ostream &stream) const -{ - stream << type_; -} diff --git a/src/compiler.cpp b/src/compiler.cpp index 1d41250..bbb8880 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4,41 +4,17 @@ #include "cli.h" #include "ast.hpp" -Node *Parse(CommandLineArguments &args) -{ - std::cout << "Parsing: " << args.compile_source_path << std::endl; - auto root = ParseAST(args.compile_source_path); - std::cout << "AST parsing complete" << std::endl; - return root; -} +using AST::NodePtr; + +NodePtr Parse(const CommandLineArguments& args); // Output the pretty print version of what was parsed to the .printed output // file. -void PrettyPrint(Node *root, CommandLineArguments &args) -{ - auto output_path = args.compile_output_path + ".printed"; - - std::cout << "Printing parsed AST..." << std::endl; - std::ofstream output(output_path, std::ios::trunc); - root->Print(output); - output.close(); - std::cout << "Printed parsed AST to: " << output_path << std::endl; -} +void PrettyPrint(const NodePtr& root, const CommandLineArguments& args); // Compile from the root of the AST and output this to the // args.compiledOutputPath file. -void Compile(Node *root, CommandLineArguments &args) -{ - // Create a Context. This can be used to pass around information about - // what's currently being compiled (e.g. function scope and variable names). - Context ctx; - - std::cout << "Compiling parsed AST..." << std::endl; - std::ofstream output(args.compile_output_path, std::ios::trunc); - root->EmitRISC(output, ctx); - output.close(); - std::cout << "Compiled to: " << args.compile_output_path << std::endl; -} +void Compile(const NodePtr& root, const CommandLineArguments& args); int main(int argc, char **argv) { @@ -58,8 +34,36 @@ int main(int argc, char **argv) PrettyPrint(ast_root, command_line_arguments); Compile(ast_root, command_line_arguments); +} - // Clean up afterwards. - delete ast_root; - return 0; +NodePtr Parse(const CommandLineArguments& args) +{ + std::cout << "Parsing: " << args.compile_source_path << std::endl; + NodePtr root{ ParseAST(args.compile_source_path) }; + std::cout << "AST parsing complete" << std::endl; + return root; +} + +void PrettyPrint(const NodePtr& root, const CommandLineArguments& args) +{ + auto output_path = args.compile_output_path + ".printed"; + + std::cout << "Printing parsed AST..." << std::endl; + std::ofstream output(output_path, std::ios::trunc); + root->Print(output); + output.close(); + std::cout << "Printed parsed AST to: " << output_path << std::endl; +} + +void Compile(const NodePtr& root, const CommandLineArguments& args) +{ + // Create a Context. This can be used to pass around information about + // what's currently being compiled (e.g. function scope and variable names). + AST::Context ctx; + + std::cout << "Compiling parsed AST..." << std::endl; + std::ofstream output(args.compile_output_path, std::ios::trunc); + root->EmitRISC(output, ctx); + output.close(); + std::cout << "Compiled to: " << args.compile_output_path << std::endl; } diff --git a/src/lexer.flex b/src/lexer.flex index 120fe38..2d7ee2f 100644 --- a/src/lexer.flex +++ b/src/lexer.flex @@ -54,14 +54,14 @@ IS (u|U|l|L)* {L}({L}|{D})* {yylval.string = new std::string(yytext); return(IDENTIFIER);} -0[xX]{H}+{IS}? {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -0{D}+{IS}? {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -{D}+{IS}? {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -L?'(\\.|[^\\'])+' {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +0[xX]{H}+{IS}? {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +0{D}+{IS}? {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +{D}+{IS}? {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +L?'(\\.|[^\\'])+' {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -{D}+{E}{FS}? {yylval.number_float = strtod(yytext, NULL); return(FLOAT_CONSTANT);} -{D}*"."{D}+({E})?{FS}? {yylval.number_float = strtod(yytext, NULL); return(FLOAT_CONSTANT);} -{D}+"."{D}*({E})?{FS}? {yylval.number_float = strtod(yytext, NULL); return(FLOAT_CONSTANT);} +{D}+{E}{FS}? {yylval.numberFloat = strtod(yytext, NULL); return(FLOAT_CONSTANT);} +{D}*"."{D}+({E})?{FS}? {yylval.numberFloat = strtod(yytext, NULL); return(FLOAT_CONSTANT);} +{D}+"."{D}*({E})?{FS}? {yylval.numberFloat = strtod(yytext, NULL); return(FLOAT_CONSTANT);} L?\"(\\.|[^\\"])*\" {/* TODO process string literal */; return(STRING_LITERAL);} diff --git a/src/parser.y b/src/parser.y index 4243310..75c7539 100644 --- a/src/parser.y +++ b/src/parser.y @@ -7,20 +7,22 @@ %code requires{ #include "ast.hpp" - extern Node *g_root; - extern FILE *yyin; + using namespace AST; + + extern Node* g_root; + extern FILE* yyin; int yylex(void); - void yyerror(const char *); + void yyerror(const char*); } -// Represents the value associated with any kind of AST node. %union{ - Node *node; - NodeList *nodes; - int number_int; - double number_float; - std::string *string; - yytokentype token; + Node* node; + NodeList* nodeList; + int numberInt; + double numberFloat; + std::string* string; + TypeSpecifier typeSpecifier; + yytokentype token; } %token IDENTIFIER INT_CONSTANT FLOAT_CONSTANT STRING_LITERAL @@ -31,22 +33,17 @@ %token STRUCT UNION ENUM ELLIPSIS %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN -%type translation_unit external_declaration function_definition primary_expression postfix_expression argument_expression_list +%type translation_unit external_declaration function_definition primary_expression postfix_expression %type unary_expression cast_expression multiplicative_expression additive_expression shift_expression relational_expression %type equality_expression and_expression exclusive_or_expression inclusive_or_expression logical_and_expression logical_or_expression -%type conditional_expression assignment_expression expression constant_expression declaration declaration_specifiers init_declarator_list -%type init_declarator type_specifier struct_specifier struct_declaration_list struct_declaration specifier_qualifier_list struct_declarator_list -%type struct_declarator enum_specifier enumerator_list enumerator declarator direct_declarator pointer parameter_list parameter_declaration -%type identifier_list type_name abstract_declarator direct_abstract_declarator initializer initializer_list statement labeled_statement -%type compound_statement declaration_list expression_statement selection_statement iteration_statement jump_statement - -%type statement_list +%type conditional_expression assignment_expression expression declarator direct_declarator statement compound_statement jump_statement -%type unary_operator assignment_operator storage_class_specifier +%type statement_list -%type INT_CONSTANT STRING_LITERAL -%type FLOAT_CONSTANT +%type INT_CONSTANT STRING_LITERAL +%type FLOAT_CONSTANT %type IDENTIFIER +%type type_specifier declaration_specifiers %start ROOT @@ -75,7 +72,7 @@ declaration_specifiers type_specifier : INT { - $$ = new TypeSpecifier("int"); + $$ = TypeSpecifier::INT; } ; @@ -125,10 +122,6 @@ postfix_expression : primary_expression ; -argument_expression_list - : assignment_expression - ; - unary_expression : postfix_expression ; @@ -191,9 +184,9 @@ expression %% -Node *g_root; +Node* g_root; -Node *ParseAST(std::string file_name) +Node* ParseAST(std::string file_name) { yyin = fopen(file_name.c_str(), "r"); if(yyin == NULL){ From b779b0b295d52447c8877677728da5d6ffcb8f09 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Fri, 1 Mar 2024 22:45:57 +0000 Subject: [PATCH 03/12] added comment and valgrind dependency --- Dockerfile | 3 ++- include/ast_node.hpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index afaf3f2..1e7a943 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,8 @@ RUN apt-get update && apt-get install -y --fix-missing \ curl \ device-tree-compiler \ lcov \ - nano + nano \ + valgrind # Install RISC-V Toolchain WORKDIR /tmp diff --git a/include/ast_node.hpp b/include/ast_node.hpp index 39b3a4e..7710040 100644 --- a/include/ast_node.hpp +++ b/include/ast_node.hpp @@ -16,9 +16,11 @@ class Node virtual void Print(std::ostream& stream) const = 0; }; +// If you don't feel comfortable using std::unique_ptr, you can switch NodePtr to be defined +// as a raw pointer instead here and your project should still compile, although you'll need +// to add destructors to avoid leaking memory using NodePtr = std::unique_ptr; -// Represents a list of nodes. class NodeList : public Node { private: From d8d7d80acdacf997632dc8d90cc436744c9ae766 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Fri, 1 Mar 2024 22:47:42 +0000 Subject: [PATCH 04/12] Removing asan from makefile as it doesn't work with valgrind --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d98ff5e..2016d4c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Based on https://stackoverflow.com/a/52036564 which is well worth reading! -CXXFLAGS += -std=c++20 -W -Wall -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -fsanitize=address -static-libasan -O0 -rdynamic --coverage -I include +CXXFLAGS += -std=c++20 -W -Wall -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -O0 -rdynamic --coverage -I include SOURCES := $(wildcard src/*.cpp) DEPENDENCIES := $(patsubst src/%.cpp,build/%.d,$(SOURCES)) From f5a5f2f6f5e8edd36e33bc37814e14903246c685 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Fri, 1 Mar 2024 23:46:07 +0000 Subject: [PATCH 05/12] Solving memory leaks --- src/parser.y | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parser.y b/src/parser.y index 75c7539..8e14f36 100644 --- a/src/parser.y +++ b/src/parser.y @@ -13,6 +13,7 @@ extern FILE* yyin; int yylex(void); void yyerror(const char*); + int yylex_destroy(void); } %union{ @@ -195,5 +196,7 @@ Node* ParseAST(std::string file_name) } g_root = nullptr; yyparse(); + yylex_destroy(); + fclose(yyin); return g_root; } From 53f775b2263fe49810846714ba8cfba9a82e41b7 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Fri, 1 Mar 2024 23:56:22 +0000 Subject: [PATCH 06/12] Fixed memory leaks *properly* --- src/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser.y b/src/parser.y index 8e14f36..b0e5a98 100644 --- a/src/parser.y +++ b/src/parser.y @@ -196,7 +196,7 @@ Node* ParseAST(std::string file_name) } g_root = nullptr; yyparse(); - yylex_destroy(); fclose(yyin); + yylex_destroy(); return g_root; } From af4ba882151753071e0a8a0c0aa128d1ac61c787 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Mon, 4 Mar 2024 20:19:40 +0000 Subject: [PATCH 07/12] Added asan flags back to makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3023171..30bcb2f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Based on https://stackoverflow.com/a/52036564 which is well worth reading! -CXXFLAGS += -std=c++20 -W -Wall -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -O0 -rdynamic --coverage -I include +CXXFLAGS += -std=c++20 -W -Wall -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -fsanitize=address -static-libasan -O0 -rdynamic --coverage -I include SOURCES := $(wildcard src/*.cpp) DEPENDENCIES := $(patsubst src/%.cpp,build/%.d,$(SOURCES)) From c2b5042e9a0eea9e8fda8fd12f734846367f3bc0 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Mon, 4 Mar 2024 23:44:01 +0100 Subject: [PATCH 08/12] Renamed parser types --- src/lexer.flex | 14 +++++++------- src/parser.y | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lexer.flex b/src/lexer.flex index 2d7ee2f..120fe38 100644 --- a/src/lexer.flex +++ b/src/lexer.flex @@ -54,14 +54,14 @@ IS (u|U|l|L)* {L}({L}|{D})* {yylval.string = new std::string(yytext); return(IDENTIFIER);} -0[xX]{H}+{IS}? {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -0{D}+{IS}? {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -{D}+{IS}? {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -L?'(\\.|[^\\'])+' {yylval.numberInt = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +0[xX]{H}+{IS}? {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +0{D}+{IS}? {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +{D}+{IS}? {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} +L?'(\\.|[^\\'])+' {yylval.number_int = (int)strtol(yytext, NULL, 0); return(INT_CONSTANT);} -{D}+{E}{FS}? {yylval.numberFloat = strtod(yytext, NULL); return(FLOAT_CONSTANT);} -{D}*"."{D}+({E})?{FS}? {yylval.numberFloat = strtod(yytext, NULL); return(FLOAT_CONSTANT);} -{D}+"."{D}*({E})?{FS}? {yylval.numberFloat = strtod(yytext, NULL); return(FLOAT_CONSTANT);} +{D}+{E}{FS}? {yylval.number_float = strtod(yytext, NULL); return(FLOAT_CONSTANT);} +{D}*"."{D}+({E})?{FS}? {yylval.number_float = strtod(yytext, NULL); return(FLOAT_CONSTANT);} +{D}+"."{D}*({E})?{FS}? {yylval.number_float = strtod(yytext, NULL); return(FLOAT_CONSTANT);} L?\"(\\.|[^\\"])*\" {/* TODO process string literal */; return(STRING_LITERAL);} diff --git a/src/parser.y b/src/parser.y index b0e5a98..9dd1fe8 100644 --- a/src/parser.y +++ b/src/parser.y @@ -18,11 +18,11 @@ %union{ Node* node; - NodeList* nodeList; - int numberInt; - double numberFloat; + NodeList* node_list; + int number_int; + double number_float; std::string* string; - TypeSpecifier typeSpecifier; + TypeSpecifier type_specifier; yytokentype token; } @@ -39,12 +39,12 @@ %type equality_expression and_expression exclusive_or_expression inclusive_or_expression logical_and_expression logical_or_expression %type conditional_expression assignment_expression expression declarator direct_declarator statement compound_statement jump_statement -%type statement_list +%type statement_list -%type INT_CONSTANT STRING_LITERAL -%type FLOAT_CONSTANT +%type INT_CONSTANT STRING_LITERAL +%type FLOAT_CONSTANT %type IDENTIFIER -%type type_specifier declaration_specifiers +%type type_specifier declaration_specifiers %start ROOT From 6f51c7eca43911e5a7d4a3e1440f7b03f72588de Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Thu, 7 Mar 2024 22:45:56 +0000 Subject: [PATCH 09/12] Addressed some PR comments --- include/ast.hpp | 2 +- include/ast_constant.hpp | 4 ++-- include/ast_context.hpp | 6 +++--- include/ast_direct_declarator.hpp | 4 ++-- include/ast_function_definition.hpp | 4 ++-- include/ast_identifier.hpp | 4 ++-- include/ast_jump_statement.hpp | 4 ++-- include/ast_node.hpp | 4 ++-- include/ast_type_specifier.hpp | 2 +- src/ast_constant.cpp | 4 ++-- src/ast_direct_declarator.cpp | 4 ++-- src/ast_function_definition.cpp | 2 +- src/ast_identifier.cpp | 2 +- src/ast_jump_statement.cpp | 2 +- src/ast_node.cpp | 2 +- src/compiler.cpp | 4 ++-- src/parser.y | 2 +- src/parser_full.y.example | 10 +++++----- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/include/ast.hpp b/include/ast.hpp index a3d618b..3c3321d 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -13,4 +13,4 @@ #include "ast_constant.hpp" #include "ast_context.hpp" -extern AST::Node* ParseAST(std::string file_name); +extern ast::Node* ParseAST(std::string file_name); diff --git a/include/ast_constant.hpp b/include/ast_constant.hpp index 455bf98..7f30138 100644 --- a/include/ast_constant.hpp +++ b/include/ast_constant.hpp @@ -2,7 +2,7 @@ #include "ast_node.hpp" -namespace AST { +namespace ast { class IntConstant : public Node { @@ -16,4 +16,4 @@ class IntConstant : public Node void Print(std::ostream& stream) const override; }; -} // namespace AST +} // namespace ast diff --git a/include/ast_context.hpp b/include/ast_context.hpp index e2393ee..a00dae9 100644 --- a/include/ast_context.hpp +++ b/include/ast_context.hpp @@ -1,7 +1,7 @@ #pragma once -namespace AST { -// An object of class Context is passed between AST nodes during compilation. +namespace ast { +// An object of class Context is passed between ast nodes during compilation. // This can be used to pass around information about what's currently being // compiled (e.g. function scope and variable names). class Context @@ -9,4 +9,4 @@ class Context /* TODO decide what goes inside here */ }; -} // namespace AST +} // namespace ast diff --git a/include/ast_direct_declarator.hpp b/include/ast_direct_declarator.hpp index d48611f..389ff9f 100644 --- a/include/ast_direct_declarator.hpp +++ b/include/ast_direct_declarator.hpp @@ -2,7 +2,7 @@ #include "ast_node.hpp" -namespace AST { +namespace ast { class DirectDeclarator : public Node { @@ -16,4 +16,4 @@ class DirectDeclarator : public Node void Print(std::ostream& stream) const override; }; -} // namespace AST +} // namespace ast diff --git a/include/ast_function_definition.hpp b/include/ast_function_definition.hpp index 703e527..f96c33d 100644 --- a/include/ast_function_definition.hpp +++ b/include/ast_function_definition.hpp @@ -3,7 +3,7 @@ #include "ast_node.hpp" #include "ast_type_specifier.hpp" -namespace AST { +namespace ast { class FunctionDefinition : public Node { @@ -19,4 +19,4 @@ class FunctionDefinition : public Node void Print(std::ostream& stream) const override; }; -} // namespace AST +} // namespace ast diff --git a/include/ast_identifier.hpp b/include/ast_identifier.hpp index 2ec2577..d0539ae 100644 --- a/include/ast_identifier.hpp +++ b/include/ast_identifier.hpp @@ -2,7 +2,7 @@ #include "ast_node.hpp" -namespace AST { +namespace ast { class Identifier : public Node { @@ -16,4 +16,4 @@ class Identifier : public Node void Print(std::ostream& stream) const override; }; -} // namespace AST +} // namespace ast diff --git a/include/ast_jump_statement.hpp b/include/ast_jump_statement.hpp index 4340e8f..a0d0108 100644 --- a/include/ast_jump_statement.hpp +++ b/include/ast_jump_statement.hpp @@ -2,7 +2,7 @@ #include "ast_node.hpp" -namespace AST { +namespace ast { class ReturnStatement : public Node { @@ -16,4 +16,4 @@ class ReturnStatement : public Node void Print(std::ostream& stream) const override; }; -} // namespace AST +} // namespace ast diff --git a/include/ast_node.hpp b/include/ast_node.hpp index 7710040..76b4fbd 100644 --- a/include/ast_node.hpp +++ b/include/ast_node.hpp @@ -6,7 +6,7 @@ #include "ast_context.hpp" -namespace AST { +namespace ast { class Node { @@ -34,4 +34,4 @@ class NodeList : public Node virtual void Print(std::ostream& stream) const override; }; -} // namespace AST +} // namespace ast diff --git a/include/ast_type_specifier.hpp b/include/ast_type_specifier.hpp index 40e373b..35d9c5d 100644 --- a/include/ast_type_specifier.hpp +++ b/include/ast_type_specifier.hpp @@ -3,7 +3,7 @@ #include #include -namespace AST { +namespace ast { enum class TypeSpecifier { diff --git a/src/ast_constant.cpp b/src/ast_constant.cpp index 7e21695..21759c0 100644 --- a/src/ast_constant.cpp +++ b/src/ast_constant.cpp @@ -1,6 +1,6 @@ #include "ast_constant.hpp" -namespace AST { +namespace ast { void IntConstant::EmitRISC(std::ostream& stream, Context& context) const { @@ -12,4 +12,4 @@ void IntConstant::Print(std::ostream& stream) const stream << value_; } -} // namespace AST +} // namespace ast diff --git a/src/ast_direct_declarator.cpp b/src/ast_direct_declarator.cpp index 8c5f7ea..ab0e19c 100644 --- a/src/ast_direct_declarator.cpp +++ b/src/ast_direct_declarator.cpp @@ -1,6 +1,6 @@ #include "ast_direct_declarator.hpp" -namespace AST { +namespace ast { void DirectDeclarator::EmitRISC(std::ostream& stream, Context& context) const { @@ -13,4 +13,4 @@ void DirectDeclarator::Print(std::ostream& stream) const identifier_->Print(stream); } -} // namespace AST +} // namespace ast diff --git a/src/ast_function_definition.cpp b/src/ast_function_definition.cpp index 11e1adb..17cc200 100644 --- a/src/ast_function_definition.cpp +++ b/src/ast_function_definition.cpp @@ -1,6 +1,6 @@ #include "ast_function_definition.hpp" -namespace AST { +namespace ast { void FunctionDefinition::EmitRISC(std::ostream& stream, Context& context) const { diff --git a/src/ast_identifier.cpp b/src/ast_identifier.cpp index b4cd8b0..b598fe1 100644 --- a/src/ast_identifier.cpp +++ b/src/ast_identifier.cpp @@ -1,6 +1,6 @@ #include "ast_identifier.hpp" -namespace AST { +namespace ast { void Identifier::EmitRISC(std::ostream& stream, Context& context) const { diff --git a/src/ast_jump_statement.cpp b/src/ast_jump_statement.cpp index 9799a77..bd90e85 100644 --- a/src/ast_jump_statement.cpp +++ b/src/ast_jump_statement.cpp @@ -1,6 +1,6 @@ #include "ast_jump_statement.hpp" -namespace AST { +namespace ast { void ReturnStatement::EmitRISC(std::ostream& stream, Context& context) const { diff --git a/src/ast_node.cpp b/src/ast_node.cpp index a64fe27..50fecfb 100644 --- a/src/ast_node.cpp +++ b/src/ast_node.cpp @@ -1,6 +1,6 @@ #include "ast_node.hpp" -namespace AST { +namespace ast { void NodeList::PushBack(Node* item) { diff --git a/src/compiler.cpp b/src/compiler.cpp index bbb8880..2794b94 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4,7 +4,7 @@ #include "cli.h" #include "ast.hpp" -using AST::NodePtr; +using ast::NodePtr; NodePtr Parse(const CommandLineArguments& args); @@ -59,7 +59,7 @@ void Compile(const NodePtr& root, const CommandLineArguments& args) { // Create a Context. This can be used to pass around information about // what's currently being compiled (e.g. function scope and variable names). - AST::Context ctx; + ast::Context ctx; std::cout << "Compiling parsed AST..." << std::endl; std::ofstream output(args.compile_output_path, std::ios::trunc); diff --git a/src/parser.y b/src/parser.y index 9dd1fe8..f3f286e 100644 --- a/src/parser.y +++ b/src/parser.y @@ -7,7 +7,7 @@ %code requires{ #include "ast.hpp" - using namespace AST; + using namespace ast; extern Node* g_root; extern FILE* yyin; diff --git a/src/parser_full.y.example b/src/parser_full.y.example index 29a4148..1861858 100644 --- a/src/parser_full.y.example +++ b/src/parser_full.y.example @@ -3,19 +3,19 @@ %code requires{ #include "ast.hpp" - extern Node *g_root; - extern FILE *yyin; + extern Node* g_root; + extern FILE* yyin; int yylex(void); void yyerror(const char *); } // Represents the value associated with any kind of AST node. %union{ - Node *node; - NodeList *nodes; + Node* node; + NodeList* nodes; int number_int; double number_float; - std::string *string; + std::string* string; yytokentype token; } From 44cea4b13891f74a2aa3e9fe66c34c7a8cc08461 Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Thu, 7 Mar 2024 22:59:18 +0000 Subject: [PATCH 10/12] NodePtr *all* the things --- include/ast.hpp | 2 +- include/ast_direct_declarator.hpp | 2 +- include/ast_function_definition.hpp | 2 +- include/ast_identifier.hpp | 2 +- include/ast_jump_statement.hpp | 2 +- include/ast_node.hpp | 4 ++-- src/ast_node.cpp | 4 ++-- src/compiler.cpp | 2 +- src/parser.y | 14 +++++++------- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/ast.hpp b/include/ast.hpp index 3c3321d..23cd246 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -13,4 +13,4 @@ #include "ast_constant.hpp" #include "ast_context.hpp" -extern ast::Node* ParseAST(std::string file_name); +ast::NodePtr ParseAST(std::string file_name); diff --git a/include/ast_direct_declarator.hpp b/include/ast_direct_declarator.hpp index 389ff9f..d14cbe2 100644 --- a/include/ast_direct_declarator.hpp +++ b/include/ast_direct_declarator.hpp @@ -10,7 +10,7 @@ class DirectDeclarator : public Node NodePtr identifier_; public: - DirectDeclarator(Node* identifier) : identifier_(identifier){}; + DirectDeclarator(NodePtr identifier) : identifier_(std::move(identifier)){}; void EmitRISC(std::ostream& stream, Context& context) const override; void Print(std::ostream& stream) const override; diff --git a/include/ast_function_definition.hpp b/include/ast_function_definition.hpp index f96c33d..e98730f 100644 --- a/include/ast_function_definition.hpp +++ b/include/ast_function_definition.hpp @@ -13,7 +13,7 @@ class FunctionDefinition : public Node NodePtr compound_statement_; public: - FunctionDefinition(TypeSpecifier declaration_specifiers, Node* declarator, Node* compound_statement) : declaration_specifiers_(declaration_specifiers), declarator_(declarator), compound_statement_(compound_statement){}; + FunctionDefinition(TypeSpecifier declaration_specifiers, NodePtr declarator, NodePtr compound_statement) : declaration_specifiers_(declaration_specifiers), declarator_(std::move(declarator)), compound_statement_(std::move(compound_statement)){}; void EmitRISC(std::ostream& stream, Context& context) const override; void Print(std::ostream& stream) const override; diff --git a/include/ast_identifier.hpp b/include/ast_identifier.hpp index d0539ae..41da20e 100644 --- a/include/ast_identifier.hpp +++ b/include/ast_identifier.hpp @@ -10,7 +10,7 @@ class Identifier : public Node std::string identifier_; public: - Identifier(std::string identifier) : identifier_(identifier){}; + Identifier(std::string identifier) : identifier_(std::move(identifier)){}; void EmitRISC(std::ostream& stream, Context& context) const override; void Print(std::ostream& stream) const override; diff --git a/include/ast_jump_statement.hpp b/include/ast_jump_statement.hpp index a0d0108..e83cfcc 100644 --- a/include/ast_jump_statement.hpp +++ b/include/ast_jump_statement.hpp @@ -10,7 +10,7 @@ class ReturnStatement : public Node NodePtr expression_; public: - ReturnStatement(Node* expression) : expression_(expression) {} + ReturnStatement(NodePtr expression) : expression_(std::move(expression)) {} void EmitRISC(std::ostream& stream, Context& context) const override; void Print(std::ostream& stream) const override; diff --git a/include/ast_node.hpp b/include/ast_node.hpp index 76b4fbd..4025b5f 100644 --- a/include/ast_node.hpp +++ b/include/ast_node.hpp @@ -27,9 +27,9 @@ class NodeList : public Node std::vector nodes_; public: - NodeList(Node* first_node) { nodes_.emplace_back(first_node); } + NodeList(NodePtr first_node) { nodes_.push_back(std::move(first_node)); } - void PushBack(Node* item); + void PushBack(NodePtr item); virtual void EmitRISC(std::ostream& stream, Context& context) const override; virtual void Print(std::ostream& stream) const override; }; diff --git a/src/ast_node.cpp b/src/ast_node.cpp index 50fecfb..74ef492 100644 --- a/src/ast_node.cpp +++ b/src/ast_node.cpp @@ -2,9 +2,9 @@ namespace ast { -void NodeList::PushBack(Node* item) +void NodeList::PushBack(NodePtr item) { - nodes_.emplace_back(item); + nodes_.push_back(std::move(item)); } void NodeList::EmitRISC(std::ostream& stream, Context& context) const diff --git a/src/compiler.cpp b/src/compiler.cpp index 2794b94..865673b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -39,7 +39,7 @@ int main(int argc, char **argv) NodePtr Parse(const CommandLineArguments& args) { std::cout << "Parsing: " << args.compile_source_path << std::endl; - NodePtr root{ ParseAST(args.compile_source_path) }; + NodePtr root = ParseAST(args.compile_source_path); std::cout << "AST parsing complete" << std::endl; return root; } diff --git a/src/parser.y b/src/parser.y index f3f286e..c28d352 100644 --- a/src/parser.y +++ b/src/parser.y @@ -63,7 +63,7 @@ external_declaration function_definition : declaration_specifiers declarator compound_statement { - $$ = new FunctionDefinition($1, $2, $3); + $$ = new FunctionDefinition($1, NodePtr($2), NodePtr($3)); } ; @@ -87,7 +87,7 @@ direct_declarator delete $1; } | direct_declarator '(' ')' { - $$ = new DirectDeclarator($1); + $$ = new DirectDeclarator(NodePtr($1)); } ; @@ -100,8 +100,8 @@ compound_statement ; statement_list - : statement { $$ = new NodeList($1); } - | statement_list statement { $1->PushBack($2); $$=$1; } + : statement { $$ = new NodeList(NodePtr($1)); } + | statement_list statement { $1->PushBack(NodePtr($2)); $$=$1; } ; jump_statement @@ -109,7 +109,7 @@ jump_statement $$ = new ReturnStatement(nullptr); } | RETURN expression ';' { - $$ = new ReturnStatement($2); + $$ = new ReturnStatement(NodePtr($2)); } ; @@ -187,7 +187,7 @@ expression Node* g_root; -Node* ParseAST(std::string file_name) +NodePtr ParseAST(std::string file_name) { yyin = fopen(file_name.c_str(), "r"); if(yyin == NULL){ @@ -198,5 +198,5 @@ Node* ParseAST(std::string file_name) yyparse(); fclose(yyin); yylex_destroy(); - return g_root; + return NodePtr(g_root); } From 94b30f4be78c8f3052ae2e01e3d301d19a471d8e Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Thu, 7 Mar 2024 23:10:55 +0000 Subject: [PATCH 11/12] Updated NodePtr comment --- include/ast_node.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/ast_node.hpp b/include/ast_node.hpp index 4025b5f..373e3f1 100644 --- a/include/ast_node.hpp +++ b/include/ast_node.hpp @@ -19,6 +19,7 @@ class Node // If you don't feel comfortable using std::unique_ptr, you can switch NodePtr to be defined // as a raw pointer instead here and your project should still compile, although you'll need // to add destructors to avoid leaking memory +// (and get rid of the now unnecessary std::move-s) using NodePtr = std::unique_ptr; class NodeList : public Node From 29fa0895a83497498fa6c1118a9bfb20b22167cf Mon Sep 17 00:00:00 2001 From: Simon Staal Date: Thu, 7 Mar 2024 23:19:58 +0000 Subject: [PATCH 12/12] Updated full parser example --- src/parser.y | 2 +- src/parser_full.y.example | 47 ++++++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/parser.y b/src/parser.y index c28d352..d7e6fbd 100644 --- a/src/parser.y +++ b/src/parser.y @@ -83,7 +83,7 @@ declarator direct_declarator : IDENTIFIER { - $$ = new Identifier(*$1); + $$ = new Identifier(std::move(*$1)); delete $1; } | direct_declarator '(' ')' { diff --git a/src/parser_full.y.example b/src/parser_full.y.example index 1861858..f52f0b5 100644 --- a/src/parser_full.y.example +++ b/src/parser_full.y.example @@ -3,20 +3,24 @@ %code requires{ #include "ast.hpp" + using namespace ast; + extern Node* g_root; extern FILE* yyin; int yylex(void); - void yyerror(const char *); + void yyerror(const char*); + int yylex_destroy(void); } // Represents the value associated with any kind of AST node. %union{ - Node* node; - NodeList* nodes; - int number_int; - double number_float; - std::string* string; - yytokentype token; + Node* node; + NodeList* node_list; + int number_int; + double number_float; + std::string* string; + TypeSpecifier type_specifier; + yytokentype token; } %token IDENTIFIER INT_CONSTANT FLOAT_CONSTANT STRING_LITERAL @@ -36,13 +40,16 @@ %type identifier_list type_name abstract_declarator direct_abstract_declarator initializer initializer_list statement labeled_statement %type compound_statement declaration_list expression_statement selection_statement iteration_statement jump_statement -%type statement_list +%type statement_list %type unary_operator assignment_operator storage_class_specifier %type INT_CONSTANT STRING_LITERAL %type FLOAT_CONSTANT %type IDENTIFIER +%type type_specifier +// TODO: Make a better type for this (only needed for advanced features) +%type declaration_specifiers %start ROOT @@ -64,7 +71,7 @@ external_declaration function_definition : declaration_specifiers declarator declaration_list compound_statement | declaration_specifiers declarator compound_statement { - $$ = new FunctionDefinition($1, $2, $3); + $$ = new FunctionDefinition($1, NodePtr($2), NodePtr($3)); } | declarator declaration_list compound_statement | declarator compound_statement @@ -245,9 +252,7 @@ type_specifier : VOID | CHAR | SHORT - | INT { - $$ = new TypeSpecifier("int"); - } + | INT { $$ = TypeSpecifier::INT; } | LONG | FLOAT | DOUBLE @@ -312,7 +317,7 @@ declarator direct_declarator : IDENTIFIER { - $$ = new Identifier(*$1); + $$ = new Identifier(std::move(*$1)); delete $1; } | '(' declarator ')' @@ -321,7 +326,7 @@ direct_declarator | direct_declarator '(' parameter_list ')' | direct_declarator '(' identifier_list ')' | direct_declarator '(' ')' { - $$ = new DirectDeclarator($1); + $$ = new DirectDeclarator(NodePtr($1)); } ; @@ -419,8 +424,8 @@ declaration_list ; statement_list - : statement { $$ = new NodeList($1); } - | statement_list statement { $1->PushBack($2); $$=$1; } + : statement { $$ = new NodeList(NodePtr($1)); } + | statement_list statement { $1->PushBack(NodePtr($2)); $$=$1; } ; expression_statement @@ -449,7 +454,7 @@ jump_statement $$ = new ReturnStatement(nullptr); } | RETURN expression ';' { - $$ = new ReturnStatement($2); + $$ = new ReturnStatement(NodePtr($2)); } ; @@ -457,9 +462,9 @@ jump_statement %% -Node *g_root; +Node* g_root; -Node *ParseAST(std::string file_name) +NodePtr ParseAST(std::string file_name) { yyin = fopen(file_name.c_str(), "r"); if(yyin == NULL){ @@ -468,5 +473,7 @@ Node *ParseAST(std::string file_name) } g_root = nullptr; yyparse(); - return g_root; + fclose(yyin); + yylex_destroy(); + return NodePtr(g_root); }