GSC Interpreter
A Turing-complete interpreter developed for a compiler course
Loading...
Searching...
No Matches
parser.cpp
Go to the documentation of this file.
1#include "gsc/parser.hpp"
2#include "gsc/error.hpp"
3#include <cassert>
4
5Parser::Parser(const std::vector<Token> &tokens) : tokens(tokens) {}
6
7std::vector<std::shared_ptr<Stmt>> Parser::parse() {
8 std::vector<std::shared_ptr<Stmt>> statements;
9 while (!isAtEnd()) {
10 statements.push_back(declaration());
11 }
12
13 return statements;
14}
15
16std::shared_ptr<Stmt> Parser::declaration() {
17 try {
18 if (match(TokenType::VAR))
19 return varDeclaration();
20 return statement();
21 } catch (ParseError &error) {
22 synchronize();
23 return nullptr; // Return null on error
24 }
25}
26
27std::shared_ptr<Stmt> Parser::statement() {
28 if (match(TokenType::PRINT))
29 return printStatement();
30 else if (match(TokenType::IF))
31 return ifStatement();
32 else if (match(TokenType::WHILE))
33 return whileStatement();
34 else if (match(TokenType::FOR))
35 return forStatement();
36 else if (match(TokenType::LEFT_BRACE))
37 return std::make_shared<Block>(block());
38 else
39 return expressionStatement();
40}
41
42std::shared_ptr<Stmt> Parser::printStatement() {
43 std::shared_ptr<Expr> value = expression();
44 consume(TokenType::SEMICOLON, "Expect ';' after value.");
45 return std::make_shared<Print>(value);
46}
47
48std::shared_ptr<Stmt> Parser::ifStatement() {
49 consume(TokenType::LEFT_PAREN, "Expect '(' after 'if'.");
50 std::shared_ptr<Expr> condition = expression();
51 consume(TokenType::RIGHT_PAREN, "Expect ')' after if condition.");
52
53 std::shared_ptr<Stmt> thenBranch = statement();
54 std::shared_ptr<Stmt> elseBranch =
55 match(TokenType::ELSE) ? statement() : nullptr;
56
57 return std::make_shared<If>(condition, thenBranch, elseBranch);
58}
59
60std::shared_ptr<Stmt> Parser::whileStatement() {
61 consume(TokenType::LEFT_PAREN, "Expect '(' after 'while'.");
62 std::shared_ptr<Expr> condition = expression();
63 consume(TokenType::RIGHT_PAREN, "Expect ')' after while condition.");
64
65 std::shared_ptr<Stmt> body = statement();
66 return std::make_shared<While>(condition, body);
67}
68
69std::shared_ptr<Stmt> Parser::forStatement() {
70 consume(TokenType::LEFT_PAREN, "Expect '(' after 'for'.");
71
72 std::shared_ptr<Stmt> initializer =
73 match(TokenType::SEMICOLON)
74 ? nullptr
75 : (match(VAR) ? varDeclaration() : expressionStatement());
76
77 std::shared_ptr<Expr> condition =
78 check(TokenType::SEMICOLON) ? nullptr : expression();
79 consume(SEMICOLON, "Expect ';' after loop condition.");
80
81 std::shared_ptr<Expr> increment =
82 check(TokenType::RIGHT_PAREN) ? nullptr : expression();
83 consume(TokenType::RIGHT_PAREN, "Expect ')' after for parameters.");
84
85 std::shared_ptr<Stmt> body = statement();
86
87 // Desugaring for statement
88 if (increment)
89 body = std::make_shared<Block>(std::vector<std::shared_ptr<Stmt>>{
90 body, std::make_shared<Expression>(increment)});
91
92 if (condition == nullptr)
93 condition = std::make_shared<Literal>(true);
94
95 body = std::make_shared<While>(condition, body);
96
97 if (initializer)
98 body = std::make_shared<Block>(
99 std::vector<std::shared_ptr<Stmt>>{initializer, body});
100
101 return body;
102}
103
104std::shared_ptr<Stmt> Parser::varDeclaration() {
105 Token name = consume(TokenType::IDENTIFIER, "Expect variable name.");
106 std::shared_ptr<Expr> initializer = nullptr;
107
108 if (match(TokenType::EQUAL)) {
109 initializer = expression();
110 }
111
112 consume(TokenType::SEMICOLON, "Expect ';' after variable declaration.");
113 return std::make_shared<Var>(std::move(name), initializer);
114}
115
116std::shared_ptr<Stmt> Parser::expressionStatement() {
117 std::shared_ptr<Expr> expr = expression();
118 consume(TokenType::SEMICOLON, "Expect ';' after expression.");
119 return std::make_shared<Expression>(expr);
120}
121
122std::vector<std::shared_ptr<Stmt>> Parser::block() {
123 std::vector<std::shared_ptr<Stmt>> statements;
124
125 while (!isAtEnd() && !check(TokenType::RIGHT_BRACE)) {
126 statements.push_back(declaration());
127 }
128
129 consume(TokenType::RIGHT_BRACE, "Expect '}' after block.");
130 return statements;
131}
132
133std::shared_ptr<Expr> Parser::assignment() {
134 std::shared_ptr<Expr> expr = orLogical();
135
136 if (match(TokenType::EQUAL)) {
137 Token equals = previous();
138 std::shared_ptr<Expr> value = assignment();
139
140 if (std::shared_ptr<Variable> var =
141 std::dynamic_pointer_cast<Variable>(expr)) {
142 return std::make_shared<Assign>(var->getName(), value);
143 }
144
145 throw error(equals, "Invalid assignment target.");
146 }
147
148 return expr;
149}
150
151std::shared_ptr<Expr> Parser::orLogical() {
152 std::shared_ptr<Expr> expr = andLogical();
153
154 while (match(TokenType::OR)) {
155 Token operatorToken = previous();
156 std::shared_ptr<Expr> right = andLogical();
157 expr = std::make_shared<Logical>(expr, std::move(operatorToken), right);
158 }
159
160 return expr;
161}
162
163std::shared_ptr<Expr> Parser::andLogical() {
164 std::shared_ptr<Expr> expr = equality();
165
166 while (match(TokenType::AND)) {
167 Token operatorToken = previous();
168 std::shared_ptr<Expr> right = equality();
169 expr = std::make_shared<Logical>(expr, std::move(operatorToken), right);
170 }
171
172 return expr;
173}
174
175std::shared_ptr<Expr> Parser::expression() { return assignment(); }
176
177std::shared_ptr<Expr> Parser::equality() {
178 std::shared_ptr<Expr> expr = comparison();
179
180 while (match(TokenType::BANG_EQUAL, TokenType::EQUAL_EQUAL)) {
181 Token operatorToken = previous();
182 std::shared_ptr<Expr> right = comparison();
183 expr = std::make_shared<Binary>(expr, std::move(operatorToken), right);
184 }
185
186 return expr;
187}
188
189std::shared_ptr<Expr> Parser::comparison() {
190 std::shared_ptr<Expr> expr = term();
191
192 while (match(TokenType::GREATER, TokenType::GREATER_EQUAL, TokenType::LESS,
193 TokenType::LESS_EQUAL)) {
194 Token operatorToken = previous();
195 std::shared_ptr<Expr> right = term();
196 expr = std::make_shared<Binary>(expr, std::move(operatorToken), right);
197 }
198
199 return expr;
200}
201
202std::shared_ptr<Expr> Parser::term() {
203 std::shared_ptr<Expr> expr = factor();
204
205 while (match(TokenType::MINUS, TokenType::PLUS)) {
206 Token operatorToken = previous();
207 std::shared_ptr<Expr> right = factor();
208 expr = std::make_shared<Binary>(expr, std::move(operatorToken), right);
209 }
210
211 return expr;
212}
213
214std::shared_ptr<Expr> Parser::factor() {
215 std::shared_ptr<Expr> expr = unary();
216
217 while (match(TokenType::SLASH, TokenType::STAR)) {
218 Token operatorToken = previous();
219 std::shared_ptr<Expr> right = unary();
220 expr = std::make_shared<Binary>(expr, std::move(operatorToken), right);
221 }
222
223 return expr;
224}
225
226std::shared_ptr<Expr> Parser::unary() {
227 if (match(TokenType::BANG, TokenType::MINUS)) {
228 Token operatorToken = previous();
229 std::shared_ptr<Expr> right = unary();
230 return std::make_shared<Unary>(std::move(operatorToken), right);
231 }
232
233 return primary();
234}
235
236std::shared_ptr<Expr> Parser::primary() {
237 if (match(TokenType::NIL))
238 return std::make_shared<Literal>(nullptr);
239 else if (match(TokenType::TRUE))
240 return std::make_shared<Literal>(true);
241 else if (match(TokenType::FALSE))
242 return std::make_shared<Literal>(false);
243 else if (match(TokenType::NUMBER, TokenType::STRING)) {
244 return std::make_shared<Literal>(previous().getLiteral());
245 } else if (match(TokenType::IDENTIFIER)) {
246 return std::make_shared<Variable>(previous());
247 } else if (match(TokenType::LEFT_PAREN)) {
248 std::shared_ptr<Expr> expr = expression();
249 consume(TokenType::RIGHT_PAREN, "Expect ')' after expression.");
250 return std::make_shared<Grouping>(std::move(expr));
251 } else {
252 std::string_view message = "Expect expression.";
253 throw error(peek(), message);
254 }
255}
256
257template <class... T> bool Parser::match(T... types) {
258 assert((std::is_same_v<T, TokenType> && ...));
259
260 for (TokenType type : {types...}) {
261 if (check(type)) {
262 advance();
263 return true;
264 }
265 }
266 return false;
267}
268
269bool Parser::check(TokenType type) const {
270 if (isAtEnd())
271 return false;
272 return peek().getType() == type;
273}
274
275bool Parser::isAtEnd() const {
276 return peek().getType() == TokenType::END_OF_FILE;
277}
278
279Token Parser::consume(TokenType type, std::string_view message) {
280 if (check(type))
281 return advance();
282
283 throw error(peek(), message);
284}
285
286Token Parser::advance() {
287 if (!isAtEnd())
288 current++;
289 return previous();
290}
291
292Token Parser::peek() const { return tokens[current]; }
293
294Token Parser::previous() const {
295 assert(current > 0);
296 return tokens[current - 1];
297}
298
299Parser::ParseError Parser::error(const Token &token, std::string_view message) {
300 ::error(token, std::string(message));
301 return ParseError("");
302}
303
304void Parser::synchronize() {
305 advance();
306
307 while (!isAtEnd()) {
308 if (previous().getType() == TokenType::SEMICOLON)
309 return;
310
311 switch (peek().getType()) {
312 case TokenType::VAR:
313 case TokenType::FOR:
314 case TokenType::IF:
315 case TokenType::WHILE:
316 case TokenType::PRINT:
317 return;
318 default:
319 break;
320 }
321
322 advance();
323 }
324}