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
|