feat(furc): add access specifiers to functions
Introduce public and private access specifiers to functions. Closes: #26
This commit is contained in:
@@ -26,6 +26,16 @@ private:
|
|||||||
std::string m_name;
|
std::string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class declaration_access_t {
|
||||||
|
Implicit = 0, /**< Implicit access. */
|
||||||
|
Public, /**< Public access. */
|
||||||
|
Private, /**< Private access. */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool same_access(declaration_access_t lhs, declaration_access_t rhs) {
|
||||||
|
return lhs == declaration_access_t::Implicit || lhs == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Declaration node type.
|
* @brief Declaration node type.
|
||||||
*/
|
*/
|
||||||
@@ -43,9 +53,10 @@ public:
|
|||||||
* @brief Construct a new declaration AST node.
|
* @brief Construct a new declaration AST node.
|
||||||
*
|
*
|
||||||
* @param location Node location.
|
* @param location Node location.
|
||||||
|
* @param access Declaration access.
|
||||||
*/
|
*/
|
||||||
declaration_node(struct location location)
|
declaration_node(struct location location, declaration_access_t access)
|
||||||
: abstract_node(location) {}
|
: abstract_node(location), p_access(access) {}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns this node's category.
|
* @brief Returns this node's category.
|
||||||
@@ -67,8 +78,17 @@ public:
|
|||||||
* @return The declaration type.
|
* @return The declaration type.
|
||||||
*/
|
*/
|
||||||
virtual declaration_node_t declaration_type() const = 0;
|
virtual declaration_node_t declaration_type() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the declaration's access.
|
||||||
|
*
|
||||||
|
* @return Access.
|
||||||
|
*/
|
||||||
|
declaration_access_t access() const { return p_access; }
|
||||||
protected:
|
protected:
|
||||||
bool equal(const node& rhs) const override;
|
bool equal(const node& rhs) const override;
|
||||||
|
protected:
|
||||||
|
declaration_access_t p_access;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,11 +119,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename T, typename ParamsFwd>
|
template <typename T, typename ParamsFwd>
|
||||||
function_declaration_node(struct location location,
|
function_declaration_node(struct location location,
|
||||||
|
declaration_access_t access,
|
||||||
T&& name,
|
T&& name,
|
||||||
std::optional<type>&& returnType,
|
std::optional<type>&& returnType,
|
||||||
ParamsFwd&& params,
|
ParamsFwd&& params,
|
||||||
function_declaration_node_t type = function_declaration_node_t::Normal)
|
function_declaration_node_t type = function_declaration_node_t::Normal)
|
||||||
: declaration_node(location),
|
: declaration_node(location, access),
|
||||||
p_name(std::forward<T>(name)),
|
p_name(std::forward<T>(name)),
|
||||||
p_returnType(std::move(returnType)),
|
p_returnType(std::move(returnType)),
|
||||||
p_params(std::forward<ParamsFwd>(params)),
|
p_params(std::forward<ParamsFwd>(params)),
|
||||||
@@ -186,11 +207,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename T, typename ParamsFwd>
|
template <typename T, typename ParamsFwd>
|
||||||
function_definition_node(struct location location,
|
function_definition_node(struct location location,
|
||||||
|
declaration_access_t access,
|
||||||
T&& name,
|
T&& name,
|
||||||
std::optional<class type>&& type,
|
std::optional<class type>&& type,
|
||||||
ParamsFwd&& params,
|
ParamsFwd&& params,
|
||||||
body&& body)
|
body&& body)
|
||||||
: function_declaration_node(location, std::forward<T>(name), std::move(type), std::forward<ParamsFwd>(params)),
|
: function_declaration_node(location,
|
||||||
|
access,
|
||||||
|
std::forward<T>(name),
|
||||||
|
std::move(type),
|
||||||
|
std::forward<ParamsFwd>(params)),
|
||||||
m_body(std::move(body)) {}
|
m_body(std::move(body)) {}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ enum class keyword_token {
|
|||||||
While, /**< `while` */
|
While, /**< `while` */
|
||||||
Import, /**< `import` */
|
Import, /**< `import` */
|
||||||
Native, /**< `native` */
|
Native, /**< `native` */
|
||||||
|
Public, /**< `public` */
|
||||||
|
Private, /**< `private` */
|
||||||
|
|
||||||
Int32, /**< `int32` */
|
Int32, /**< `int32` */
|
||||||
};
|
};
|
||||||
@@ -169,6 +171,8 @@ static inline std::ostream& operator<<(std::ostream& os, keyword_token keyword)
|
|||||||
case keyword_token::While: return os << "while";
|
case keyword_token::While: return os << "while";
|
||||||
case keyword_token::Import: return os << "import";
|
case keyword_token::Import: return os << "import";
|
||||||
case keyword_token::Native: return os << "native";
|
case keyword_token::Native: return os << "native";
|
||||||
|
case keyword_token::Public: return os << "public";
|
||||||
|
case keyword_token::Private: return os << "private";
|
||||||
case keyword_token::Int32: return os << "int32";
|
case keyword_token::Int32: return os << "int32";
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
@@ -184,6 +188,8 @@ static inline std::string operator+(const std::string& str, keyword_token keywor
|
|||||||
case keyword_token::While: return str + "while";
|
case keyword_token::While: return str + "while";
|
||||||
case keyword_token::Import: return str + "import";
|
case keyword_token::Import: return str + "import";
|
||||||
case keyword_token::Native: return str + "native";
|
case keyword_token::Native: return str + "native";
|
||||||
|
case keyword_token::Public: return str + "public";
|
||||||
|
case keyword_token::Private: return str + "private";
|
||||||
case keyword_token::Int32: return str + "int32";
|
case keyword_token::Int32: return str + "int32";
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ token_r lexer::next_token() {
|
|||||||
{ "while", keyword_token::While },
|
{ "while", keyword_token::While },
|
||||||
{ "import", keyword_token::Import },
|
{ "import", keyword_token::Import },
|
||||||
{ "native", keyword_token::Native },
|
{ "native", keyword_token::Native },
|
||||||
|
{ "public", keyword_token::Public },
|
||||||
|
{ "private", keyword_token::Private },
|
||||||
{ "int32", keyword_token::Int32 },
|
{ "int32", keyword_token::Int32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+37
-10
@@ -54,21 +54,40 @@ ast::type_r parser::parse_type() {
|
|||||||
|
|
||||||
ast::declaration_node_r parser::parse_declaration() {
|
ast::declaration_node_r parser::parse_declaration() {
|
||||||
const auto& first = peek_token();
|
const auto& first = peek_token();
|
||||||
|
if (first.has_error()) return ast::declaration_node_r(ast::error{ first.error().location });
|
||||||
switch (first->type) {
|
switch (first->type) {
|
||||||
case token_t::Keyword: {
|
case token_t::Keyword: {
|
||||||
|
token firstToken = *first;
|
||||||
|
|
||||||
|
ast::declaration_access_t accessOverride = ast::declaration_access_t::Implicit;
|
||||||
|
switch ((*first)->keyword) {
|
||||||
|
default: break;
|
||||||
|
case keyword_token::Public:
|
||||||
|
case keyword_token::Private: {
|
||||||
|
if ((*first)->keyword == keyword_token::Public) accessOverride = ast::declaration_access_t::Public;
|
||||||
|
if ((*first)->keyword == keyword_token::Private) accessOverride = ast::declaration_access_t::Private;
|
||||||
|
auto kw = eat_token(token_t::Keyword);
|
||||||
|
if (kw.has_error()) return ast::declaration_node_r(ast::error{ kw.error().location });
|
||||||
|
firstToken = *kw;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
ast::function_declaration_node_t funcDeclType{};
|
ast::function_declaration_node_t funcDeclType{};
|
||||||
|
|
||||||
auto first = next_token();
|
auto kw = next_token();
|
||||||
switch ((*first)->keyword) {
|
if (kw.has_error()) return ast::declaration_node_r(ast::error{ kw.error().location });
|
||||||
|
firstToken = *kw;
|
||||||
|
switch (firstToken->keyword) {
|
||||||
case keyword_token::Import:
|
case keyword_token::Import:
|
||||||
case keyword_token::Native: {
|
case keyword_token::Native: {
|
||||||
funcDeclType = ((*first)->keyword == keyword_token::Import) ? ast::function_declaration_node_t::Import
|
funcDeclType = (firstToken->keyword == keyword_token::Import) ? ast::function_declaration_node_t::Import
|
||||||
: ast::function_declaration_node_t::Native;
|
: ast::function_declaration_node_t::Native;
|
||||||
|
|
||||||
first = eat_token(token_t::Keyword);
|
auto kw = eat_token(token_t::Keyword);
|
||||||
if (first.has_error()) return ast::declaration_node_r(ast::error{ first.error().location });
|
if (kw.has_error()) return ast::declaration_node_r(ast::error{ kw.error().location });
|
||||||
if (first->value.keyword != keyword_token::Func)
|
firstToken = *kw;
|
||||||
return ast::declaration_node_r(ast::error{ first->location });
|
if (firstToken.value.keyword != keyword_token::Func)
|
||||||
|
return ast::declaration_node_r(ast::error{ firstToken.location });
|
||||||
}
|
}
|
||||||
case keyword_token::Func: {
|
case keyword_token::Func: {
|
||||||
auto name = eat_token(token_t::Identifier);
|
auto name = eat_token(token_t::Identifier);
|
||||||
@@ -106,6 +125,12 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
returnType = *type;
|
returnType = *type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto access = (funcDeclType == ast::function_declaration_node_t::Import)
|
||||||
|
? ast::declaration_access_t::Private
|
||||||
|
: accessOverride;
|
||||||
|
if (access == ast::declaration_access_t::Implicit) access = ast::declaration_access_t::Public;
|
||||||
|
if (!ast::same_access(accessOverride, access)) return ast::declaration_node_r(ast::error{ tok->location });
|
||||||
|
|
||||||
const auto& peek = peek_token();
|
const auto& peek = peek_token();
|
||||||
if (peek.has_error()) return ast::declaration_node_r(ast::error{ peek.error().location });
|
if (peek.has_error()) return ast::declaration_node_r(ast::error{ peek.error().location });
|
||||||
switch (peek->type) {
|
switch (peek->type) {
|
||||||
@@ -114,7 +139,8 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
if (body.has_error()) return ast::declaration_node_r(ast::error{ body.error().location });
|
if (body.has_error()) return ast::declaration_node_r(ast::error{ body.error().location });
|
||||||
if (funcDeclType != ast::function_declaration_node_t::Normal)
|
if (funcDeclType != ast::function_declaration_node_t::Normal)
|
||||||
return ast::declaration_node_r(ast::error{ body->begin });
|
return ast::declaration_node_r(ast::error{ body->begin });
|
||||||
return m_arena->allocate_shared<ast::function_definition_node>(first->location,
|
return m_arena->allocate_shared<ast::function_definition_node>(firstToken.location,
|
||||||
|
access,
|
||||||
name->value.string,
|
name->value.string,
|
||||||
std::move(returnType),
|
std::move(returnType),
|
||||||
std::move(params),
|
std::move(params),
|
||||||
@@ -122,7 +148,8 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
}
|
}
|
||||||
case token_t::Semicolon: {
|
case token_t::Semicolon: {
|
||||||
m_peekBuffer.clear();
|
m_peekBuffer.clear();
|
||||||
return m_arena->allocate_shared<ast::function_declaration_node>(first->location,
|
return m_arena->allocate_shared<ast::function_declaration_node>(firstToken.location,
|
||||||
|
access,
|
||||||
name->value.string,
|
name->value.string,
|
||||||
std::move(returnType),
|
std::move(returnType),
|
||||||
std::move(params),
|
std::move(params),
|
||||||
@@ -131,7 +158,7 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
default: return ast::declaration_node_r(ast::error{ tok->location });
|
default: return ast::declaration_node_r(ast::error{ tok->location });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default: return ast::declaration_node_r(ast::error{ first->location });
|
default: return ast::declaration_node_r(ast::error{ firstToken.location });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case token_t::None:
|
case token_t::None:
|
||||||
|
|||||||
Reference in New Issue
Block a user