Use arena in parser

Signed-off-by: CHatingPython <chatingpython@gmail.com>
This commit is contained in:
CHatingPython
2026-05-25 15:34:05 +02:00
committed by CHatingPython
parent d2cfbb6763
commit 156aa224ee
7 changed files with 62 additions and 13 deletions
+2
View File
@@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.14)
project(furlang VERSION 0.0.0 LANGUAGES CXX)
enable_testing()
find_package(GTest REQUIRED)
add_subdirectory(furlang)
+17
View File
@@ -62,6 +62,23 @@ 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)) {}
~function_definition_node() override = default;
function_definition_node(function_definition_node&& other) noexcept
: function_declarartion_node(std::move(other)), m_name(other.m_name), m_body(std::move(other.m_body)) {}
function_definition_node(const function_definition_node&) = delete;
function_definition_node& operator=(function_definition_node&& other) noexcept {
if (this == &other) return *this;
function_declarartion_node::operator=(std::move(other));
m_name = other.m_name;
m_body = std::move(other.m_body);
return *this;
}
function_definition_node& operator=(const function_definition_node&) = delete;
public:
declaration_node_t type() const override { return declaration_node_t::FunctionDefinition; }
+3 -3
View File
@@ -35,14 +35,14 @@ public:
class declaration_node;
class declaration_statement_node : public statement_node {
public:
declaration_statement_node(declaration_node* declaration)
: m_declaration(declaration) {}
declaration_statement_node(node_handle<declaration_node>&& declaration)
: m_declaration(std::move(declaration)) {}
public:
statement_node_t type() const override { return statement_node_t::Declaration; }
std::ostream& print(std::ostream& os) const override { return os; }
private:
declaration_node* m_declaration = nullptr;
node_handle<declaration_node> m_declaration;
};
class return_statement_node : public statement_node {
+4 -1
View File
@@ -5,6 +5,7 @@
#include "furc/ast/node.hpp"
#include "furc/ast/program.hpp"
#include "furc/front/lexer.hpp"
#include "furlang/arena.hpp"
#include <vector>
@@ -22,7 +23,8 @@ public:
parser& operator=(parser&&) = default;
parser& operator=(const parser&) = delete;
public:
ast::node_handle<ast::program_node> parse();
// parser owns the arena :3c
ast::node_handle<ast::program_node> parse() &;
private:
ast::node_handle<ast::declaration_node> parse_declaration();
ast::node_handle<ast::statement_node> parse_statement();
@@ -36,6 +38,7 @@ private:
std::string m_filename;
std::string m_content;
lexer m_lexer;
furlang::arena m_arena;
std::vector<token_handle<>> m_peekBuffer;
};
+5
View File
@@ -2,6 +2,7 @@
#define FURC_HANDLE_HPP
#include "furc/diag.hpp"
#include "furlang/arena.hpp"
#include <memory>
#include <optional>
@@ -123,6 +124,10 @@ public:
handle(location location, Args&&... args)
: m_location(location), m_value(std::make_shared<value_type>(std::forward<Args>(args)...)) {}
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
handle(location location, furlang::arena& arena, Args&&... args)
: m_location(location), m_value(arena.allocate_shared<value_type>(std::forward<Args>(args)...)) {}
handle(location location, Error&& error)
: m_location(location), m_error(std::move(error)) {}
+9 -6
View File
@@ -25,8 +25,8 @@ parser::parser(std::string_view filename)
m_lexer = { filename, m_content };
}
ast::node_handle<ast::program_node> parser::parse() {
auto program = std::make_shared<ast::program_node>();
ast::node_handle<ast::program_node> parser::parse() & {
auto program = m_arena.allocate_shared<ast::program_node>();
while (!m_lexer.empty()) {
program->push(std::move(parse_declaration()));
@@ -55,11 +55,14 @@ ast::node_handle<ast::declaration_node> parser::parse_declaration() {
case token_t::Lbrace: {
ast::function_body_handle body = parse_body();
if (body.error()) return body;
return ast::node_handle<ast::function_definition_node>{ first.location(), name, std::move(body) };
return ast::node_handle<ast::function_definition_node>{ first.location(),
m_arena,
name,
std::move(body) };
}
case token_t::Semicolon: {
m_peekBuffer.clear();
return ast::node_handle<ast::function_declarartion_node>{ first.location(), name };
return ast::node_handle<ast::function_declarartion_node>{ first.location(), m_arena, name };
}
case token_t::None:
case token_t::Identifier:
@@ -106,7 +109,7 @@ ast::node_handle<ast::statement_node> parser::parse_statement() {
auto err = eat_token(token_t::Semicolon);
if (err.error()) return err;
return ast::node_handle<ast::return_statement_node>{ tok.location() };
return ast::node_handle<ast::return_statement_node>{ tok.location(), m_arena };
}
default: break;
}
@@ -114,7 +117,7 @@ ast::node_handle<ast::statement_node> parser::parse_statement() {
auto declaration = parse_declaration();
if (declaration.error())
return { declaration.location(), "unexpected token "s + tok->type + ", expected statement" };
return ast::node_handle<ast::declaration_statement_node>{ declaration.location(), declaration };
return ast::node_handle<ast::declaration_statement_node>{ declaration.location(), m_arena, std::move(declaration) };
}
ast::function_body_handle parser::parse_body() {
+22 -3
View File
@@ -3,6 +3,8 @@
#include <cstddef>
#include <cstdint>
#include <memory>
#include <type_traits>
namespace furlang {
@@ -29,9 +31,26 @@ public:
arena& operator=(arena&& other) noexcept;
arena& operator=(const arena&) = delete;
public:
template <typename T>
T* allocate(std::size_t count = 1) {
return reinterpret_cast<T*>(allocate(sizeof(T), count));
template <typename T, typename = std::enable_if_t<std::is_default_constructible_v<T>>>
T* allocate(std::size_t count) {
T* allocated = reinterpret_cast<T*>(allocate(sizeof(T), count));
for (std::size_t i = 0; i < count; ++i) {
new (&allocated[i]) T();
}
return allocated;
}
template <typename T, typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
T* allocate(Args&&... args) {
T* allocated = reinterpret_cast<T*>(allocate(sizeof(T), 1));
new (allocated) T(std::forward<Args>(args)...);
return allocated;
}
template <typename T, typename... Args>
std::shared_ptr<T> allocate_shared(Args&&... args) {
T* allocated = allocate<T>(std::forward<Args>(args)...);
return std::shared_ptr<T>(allocated, [](T* object) { object->~T(); });
}
void reset();