From 016318bd70c8eb7b7983a650a8a85dc91bffcce9 Mon Sep 17 00:00:00 2001 From: Clement Doucy Date: Sun, 22 Oct 2023 23:11:09 +0200 Subject: [PATCH] Completed parsing --- doc/operator-precedence.md | 7 +- .../{FunctionCallNode.hpp => CallNode.hpp} | 16 +-- inc/ast/visitors/EvalVisitor.hpp | 8 +- inc/ast/visitors/IVisitor.hpp | 4 +- inc/parser/Parser.hpp | 3 +- src/ast/nodes/CallNode.cpp | 34 ++++++ src/ast/nodes/FunctionCallNode.cpp | 33 ------ src/ast/visitors/EvalVisitor.cpp | 9 +- src/parser/Parser.cpp | 100 +++++++++--------- src/src.cmake | 2 +- 10 files changed, 108 insertions(+), 108 deletions(-) rename inc/ast/nodes/{FunctionCallNode.hpp => CallNode.hpp} (58%) create mode 100644 src/ast/nodes/CallNode.cpp delete mode 100644 src/ast/nodes/FunctionCallNode.cpp diff --git a/doc/operator-precedence.md b/doc/operator-precedence.md index 3b76302..1e26931 100644 --- a/doc/operator-precedence.md +++ b/doc/operator-precedence.md @@ -31,14 +31,15 @@ bitshift -> term (( '>>' | '<<' ) term ) * term -> factor ( ( '-' | '+' ) factor ) * factor -> unary ( ( '/' | '*' | '%' ) unary ) * unary -> ( '+' | '-' | '!' | '~' ) unary | call -call -> Identifier '(' (expression ',')* (expression)? ')' | primary +call -> primary ( '(' params? ')' )* +params -> expression ( ',' expression )* primary -> Integer | Identifier | String | grouping grouping -> '(' expression ')' Integer -> ['0'-'9']+ Type -> 'int' | 'str' | 'fnc' FunctionSignature -FunctionSignature -> FunctionParams (Type)? block -FunctionParams -> '(' ( ( TypeIdent ',')* TypeIdent )? ')' +FunctionSignature -> FunctionParams (Type)? +FunctionParams -> '(' ( TypeIdent ( ',' TypeIdent)* )? ')' TypeIdent -> Identifier Type Identifier -> [a-zA-Z_][a-zA-Z_0-9]* String -> "*" diff --git a/inc/ast/nodes/FunctionCallNode.hpp b/inc/ast/nodes/CallNode.hpp similarity index 58% rename from inc/ast/nodes/FunctionCallNode.hpp rename to inc/ast/nodes/CallNode.hpp index 04efe72..947403a 100644 --- a/inc/ast/nodes/FunctionCallNode.hpp +++ b/inc/ast/nodes/CallNode.hpp @@ -7,27 +7,27 @@ namespace ast { - class FunctionCallNode final : public ExpressionNode + class CallNode final : public ExpressionNode { public: - using ptr = std::shared_ptr; + using ptr = std::shared_ptr; static ptr create( - const std::string &identifier, + const ExpressionNode::ptr &callee, const std::vector ¶ms ); - explicit FunctionCallNode( - std::string identifier, + explicit CallNode( + ExpressionNode::ptr callee, const std::vector ¶ms ); - ~FunctionCallNode() final = default; + ~CallNode() final = default; void accept(IVisitor &visitor) final; - [[nodiscard]] const std::string &getIdentifier() const; + [[nodiscard]] const ExpressionNode::ptr &getCallee() const; [[nodiscard]] const std::vector &getParams() const; private: - std::string _identifier; + ExpressionNode::ptr _callee; std::vector _params; }; }; \ No newline at end of file diff --git a/inc/ast/visitors/EvalVisitor.hpp b/inc/ast/visitors/EvalVisitor.hpp index 5fb7c6d..342305a 100644 --- a/inc/ast/visitors/EvalVisitor.hpp +++ b/inc/ast/visitors/EvalVisitor.hpp @@ -23,7 +23,7 @@ #include "FunctionNode.hpp" #include "ReturnNode.hpp" -#include "FunctionCallNode.hpp" +#include "CallNode.hpp" #include "ProgramNode.hpp" @@ -56,15 +56,15 @@ namespace ast void visit(IncrementNode &node) final; void visit(FunctionNode &node) final; - void visit(FunctionCallNode &node) final; + void visit(CallNode &node) final; void visit(ReturnNode &node) final; void visit(ProgramNode &node) final; - const runtime::Object &value() const noexcept; + [[nodiscard]] const runtime::Object &value() const noexcept; [[nodiscard]] Token::Integer getResult() const; - const runtime::State &getState() const noexcept; + [[nodiscard]] const runtime::State &getState() const noexcept; void clearState() noexcept; diff --git a/inc/ast/visitors/IVisitor.hpp b/inc/ast/visitors/IVisitor.hpp index c328a6e..0fb7b1b 100644 --- a/inc/ast/visitors/IVisitor.hpp +++ b/inc/ast/visitors/IVisitor.hpp @@ -21,7 +21,7 @@ namespace ast class IncrementNode; class FunctionNode; - class FunctionCallNode; + class CallNode; class ReturnNode; class ProgramNode; @@ -49,7 +49,7 @@ namespace ast virtual void visit(ForNode &node) = 0; virtual void visit(FunctionNode &node) = 0; - virtual void visit(FunctionCallNode &node) = 0; + virtual void visit(CallNode &node) = 0; virtual void visit(ReturnNode &node) = 0; virtual void visit(ProgramNode &node) = 0; diff --git a/inc/parser/Parser.hpp b/inc/parser/Parser.hpp index 39623fe..f014c08 100644 --- a/inc/parser/Parser.hpp +++ b/inc/parser/Parser.hpp @@ -53,7 +53,8 @@ class Parser ast::ExpressionNode::ptr parseTerm(); ast::ExpressionNode::ptr parseFactor(); ast::ExpressionNode::ptr parseUnary(); - ast::ExpressionNode::ptr parseFunctionCall(); + ast::ExpressionNode::ptr parseCall(); + std::vector parseParams(); ast::ExpressionNode::ptr parsePrimary(); ast::ExpressionNode::ptr parseInteger(); ast::ExpressionNode::ptr parseString(); diff --git a/src/ast/nodes/CallNode.cpp b/src/ast/nodes/CallNode.cpp new file mode 100644 index 0000000..baa3ff2 --- /dev/null +++ b/src/ast/nodes/CallNode.cpp @@ -0,0 +1,34 @@ +#include "CallNode.hpp" + +#include + +ast::CallNode::ptr ast::CallNode::create( + const ast::ExpressionNode::ptr &callee, + const std::vector ¶ms +) +{ + return std::make_shared(callee, params); +} + +ast::CallNode::CallNode( + ast::ExpressionNode::ptr callee, + const std::vector ¶ms +): _callee(std::move(callee)), + _params(params) +{ +} + +void ast::CallNode::accept(ast::IVisitor &visitor) +{ + visitor.visit(*this); +} + +const ast::ExpressionNode::ptr &ast::CallNode::getCallee() const +{ + return this->_callee; +} + +const std::vector &ast::CallNode::getParams() const +{ + return this->_params; +} diff --git a/src/ast/nodes/FunctionCallNode.cpp b/src/ast/nodes/FunctionCallNode.cpp deleted file mode 100644 index b8dbfc4..0000000 --- a/src/ast/nodes/FunctionCallNode.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "FunctionCallNode.hpp" - -#include - -ast::FunctionCallNode::ptr ast::FunctionCallNode::create( - const std::string &identifier, - const std::vector ¶ms -) { - return std::make_shared(identifier, params); -} - -ast::FunctionCallNode::FunctionCallNode( - std::string identifier, - const std::vector ¶ms -): _identifier(std::move(identifier)), - _params(params) -{ -} - -void ast::FunctionCallNode::accept(ast::IVisitor &visitor) -{ - visitor.visit(*this); -} - -const std::string &ast::FunctionCallNode::getIdentifier() const -{ - return this->_identifier; -} - -const std::vector &ast::FunctionCallNode::getParams() const -{ - return this->_params; -} diff --git a/src/ast/visitors/EvalVisitor.cpp b/src/ast/visitors/EvalVisitor.cpp index a26feb7..c8ca890 100644 --- a/src/ast/visitors/EvalVisitor.cpp +++ b/src/ast/visitors/EvalVisitor.cpp @@ -251,22 +251,19 @@ void ast::EvalVisitor::visit(ast::IncrementNode &node) auto &object = this->_state->find(node.getIdentifier()); switch (node.getOperator()) { - default: - throw InternalError("EvalVisitor : invalid operator in IncrementNode"); case Token::INCR: object.assign(object + 1); break; case Token::DECR: object.assign(object - 1); break; -// default: -// throw InternalError("EvalVisitor : invalid operator in IncrementNode"); + default: + throw InternalError("EvalVisitor : invalid operator in IncrementNode"); } } void ast::EvalVisitor::visit(ast::FunctionNode &node) { - } -void ast::EvalVisitor::visit(ast::FunctionCallNode &node) +void ast::EvalVisitor::visit(ast::CallNode &node) { } diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp index 0540c1d..4ccc196 100644 --- a/src/parser/Parser.cpp +++ b/src/parser/Parser.cpp @@ -379,39 +379,35 @@ ast::StatementNode::ptr Parser::parseFunction() throw syntaxError("expecting identifier", *fncToken); this->_tokenItr.advance(); - auto token = this->_tokenItr.get(); - if (!token || !token->isType(Token::OPEN_PARENTHESIS)) + auto open_p = this->_tokenItr.get(); + if (!open_p || !open_p->isType(Token::OPEN_PARENTHESIS)) throw syntaxError("expecting '('", *identToken); this->_tokenItr.advance(); - std::clog << "FUNCTION" << std::endl; - std::map params; auto typeIdent = this->parseTypeIdent(); - if (typeIdent) { - while (true) { - if (params.find(typeIdent->first) != params.end()) - throw syntaxError("parameter name already used", *this->_tokenItr.prev()); + while (typeIdent) { + + if (params.find(typeIdent->first) != params.end()) + throw syntaxError("parameter name already used", *this->_tokenItr.prev()); - std::clog << "ident = " << typeIdent->first << std::endl; - params.insert(*typeIdent); + params.insert(*typeIdent); - token = this->_tokenItr.get(); - if (!token || !token->isType(Token::COMMA)) - break; - this->_tokenItr.advance(); + auto token = this->_tokenItr.get(); + if (!token || !token->isType(Token::COMMA)) + break; + this->_tokenItr.advance(); - typeIdent = this->parseTypeIdent(); - } + typeIdent = this->parseTypeIdent(); } - token = this->_tokenItr.get(); - if (!token || !token->isType(Token::CLOSE_PARENTHESIS)) - throw syntaxError("dwqdwqdwqdwqexpecting ')'", *this->_tokenItr.prev()); + auto close_p = this->_tokenItr.get(); + if (!close_p || !close_p->isType(Token::CLOSE_PARENTHESIS)) + throw syntaxError("unmatched '('", *open_p); this->_tokenItr.advance(); - token = this->_tokenItr.get(); + auto token = this->_tokenItr.get(); if (!token) throw syntaxError("expecting return type or block", *this->_tokenItr.prev()); @@ -422,6 +418,8 @@ ast::StatementNode::ptr Parser::parseFunction() } auto block = this->parseBlock(); + if (block == nullptr) + throw syntaxError("expecting function body", *identToken); return ast::FunctionNode::create( identToken->getLexeme(), @@ -573,7 +571,7 @@ ast::ExpressionNode::ptr Parser::parseUnary() return nullptr; if (!token->isTypeAnyOf({Token::PLUS, Token::MINUS, Token::NOT, Token::BITWISE_NOT})) - return this->parseFunctionCall(); + return this->parseCall(); this->_tokenItr.advance(); @@ -584,47 +582,49 @@ ast::ExpressionNode::ptr Parser::parseUnary() return ast::UnaryNode::create(token->getType(), expression); } -ast::ExpressionNode::ptr Parser::parseFunctionCall() +ast::ExpressionNode::ptr Parser::parseCall() { - auto token = this->_tokenItr.get(); - if (!token) - return nullptr; + auto expr = this->parsePrimary(); + ast::ExpressionNode::ptr ret; - if (!token->isType(Token::IDENTIFIER)) - return this->parsePrimary(); + auto open_p = this->_tokenItr.get(); + while (open_p && open_p->isType(Token::OPEN_PARENTHESIS)) { + this->_tokenItr.advance(); - std::string ident(token->getLexeme()); + auto params = this->parseParams(); - auto nextToken = this->_tokenItr.next(); - if (!nextToken || !nextToken->isType(Token::OPEN_PARENTHESIS)) - return this->parsePrimary(); + auto close_p = this->_tokenItr.get(); + if (!close_p || !close_p->isType(Token::CLOSE_PARENTHESIS)) + throw syntaxError("unmatched parenthesis", *open_p); + this->_tokenItr.advance(); - this->_tokenItr.advance().advance(); + expr = ast::CallNode::create(expr, params); + open_p = this->_tokenItr.get(); + } + + return expr; +} +std::vector Parser::parseParams() +{ auto expr = this->parseExpression(); - std::vector params; + if (!expr) + return {}; - if (expr != nullptr) { - while (true) { - params.push_back(std::move(expr)); + std::vector params = {expr}; - token = this->_tokenItr.get(); - if (!token || !token->isType(Token::COMMA)) - break; - this->_tokenItr.advance(); + auto comma = this->_tokenItr.get(); + while (comma && comma->isType(Token::COMMA)) { + this->_tokenItr.advance(); + expr = this->parseExpression(); + if (!expr) + throw syntaxError("expecting expression after ','", *comma); - expr = this->parseExpression(); - if (expr == nullptr) - throw syntaxError("expecting expression", *token); - } + params.push_back(expr); + comma = this->_tokenItr.get(); } - token = this->_tokenItr.get(); - if (!token || !token->isType(Token::CLOSE_PARENTHESIS)) - throw syntaxError("expecting ')'", *this->_tokenItr.prev()); - this->_tokenItr.advance(); - - return ast::FunctionCallNode::create(ident, params); + return params; } ast::ExpressionNode::ptr Parser::parsePrimary() diff --git a/src/src.cmake b/src/src.cmake index 9381e97..e5972a8 100644 --- a/src/src.cmake +++ b/src/src.cmake @@ -37,7 +37,7 @@ set(SOURCES ${PROJECT_ROOT}/src/ast/nodes/ForNode.cpp ${PROJECT_ROOT}/src/ast/nodes/IncrementNode.cpp ${PROJECT_ROOT}/src/ast/nodes/FunctionNode.cpp - ${PROJECT_ROOT}/src/ast/nodes/FunctionCallNode.cpp + ${PROJECT_ROOT}/src/ast/nodes/CallNode.cpp ${PROJECT_ROOT}/src/ast/nodes/ReturnNode.cpp ${PROJECT_ROOT}/src/ast/visitors/EvalVisitor.cpp