@@ -79,6 +79,12 @@ struct function_declaration_param {
|
|||||||
type type;
|
type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class function_declaration_node_t {
|
||||||
|
Normal = 0,
|
||||||
|
Import,
|
||||||
|
Native,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Function declaration AST node.
|
* @brief Function declaration AST node.
|
||||||
*/
|
*/
|
||||||
@@ -92,11 +98,16 @@ public:
|
|||||||
* @param type Return type of the function.
|
* @param type Return type of the function.
|
||||||
*/
|
*/
|
||||||
template <typename T, typename ParamsFwd>
|
template <typename T, typename ParamsFwd>
|
||||||
function_declaration_node(struct location location, T&& name, std::optional<type>&& returnType, ParamsFwd&& params)
|
function_declaration_node(struct location location,
|
||||||
|
T&& name,
|
||||||
|
std::optional<type>&& returnType,
|
||||||
|
ParamsFwd&& params,
|
||||||
|
function_declaration_node_t type = function_declaration_node_t::Normal)
|
||||||
: declaration_node(location),
|
: declaration_node(location),
|
||||||
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)),
|
||||||
|
p_type(type) {}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns this node's declaration type.
|
* @brief Returns this node's declaration type.
|
||||||
@@ -125,6 +136,13 @@ public:
|
|||||||
* @return Function's parameters.
|
* @return Function's parameters.
|
||||||
*/
|
*/
|
||||||
const std::vector<function_declaration_param>& params() const { return p_params; }
|
const std::vector<function_declaration_param>& params() const { return p_params; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns function's type.
|
||||||
|
*
|
||||||
|
* @return Function's type.
|
||||||
|
*/
|
||||||
|
function_declaration_node_t type() const { return p_type; }
|
||||||
public:
|
public:
|
||||||
void accept(visitor& visitor) const override;
|
void accept(visitor& visitor) const override;
|
||||||
|
|
||||||
@@ -140,12 +158,17 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* @brief Return type of the function.
|
* @brief Return type of the function.
|
||||||
*/
|
*/
|
||||||
std::optional<type> p_returnType;
|
std::optional<class type> p_returnType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Parameters of the function.
|
* @brief Parameters of the function.
|
||||||
*/
|
*/
|
||||||
std::vector<function_declaration_param> p_params;
|
std::vector<function_declaration_param> p_params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of the function declaration.
|
||||||
|
*/
|
||||||
|
function_declaration_node_t p_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,7 +187,7 @@ public:
|
|||||||
template <typename T, typename ParamsFwd>
|
template <typename T, typename ParamsFwd>
|
||||||
function_definition_node(struct location location,
|
function_definition_node(struct location location,
|
||||||
T&& name,
|
T&& name,
|
||||||
std::optional<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, std::forward<T>(name), std::move(type), std::forward<ParamsFwd>(params)),
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ enum class keyword_token {
|
|||||||
If, /**< `if` */
|
If, /**< `if` */
|
||||||
Else, /**< `else` */
|
Else, /**< `else` */
|
||||||
While, /**< `while` */
|
While, /**< `while` */
|
||||||
|
Import, /**< `import` */
|
||||||
|
Native, /**< `native` */
|
||||||
|
|
||||||
Int32, /**< `int32` */
|
Int32, /**< `int32` */
|
||||||
};
|
};
|
||||||
@@ -165,6 +167,8 @@ static inline std::ostream& operator<<(std::ostream& os, keyword_token keyword)
|
|||||||
case keyword_token::If: return os << "if";
|
case keyword_token::If: return os << "if";
|
||||||
case keyword_token::Else: return os << "else";
|
case keyword_token::Else: return os << "else";
|
||||||
case keyword_token::While: return os << "while";
|
case keyword_token::While: return os << "while";
|
||||||
|
case keyword_token::Import: return os << "import";
|
||||||
|
case keyword_token::Native: return os << "native";
|
||||||
case keyword_token::Int32: return os << "int32";
|
case keyword_token::Int32: return os << "int32";
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
@@ -178,6 +182,8 @@ static inline std::string operator+(const std::string& str, keyword_token keywor
|
|||||||
case keyword_token::If: return str + "if";
|
case keyword_token::If: return str + "if";
|
||||||
case keyword_token::Else: return str + "else";
|
case keyword_token::Else: return str + "else";
|
||||||
case keyword_token::While: return str + "while";
|
case keyword_token::While: return str + "while";
|
||||||
|
case keyword_token::Import: return str + "import";
|
||||||
|
case keyword_token::Native: return str + "native";
|
||||||
case keyword_token::Int32: return str + "int32";
|
case keyword_token::Int32: return str + "int32";
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ token_r lexer::next_token() {
|
|||||||
{ "if", keyword_token::If },
|
{ "if", keyword_token::If },
|
||||||
{ "else", keyword_token::Else },
|
{ "else", keyword_token::Else },
|
||||||
{ "while", keyword_token::While },
|
{ "while", keyword_token::While },
|
||||||
|
{ "import", keyword_token::Import },
|
||||||
|
{ "native", keyword_token::Native },
|
||||||
{ "int32", keyword_token::Int32 },
|
{ "int32", keyword_token::Int32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,14 +38,11 @@ ast::program_node_r parser::parse() & {
|
|||||||
|
|
||||||
while (peek_token().has_value()) {
|
while (peek_token().has_value()) {
|
||||||
auto decl = parse_declaration();
|
auto decl = parse_declaration();
|
||||||
if (decl.has_error()) {
|
if (decl.has_error()) return ast::program_node_r(ast::error{ decl.error().location });
|
||||||
program = nullptr;
|
|
||||||
} else if (program != nullptr) {
|
|
||||||
program->push(std::move(decl.value()));
|
program->push(std::move(decl.value()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return program != nullptr ? std::move(program) : ast::program_node_r(ast::error{ location{ m_filename } });
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::type_r parser::parse_type() {
|
ast::type_r parser::parse_type() {
|
||||||
@@ -59,8 +56,20 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
const auto& first = peek_token();
|
const auto& first = peek_token();
|
||||||
switch (first->type) {
|
switch (first->type) {
|
||||||
case token_t::Keyword: {
|
case token_t::Keyword: {
|
||||||
|
ast::function_declaration_node_t funcDeclType{};
|
||||||
|
|
||||||
auto first = next_token();
|
auto first = next_token();
|
||||||
switch ((*first)->keyword) {
|
switch ((*first)->keyword) {
|
||||||
|
case keyword_token::Import:
|
||||||
|
case keyword_token::Native: {
|
||||||
|
funcDeclType = ((*first)->keyword == keyword_token::Import) ? ast::function_declaration_node_t::Import
|
||||||
|
: ast::function_declaration_node_t::Native;
|
||||||
|
|
||||||
|
first = eat_token(token_t::Keyword);
|
||||||
|
if (first.has_error()) return ast::declaration_node_r(ast::error{ first.error().location });
|
||||||
|
if (first->value.keyword != keyword_token::Func)
|
||||||
|
return ast::declaration_node_r(ast::error{ first->location });
|
||||||
|
}
|
||||||
case keyword_token::Func: {
|
case keyword_token::Func: {
|
||||||
auto name = eat_token(token_t::Identifier);
|
auto name = eat_token(token_t::Identifier);
|
||||||
if (name.has_error()) return ast::declaration_node_r(ast::error{ name.error().location });
|
if (name.has_error()) return ast::declaration_node_r(ast::error{ name.error().location });
|
||||||
@@ -103,6 +112,8 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
case token_t::LBrace: {
|
case token_t::LBrace: {
|
||||||
ast::body_r body = parse_body();
|
ast::body_r body = parse_body();
|
||||||
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)
|
||||||
|
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>(first->location,
|
||||||
name->value.string,
|
name->value.string,
|
||||||
std::move(returnType),
|
std::move(returnType),
|
||||||
@@ -114,7 +125,8 @@ ast::declaration_node_r parser::parse_declaration() {
|
|||||||
return m_arena->allocate_shared<ast::function_declaration_node>(first->location,
|
return m_arena->allocate_shared<ast::function_declaration_node>(first->location,
|
||||||
name->value.string,
|
name->value.string,
|
||||||
std::move(returnType),
|
std::move(returnType),
|
||||||
std::move(params));
|
std::move(params),
|
||||||
|
funcDeclType);
|
||||||
}
|
}
|
||||||
default: return ast::declaration_node_r(ast::error{ tok->location });
|
default: return ast::declaration_node_r(ast::error{ tok->location });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
try {
|
try {
|
||||||
std::string programStr = R"(
|
std::string programStr = R"(
|
||||||
|
native func print(value: int32);
|
||||||
|
|
||||||
func main() -> int32 {
|
func main() -> int32 {
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 10;
|
y = 10;
|
||||||
|
|||||||
Reference in New Issue
Block a user