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