From 2cf4ff90a5ab708c00ae3babfdc06b6112bfb792 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Mon, 25 May 2026 12:18:31 +0200 Subject: [PATCH] Parser tests Signed-off-by: CHatingPython --- .clang-tidy | 3 ++- furc/include/furc/ast/declaration.hpp | 37 +++++++++++++++++++-------- furc/include/furc/handle.hpp | 11 +++++--- furc/src/front/parser.cpp | 4 +-- furc/test/parser.cpp | 33 ++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 furc/test/parser.cpp diff --git a/.clang-tidy b/.clang-tidy index bbe8587..3109f61 100755 --- a/.clang-tidy +++ b/.clang-tidy @@ -26,7 +26,8 @@ Checks: > -cppcoreguidelines-avoid-c-arrays, -cppcoreguidelines-pro-bounds-constant-array-index, -cppcoreguidelines-macro-usage, - -cppcoreguidelines-owning-memory + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-non-private-member-variables-in-classes WarningsAsErrors: "*" diff --git a/furc/include/furc/ast/declaration.hpp b/furc/include/furc/ast/declaration.hpp index ac35bbe..fee99f8 100644 --- a/furc/include/furc/ast/declaration.hpp +++ b/furc/include/furc/ast/declaration.hpp @@ -12,13 +12,15 @@ namespace furc { namespace ast { enum class declaration_node_t { - Function, + FunctionDeclaration, + FunctionDefinition, Variable, }; static inline std::ostream& operator<<(std::ostream& os, declaration_node_t type) { switch (type) { - case declaration_node_t::Function: return os << "function"; + case declaration_node_t::FunctionDeclaration: return os << "function declaration"; + case declaration_node_t::FunctionDefinition: return os << "function definition"; case declaration_node_t::Variable: return os << "variable"; } } @@ -30,7 +32,7 @@ public: virtual std::ostream& print(std::ostream& os) const = 0; friend std::ostream& operator<<(std::ostream& os, const declaration_node& node) { - os << node.type() << " declaration"; + os << node.type(); return node.print(os); } }; @@ -46,15 +48,28 @@ class function_declarartion_node : public declaration_node { public: function_declarartion_node(front::token name) : m_name(name) {} - - function_declarartion_node(front::token name, function_body&& body) - : m_name(name), m_body(std::move(body)) {} public: - declaration_node_t type() const override { return declaration_node_t::Function; } + declaration_node_t type() const override { return declaration_node_t::FunctionDeclaration; } + + front::token name() const { return m_name; } +public: + std::ostream& print(std::ostream& os) const override { return os << ": " << m_name; } +protected: + front::token m_name; +}; + +class function_definition_node : public function_declarartion_node { +public: + function_definition_node(front::token name, function_body_handle&& body) + : function_declarartion_node(name), m_body(std::move(body)) {} +public: + declaration_node_t type() const override { return declaration_node_t::FunctionDefinition; } + + const function_body_handle& body() const { return m_body; } public: std::ostream& print(std::ostream& os) const override { - os << ": " << m_name; - if (m_body.has_value()) { + os << ": " << m_name.value; + if (m_body.present()) { os << '\n' << m_body->begin << ": begin:"; for (const auto& entry : m_body->statements) { os << '\n' << entry; @@ -64,8 +79,8 @@ public: return os; } private: - front::token m_name; - std::optional m_body; + front::token m_name; + function_body_handle m_body; }; } // namespace ast diff --git a/furc/include/furc/handle.hpp b/furc/include/furc/handle.hpp index db7d550..2b9009c 100644 --- a/furc/include/furc/handle.hpp +++ b/furc/include/furc/handle.hpp @@ -115,6 +115,10 @@ public: handle(location location, std::shared_ptr value) : m_location(location), m_value(value) {} + template >> + handle(const handle& other) + : m_location(other.m_location), m_value(std::dynamic_pointer_cast(other.m_value)) {} + template >> handle(location location, Args&&... args) : m_location(location), m_value(std::make_shared(std::forward(args)...)) {} @@ -133,7 +137,8 @@ public: other.m_value = nullptr; } - template >> + template || std::is_base_of_v>> handle(handle&& other) noexcept // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved) : m_location(other.m_location), m_value(std::move(other.m_value)), m_error(std::move(other.m_error)) { other.m_value = nullptr; @@ -172,8 +177,8 @@ public: reference operator*() { return *m_value; } const_reference operator*() const { return *m_value; } - pointer operator->() { return m_value; } - const_pointer operator->() const { return m_value; } + pointer operator->() { return m_value.get(); } + const_pointer operator->() const { return m_value.get(); } public: friend std::ostream& operator<<(std::ostream& os, const handle& result) { os << result.m_location << ": "; diff --git a/furc/src/front/parser.cpp b/furc/src/front/parser.cpp index 5c8ebfd..b71ee0b 100644 --- a/furc/src/front/parser.cpp +++ b/furc/src/front/parser.cpp @@ -55,9 +55,7 @@ ast::node_handle parser::parse_declaration() { case token_t::Lbrace: { ast::function_body_handle body = parse_body(); if (body.error()) return body; - return ast::node_handle{ first.location(), - name, - std::move(body.move()) }; + return ast::node_handle{ first.location(), name, std::move(body) }; } case token_t::Semicolon: { m_peekBuffer.clear(); diff --git a/furc/test/parser.cpp b/furc/test/parser.cpp new file mode 100644 index 0000000..ad2e259 --- /dev/null +++ b/furc/test/parser.cpp @@ -0,0 +1,33 @@ +#include "furc/front/parser.hpp" + +#include "gtest/gtest.h" + +namespace { + +using namespace furc::front; +using namespace furc::ast; +using namespace std::string_view_literals; + +TEST(Parser, EmptyFunctions) { + parser parser("", "func main() {}\nfunc foo();"); + auto program = parser.parse(); + EXPECT_TRUE(program.present()); + EXPECT_EQ(program->declarations().size(), 2); + { + auto first = program->declarations()[0]; + EXPECT_TRUE(first.present()); + EXPECT_EQ(first->type(), declaration_node_t::FunctionDefinition); + node_handle funcDef = first; + EXPECT_EQ(funcDef->name().value, "main"); + EXPECT_EQ(funcDef->body()->statements.size(), 0); + } + { + auto second = program->declarations()[1]; + EXPECT_TRUE(second.present()); + EXPECT_EQ(second->type(), declaration_node_t::FunctionDeclaration); + node_handle funcDecl = second; + EXPECT_EQ(funcDecl->name().value, "foo"); + } +} + +} // namespace \ No newline at end of file