LCOV - code coverage report
Current view: top level - staxlib/frontend/src/parser - parser.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.8 % 111 83
Test Date: 1980-01-01 00:00:00 Functions: 100.0 % 11 11

            Line data    Source code
       1              : #include "stax/parser/parser.hpp"
       2              : 
       3              : #include "stax/utils/format.hpp"
       4              : #include "stax/utils/result.hpp"
       5              : 
       6              : namespace stax::parser {
       7              : 
       8            2 : Parser::Parser(const std::string& input) : input_(input), lexer_(input_) {
       9              :   // TODO deal with error handling
      10            2 :   NextToken().value();
      11            2 :   NextToken().value();
      12            2 : }
      13              : 
      14            2 : auto Parser::ParseProgram() -> result_t<Program> {
      15            2 :   Program prog{};
      16              : 
      17            7 :   while (curr_.type != token::Type::kEOF) {
      18            5 :     TRY_RESULT(const auto stmt, ParseStatement());
      19            5 :     prog.statements.push_back(stmt);
      20            5 :   }
      21              : 
      22            2 :   return prog;
      23            2 : }
      24              : 
      25            7 : auto Parser::ParseStatement() -> result_t<ast_t> {
      26            7 :   switch (curr_.type) {
      27            5 :     case token::Type::kIdent: return ParseDeclaration(); break;
      28            2 :     case token::Type::kReturn: return ParseReturn(); break;
      29            0 :     default:
      30            0 :       return stax::result::Err(Error::InvalidToken, std::format("{}", curr_));
      31              :   }
      32              : }
      33              : 
      34            2 : auto Parser::ParseReturn() -> result_t<ast_t> {
      35            2 :   TRY_RESULT(NextToken());
      36            2 :   TRY_RESULT(const auto& expression, ParseExpressionStatement());
      37              : 
      38            2 :   return ReturnStatement{.expression = expression};
      39            2 : }
      40              : 
      41            5 : auto Parser::ParseDeclaration() -> result_t<ast_t> {
      42            5 :   TRY_RESULT(Expect(token::Type::kIdent));
      43           15 :   const auto& data_type = DataType{curr_, std::string{curr_.view}};
      44            5 :   TRY_RESULT(NextToken());
      45              : 
      46            5 :   TRY_RESULT(Expect(token::Type::kIdent));
      47           15 :   const auto& ident = Identifier{curr_, std::string{curr_.view}};
      48            5 :   TRY_RESULT(NextToken());
      49              : 
      50            5 :   if (curr_.type == token::Type::kLParen) {
      51            2 :     return ParseFunctionDeclaration(data_type, ident);
      52              :   } else {
      53            3 :     return ParseVariableDeclaration(data_type, ident);
      54              :   }
      55           15 : }
      56              : 
      57            2 : auto Parser::ParseFunctionDeclaration(const DataType& return_type,
      58              :                                       const Identifier& ident)
      59              :     -> result_t<ast_t> {
      60            2 :   if (curr_.type == token::Type::kLParen) {
      61            2 :     TRY_RESULT(NextToken());
      62            2 :   }
      63              : 
      64            2 :   std::vector<VariableDeclaration> args;
      65            2 :   while (curr_.type != token::Type::kRParen) {
      66            0 :     TRY_RESULT(Expect(token::Type::kIdent));
      67            0 :     const auto& data_type = DataType{curr_, std::string{curr_.view}};
      68            0 :     TRY_RESULT(NextToken());
      69              : 
      70            0 :     TRY_RESULT(Expect(token::Type::kIdent));
      71            0 :     const auto& ident = Identifier{curr_, std::string{curr_.view}};
      72            0 :     TRY_RESULT(NextToken());
      73              : 
      74            0 :     if (curr_.type == token::Type::kComma) {
      75            0 :       TRY_RESULT(NextToken());
      76            0 :     }
      77              : 
      78            0 :     args.emplace_back(data_type, ident);
      79            0 :   }
      80              : 
      81            2 :   if (curr_.type == token::Type::kRParen) {
      82            2 :     TRY_RESULT(NextToken());
      83            2 :   }
      84              : 
      85            2 :   TRY_RESULT(Expect(token::Type::kLBrace));
      86            2 :   TRY_RESULT(NextToken());
      87              : 
      88            2 :   std::vector<ast_t> statements;
      89            4 :   while (curr_.type != token::Type::kRBrace) {
      90            2 :     TRY_RESULT(const auto& stmt, ParseStatement());
      91            2 :     statements.emplace_back(stmt);
      92            2 :   }
      93              : 
      94            2 :   TRY_RESULT(Expect(token::Type::kRBrace));
      95            2 :   TRY_RESULT(NextToken());
      96              : 
      97            2 :   auto block = std::make_shared<BlockStatement>();
      98            2 :   if (!statements.empty()) block->statements = statements;
      99            2 :   return FunctionDeclaration(return_type, ident, {}, block);
     100            2 : }
     101              : 
     102            3 : auto Parser::ParseVariableDeclaration(const DataType& var_type,
     103              :                                       const Identifier& ident)
     104              :     -> result_t<ast_t> {
     105            3 :   std::optional<ExpressionStatement> expression;
     106            3 :   if (curr_.type == token::Type::kAssign) {
     107            3 :     TRY_RESULT(NextToken());
     108            3 :     TRY_RESULT(expression, ParseExpressionStatement());
     109            3 :   }
     110              : 
     111            3 :   return VariableDeclaration(var_type, ident, expression);
     112              : }
     113              : 
     114            5 : auto Parser::ParseExpressionStatement() -> result_t<ExpressionStatement> {
     115              :   // TODO rewrite as Pratt parser
     116              :   
     117            5 :   expression_t exp;
     118            5 :   switch (curr_.type) {
     119            5 :     case token::Type::kInt:
     120            5 :       exp = IntegerLiteral{.value = std::stoi(std::string(curr_.view))};
     121            5 :       break;
     122            0 :     default: {
     123            0 :       switch (peek_.type) {
     124            0 :         case token::kPlus:
     125              :           // TODO parse mathematical operations
     126            0 :           break;
     127            0 :         default:
     128            0 :           return stax::result::Err(Error::InvalidToken,
     129            0 :                                    std::format("Not an expression {}", curr_));
     130              :       }
     131              : 
     132            0 :       return stax::result::Err(Error::InvalidToken,
     133            0 :                                std::format("Not an expression {}", curr_));
     134              :     }
     135              :   }
     136              : 
     137            5 :   TRY_RESULT(ExpectPeek(token::Type::kSemicolon));
     138            5 :   TRY_RESULT(NextToken());  // Skip to semicolon
     139            5 :   TRY_RESULT(NextToken());  // Skip passed semicolon
     140              : 
     141            5 :   return ExpressionStatement{.expression = exp};
     142            5 : }
     143              : 
     144           37 : auto Parser::NextToken() -> result_t<void> {
     145           37 :   curr_ = peek_;
     146           37 :   TRY_RESULT(peek_, lexer_.NextToken());
     147           37 :   return result::Ok();
     148           37 : }
     149              : 
     150            5 : auto Parser::ExpectPeek(token::Type tok_type) -> result_t<void> {
     151            5 :   if (peek_.type != tok_type) {
     152            0 :     return result::Err(
     153            0 :         Error::ExpectedToken,
     154            0 :         std::format("Expected {}, but got: {}", tok_type, peek_.type));
     155              :   }
     156              : 
     157            5 :   return result::Ok();
     158              : }
     159              : 
     160           14 : auto Parser::Expect(token::Type tok_type) -> result_t<void> {
     161           14 :   if (curr_.type != tok_type) {
     162            0 :     return result::Err(
     163            0 :         Error::ExpectedToken,
     164            0 :         std::format("Expected {}, but got: {}", tok_type, curr_.type));
     165              :   }
     166              : 
     167           14 :   return result::Ok();
     168              : }
     169              : 
     170              : }  // namespace stax::parser
        

Generated by: LCOV version 2.3.2-1