diff --git a/furc/include/furc/ast/declaration.hpp b/furc/include/furc/ast/declaration.hpp index 895b00c..7dd18d4 100644 --- a/furc/include/furc/ast/declaration.hpp +++ b/furc/include/furc/ast/declaration.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace furc { namespace ast { @@ -70,6 +71,14 @@ protected: bool equal(const node& rhs) const override; }; +/** + * @brief Parameter of function declaration AST node. + */ +struct function_declaration_param { + std::string name; + type type; +}; + /** * @brief Function declaration AST node. */ @@ -82,9 +91,12 @@ public: * @param name Name of the function. * @param type Return type of the function. */ - template - function_declaration_node(struct location location, T&& name, std::optional&& returnType) - : declaration_node(location), p_name(std::forward(name)), p_returnType(std::move(returnType)) {} + template + function_declaration_node(struct location location, T&& name, std::optional&& returnType, ParamsFwd&& params) + : declaration_node(location), + p_name(std::forward(name)), + p_returnType(std::move(returnType)), + p_params(std::forward(params)) {} public: /** * @brief Returns this node's declaration type. @@ -106,6 +118,13 @@ public: * @return Function's return type. */ const std::optional& return_type() const { return p_returnType; } + + /** + * @brief Returns function's parameters. + * + * @return Function's parameters. + */ + const std::vector& params() const { return p_params; } public: void accept(visitor& visitor) const override; @@ -122,6 +141,11 @@ protected: * @brief Return type of the function. */ std::optional p_returnType; + + /** + * @brief Parameters of the function. + */ + std::vector p_params; }; /** @@ -137,9 +161,14 @@ public: * @param type Return type of the function. * @param body Body of the function. */ - template - function_definition_node(struct location location, T&& name, std::optional&& type, body&& body) - : function_declaration_node(location, std::forward(name), std::move(type)), m_body(std::move(body)) {} + template + function_definition_node(struct location location, + T&& name, + std::optional&& type, + ParamsFwd&& params, + body&& body) + : function_declaration_node(location, std::forward(name), std::move(type), std::forward(params)), + m_body(std::move(body)) {} public: /** * @brief Returns this node's declaration type. diff --git a/furc/src/front/parser.cpp b/furc/src/front/parser.cpp index 0411c8d..4967df5 100644 --- a/furc/src/front/parser.cpp +++ b/furc/src/front/parser.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace furc::front { @@ -66,6 +67,25 @@ ast::declaration_node_r parser::parse_declaration() { auto tok = eat_token(token_t::LParen); if (tok.has_error()) return ast::declaration_node_r(ast::error{ tok.error().location }); + + std::vector params; + if (peek_token().has_value() && peek_token()->type != token_t::RParen) { + while (true) { + auto name = eat_token(token_t::Identifier); + if (name.has_error()) return ast::declaration_node_r(ast::error{ name.error().location }); + auto colon = eat_token(token_t::Colon); + if (colon.has_error()) return ast::declaration_node_r(ast::error{ colon.error().location }); + auto type = parse_type(); + if (type.has_error()) return ast::declaration_node_r(ast::error{ type.error().location }); + + params.push_back( + ast::function_declaration_param{ std::string(name->value.string), std::move(*type) }); + + auto comma = eat_token(token_t::Comma); + if (comma.has_error()) break; + } + } + tok = eat_token(token_t::RParen); if (tok.has_error()) return ast::declaration_node_r(ast::error{ tok.error().location }); @@ -86,13 +106,15 @@ ast::declaration_node_r parser::parse_declaration() { return m_arena->allocate_shared(first->location, name->value.string, std::move(returnType), + std::move(params), std::move(body.value())); } case token_t::Semicolon: { m_peekBuffer.clear(); return m_arena->allocate_shared(first->location, name->value.string, - std::move(returnType)); + std::move(returnType), + std::move(params)); } default: return ast::declaration_node_r(ast::error{ tok->location }); } @@ -465,15 +487,14 @@ const token_r& parser::peek_token() { } token_r parser::eat_token(token_t type) { - auto token = next_token(); - if (token.has_error()) return token; - if (token->type != type) { + if (const auto& token = peek_token(); token.has_error() || peek_token()->type != type) { + if (token.has_error()) return token; if (token->type == token_t::None) return token_r(token_error{ token->location, token_error_t::UnexpectedToken, ", expected " + type }); return token_r( token_error{ token->location, token_error_t::UnexpectedToken, ""s + token->type + ", expected " + type }); } - return token; + return next_token(); } } // namespace furc::front