Phasor 3.1.1
Stack VM based Programming Language
Loading...
Searching...
No Matches
Parser.cpp
Go to the documentation of this file.
1#include "Parser.hpp"
2#include "../Lexer/Lexer.hpp"
3#include <filesystem>
4#include <fstream>
5#include <iostream>
6
7namespace Phasor
8{
9
10static std::vector<Token> tokenizeFile(const std::filesystem::path &path)
11{
12 std::ifstream file(path);
13 if (!file.is_open())
14 {
15 throw std::runtime_error("Could not open file " + path.string());
16 }
17 std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
18 file.close();
19
20 Lexer lexer(source);
21 return lexer.tokenize();
22}
23
24static std::vector<std::unique_ptr<AST::Statement>>
25resolveIncludes(std::vector<std::unique_ptr<AST::Statement>> &stmts, const std::filesystem::path &baseDir);
26
27static std::vector<std::unique_ptr<AST::Statement>>
28resolveIncludesInternal(std::vector<std::unique_ptr<AST::Statement>> &stmts, const std::filesystem::path &baseDir)
29{
30 std::vector<std::unique_ptr<AST::Statement>> result;
31
32 for (size_t i = 0; i < stmts.size(); ++i)
33 {
34 if (auto includeStmt = dynamic_cast<AST::IncludeStmt *>(stmts[i].get()))
35 {
36 auto includePath = (baseDir / includeStmt->modulePath).lexically_normal();
37 auto tokens = tokenizeFile(includePath);
38 Parser parser(tokens, includePath);
39 auto program = parser.parse();
40
41 auto resolved = resolveIncludes(program->statements, includePath.parent_path());
42 for (auto &stmt : resolved)
43 {
44 result.push_back(std::move(stmt));
45 }
46 }
47 else
48 {
49 result.push_back(std::move(stmts[i]));
50 }
51 }
52
53 return result;
54}
55
56static std::vector<std::unique_ptr<AST::Statement>>
57resolveIncludes(std::vector<std::unique_ptr<AST::Statement>> &stmts, const std::filesystem::path &baseDir)
58{
59 return resolveIncludesInternal(stmts, baseDir);
60}
61
62
63using namespace AST;
64
65Parser::Parser(const std::vector<Token> &tokens) : tokens(tokens)
66{
67}
68
69Parser::Parser(const std::vector<Token> &tokens, const std::filesystem::path &sourcePath) : tokens(tokens), sourcePath(sourcePath)
70{
71}
72
73std::unique_ptr<Program> Parser::parse()
74{
75 auto program = std::make_unique<Program>();
76 while (!isAtEnd())
77 {
78 program->statements.push_back(declaration());
79 }
80
81 program->statements = Phasor::resolveIncludes(program->statements, sourcePath.parent_path());
82
83 return program;
84}
85
86std::unique_ptr<Statement> Parser::declaration()
87{
88 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "fn")
89 {
90 Token start = peek();
91 advance();
92 auto node = functionDeclaration();
93 node->line = start.line;
94 node->column = start.column;
95 return node;
96 }
97 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "var")
98 {
99 Token start = peek();
100 advance();
101 auto node = varDeclaration();
102 node->line = start.line;
103 node->column = start.column;
104 return node;
105 }
106 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "import")
107 {
108 Token start = peek();
109 advance();
110 auto node = importStatement();
111 node->line = start.line;
112 node->column = start.column;
113 return node;
114 }
115 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "export")
116 {
117 Token start = peek();
118 advance();
119 auto node = exportStatement();
120 node->line = start.line;
121 node->column = start.column;
122 return node;
123 }
124 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "struct")
125 {
126 return structDecl();
127 }
128 return statement();
129}
130
131std::unique_ptr<Statement> Parser::functionDeclaration()
132{
133 Token name = consume(Phasor::TokenType::Identifier, "Expect function name.");
134 consume(Phasor::TokenType::Symbol, "(", "Expect '(' after function name.");
135 std::vector<FunctionDecl::Param> params;
136 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != ")")
137 {
138 do
139 {
140 Token paramName = consume(Phasor::TokenType::Identifier, "Expect parameter name.");
141 consume(Phasor::TokenType::Symbol, ":", "Expect ':' after parameter name.");
142 auto type = parseType();
143 params.push_back({paramName.lexeme, std::move(type)});
144 } while (match(Phasor::TokenType::Symbol, ","));
145 }
146 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after parameters.");
147
148 std::unique_ptr<TypeNode> returnType = nullptr;
150 {
151 returnType = parseType();
152 }
153
154 consume(Phasor::TokenType::Symbol, "{", "Expect '{' before function body.");
155
156 // Track function context for better error messages
157 std::string previousFunction = currentFunction;
158 currentFunction = name.lexeme;
159
160 auto body = block();
161
162 // Restore previous function context
163 currentFunction = previousFunction;
164
165 auto node = std::make_unique<FunctionDecl>(name.lexeme, std::move(params), std::move(returnType), std::move(body));
166 node->line = name.line;
167 node->column = name.column;
168 return node;
169}
170
171std::unique_ptr<TypeNode> Parser::parseType()
172{
173 Token start = peek();
174 bool isPointer = false;
176 {
177 isPointer = true;
178 }
179 Token typeName = consume(Phasor::TokenType::Identifier, "Expect type name.");
180
181 std::vector<int> dims;
182 while (match(Phasor::TokenType::Symbol, "["))
183 {
184 Token size = consume(Phasor::TokenType::Number, "Expect array size in type declaration.");
185 dims.push_back(std::stoi(size.lexeme));
186 consume(Phasor::TokenType::Symbol, "]", "Expect ']' after array size.");
187 }
188 auto node = std::make_unique<TypeNode>(typeName.lexeme, isPointer, dims);
189 node->line = start.line;
190 node->column = start.column;
191 return node;
192}
193
194std::unique_ptr<Statement> Parser::varDeclaration()
195{
196 Token name = consume(Phasor::TokenType::Identifier, "Expect variable name.");
197 std::unique_ptr<Expression> initializer = nullptr;
199 {
200 initializer = expression();
201 }
202 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after variable declaration.");
203 auto node = std::make_unique<VarDecl>(name.lexeme, std::move(initializer));
204 node->line = name.line;
205 node->column = name.column;
206 return node;
207}
208
209std::unique_ptr<Statement> Parser::statement()
210{
211 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "print")
212 {
213 Token start = peek();
214 advance();
215 auto node = printStatement();
216 node->line = start.line;
217 node->column = start.column;
218 return node;
219 }
220 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "if")
221 {
222 Token start = peek();
223 advance();
224 auto node = ifStatement();
225 node->line = start.line;
226 node->column = start.column;
227 return node;
228 }
229 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "while")
230 {
231 Token start = peek();
232 advance();
233 auto node = whileStatement();
234 node->line = start.line;
235 node->column = start.column;
236 return node;
237 }
238 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "for")
239 {
240 Token start = peek();
241 advance();
242 auto node = forStatement();
243 node->line = start.line;
244 node->column = start.column;
245 return node;
246 }
247 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "switch")
248 {
249 Token start = peek();
250 advance();
251 auto node = switchStatement();
252 node->line = start.line;
253 node->column = start.column;
254 return node;
255 }
256 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "return")
257 {
258 Token start = peek();
259 advance();
260 auto node = returnStatement();
261 node->line = start.line;
262 node->column = start.column;
263 return node;
264 }
265 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "break")
266 {
267 Token start = peek();
268 advance();
269 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after 'break'.");
270 auto node = std::make_unique<BreakStmt>();
271 node->line = start.line;
272 node->column = start.column;
273 return node;
274 }
275 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "continue")
276 {
277 Token start = peek();
278 advance();
279 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after 'continue'.");
280 auto node = std::make_unique<ContinueStmt>();
281 node->line = start.line;
282 node->column = start.column;
283 return node;
284 }
285 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "include")
286 {
287 Token start = peek();
288 advance();
289
290 Token pathToken = consume(Phasor::TokenType::String, "Expect file path after 'include'.");
291
292 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after include.");
293
294 auto node = std::make_unique<IncludeStmt>(pathToken.lexeme);
295 node->line = start.line;
296 node->column = start.column;
297 return node;
298 }
299 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "unsafe")
300 {
301 Token start = peek();
302 advance();
303 auto node = unsafeStatement();
304 node->line = start.line;
305 node->column = start.column;
306 return node;
307 }
308 if (check(Phasor::TokenType::Symbol) && peek().lexeme == "{")
309 {
310 Token start = peek();
311 advance();
312 auto blk = block();
313 blk->line = start.line;
314 blk->column = start.column;
315 return blk;
316 }
317 return expressionStatement();
318}
319
320std::unique_ptr<Statement> Parser::ifStatement()
321{
322 consume(Phasor::TokenType::Symbol, "(", "Expect '(' after 'if'.");
323 auto condition = expression();
324 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after if condition.");
325 auto thenBranch = statement();
326 std::unique_ptr<Statement> elseBranch = nullptr;
328 {
329 elseBranch = statement();
330 }
331 return std::make_unique<IfStmt>(std::move(condition), std::move(thenBranch), std::move(elseBranch));
332 // Note: line/column is set by the caller (statement()) from the 'if' keyword token.
333}
334
335std::unique_ptr<Statement> Parser::whileStatement()
336{
337 consume(Phasor::TokenType::Symbol, "(", "Expect '(' after 'while'.");
338 auto condition = expression();
339 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after while condition.");
340 auto body = statement();
341 return std::make_unique<WhileStmt>(std::move(condition), std::move(body));
342}
343
344std::unique_ptr<Statement> Parser::forStatement()
345{
346 consume(Phasor::TokenType::Symbol, "(", "Expect '(' after 'for'.");
347
348 std::unique_ptr<Statement> initializer = nullptr;
349 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != ";")
350 {
351 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "var")
352 {
353 advance();
354 initializer = varDeclaration();
355 }
356 else
357 {
358 initializer = expressionStatement();
359 }
360 }
361 else
362 {
363 consume(Phasor::TokenType::Symbol, ";", "Expect ';'.");
364 }
365
366 std::unique_ptr<Expression> condition = nullptr;
367 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != ";")
368 {
369 condition = expression();
370 }
371 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after loop condition.");
372
373 std::unique_ptr<Expression> increment = nullptr;
374 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != ")")
375 {
376 increment = expression();
377 }
378 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after for clauses.");
379
380 auto body = statement();
381 return std::make_unique<ForStmt>(std::move(initializer), std::move(condition), std::move(increment),
382 std::move(body));
383}
384
385std::unique_ptr<Statement> Parser::switchStatement()
386{
387 consume(Phasor::TokenType::Symbol, "(", "Expect '(' after 'switch'.");
388 auto expr = expression();
389 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after switch expression.");
390 consume(Phasor::TokenType::Symbol, "{", "Expect '{' after switch.");
391
392 std::vector<CaseClause> cases;
393 std::vector<std::unique_ptr<Statement>> defaultStmts;
394
395 while (!check(Phasor::TokenType::Symbol) || peek().lexeme != "}")
396 {
397 if (isAtEnd())
398 {
399 lastError = {"Unterminated switch statement.", peek().line, peek().column};
400 throw std::runtime_error("Unterminated switch statement.");
401 }
402
403 if (check(Phasor::TokenType::Keyword) && peek().lexeme == "case")
404 {
405 advance();
406 auto caseValue = expression();
407 consume(Phasor::TokenType::Symbol, ":", "Expect ':' after case value.");
408
409 std::vector<std::unique_ptr<Statement>> stmts;
410 while ((!check(Phasor::TokenType::Keyword) || (peek().lexeme != "case" && peek().lexeme != "default")) &&
411 (!check(Phasor::TokenType::Symbol) || peek().lexeme != "}"))
412 {
413 if (isAtEnd())
414 {
415 lastError = {"Unterminated case clause.", peek().line, peek().column};
416 throw std::runtime_error("Unterminated case clause.");
417 }
418 stmts.push_back(declaration());
419 }
420 cases.emplace_back(std::move(caseValue), std::move(stmts));
421 }
422 else if (check(Phasor::TokenType::Keyword) && peek().lexeme == "default")
423 {
424 advance();
425 consume(Phasor::TokenType::Symbol, ":", "Expect ':' after default.");
426
427 while ((!check(Phasor::TokenType::Keyword) || (peek().lexeme != "case" && peek().lexeme != "default")) &&
428 (!check(Phasor::TokenType::Symbol) || peek().lexeme != "}"))
429 {
430 if (isAtEnd())
431 {
432 lastError = {"Unterminated default clause.", peek().line, peek().column};
433 throw std::runtime_error("Unterminated default clause.");
434 }
435 defaultStmts.push_back(declaration());
436 }
437 }
438 else
439 {
440 lastError = {"Expected 'case' or 'default' in switch statement.", peek().line, peek().column};
441 throw std::runtime_error("Expected 'case' or 'default' in switch statement.");
442 }
443 }
444
445 consume(Phasor::TokenType::Symbol, "}", "Expect '}' after switch body.");
446 return std::make_unique<SwitchStmt>(std::move(expr), std::move(cases), std::move(defaultStmts));
447}
448
449std::unique_ptr<Statement> Parser::returnStatement()
450{
451 std::unique_ptr<Expression> value = nullptr;
452 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != ";")
453 {
454 value = expression();
455 }
456 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after return value.");
457 return std::make_unique<ReturnStmt>(std::move(value));
458 // Note: line/column is set by the caller (statement()) from the 'return' keyword token.
459}
460
461std::unique_ptr<Statement> Parser::unsafeStatement()
462{
463 consume(Phasor::TokenType::Symbol, "{", "Expect '{' after 'unsafe'.");
464 return std::make_unique<UnsafeBlockStmt>(block());
465}
466
467std::unique_ptr<BlockStmt> Parser::block()
468{
469 std::vector<std::unique_ptr<Statement>> statements;
470 while (!check(Phasor::TokenType::Symbol) || peek().lexeme != "}")
471 {
472 if (isAtEnd())
473 {
474 lastError = {"Unterminated block.", peek().line, peek().column};
475 throw std::runtime_error("Unterminated block.");
476 }
477 statements.push_back(declaration());
478 }
479 consume(Phasor::TokenType::Symbol, "}", "Expect '}' after block.");
480 return std::make_unique<BlockStmt>(std::move(statements));
481}
482
483std::unique_ptr<Statement> Parser::printStatement()
484{
485 auto expr = expression();
486 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after print statement.");
487 return std::make_unique<PrintStmt>(std::move(expr));
488 // Note: line/column set by caller (statement()) from the 'print' keyword token.
489}
490
491std::unique_ptr<Statement> Parser::importStatement()
492{
493 Token path = consume(Phasor::TokenType::String, "Expect string after 'import'.");
494 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after import statement.");
495 auto node = std::make_unique<ImportStmt>(path.lexeme);
496 node->line = path.line;
497 node->column = path.column;
498 return node;
499}
500
501std::unique_ptr<Statement> Parser::exportStatement()
502{
503 auto node = std::make_unique<ExportStmt>(declaration());
504 // line/column set by caller (declaration()) from the 'export' keyword token.
505 return node;
506}
507
508std::unique_ptr<Statement> Parser::expressionStatement()
509{
510 Token start = peek();
511 auto expr = expression();
512 consume(Phasor::TokenType::Symbol, ";", "Expect ';' after expression.");
513 auto node = std::make_unique<ExpressionStmt>(std::move(expr));
514 node->line = start.line;
515 node->column = start.column;
516 return node;
517}
518
519std::unique_ptr<Expression> Parser::expression()
520{
521 return assignment();
522}
523
524std::unique_ptr<Expression> Parser::assignment()
525{
526 auto expr = logicalOr();
527
529 {
530 Token op = previous();
531 auto value = assignment(); // Right-associative
532 auto node = std::make_unique<AssignmentExpr>(std::move(expr), std::move(value));
533 node->line = op.line;
534 node->column = op.column;
535 return node;
536 }
537
538 return expr;
539}
540
541std::unique_ptr<Expression> Parser::logicalOr()
542{
543 auto expr = logicalAnd();
544
545 while (check(Phasor::TokenType::Symbol) && peek().lexeme == "||")
546 {
547 Token op = advance();
548 auto right = logicalAnd();
549 auto node = std::make_unique<BinaryExpr>(std::move(expr), BinaryOp::Or, std::move(right));
550 node->line = op.line;
551 node->column = op.column;
552 expr = std::move(node);
553 }
554
555 return expr;
556}
557
558std::unique_ptr<Expression> Parser::logicalAnd()
559{
560 auto expr = equality();
561
562 while (check(Phasor::TokenType::Symbol) && peek().lexeme == "&&")
563 {
564 Token op = advance();
565 auto right = equality();
566 auto node = std::make_unique<BinaryExpr>(std::move(expr), BinaryOp::And, std::move(right));
567 node->line = op.line;
568 node->column = op.column;
569 expr = std::move(node);
570 }
571
572 return expr;
573}
574
575std::unique_ptr<Expression> Parser::equality()
576{
577 auto expr = comparison();
578
579 while (check(Phasor::TokenType::Symbol) && (peek().lexeme == "==" || peek().lexeme == "!="))
580 {
581 Token op = advance();
582 auto right = comparison();
583 BinaryOp binOp = (op.lexeme == "==") ? BinaryOp::Equal : BinaryOp::NotEqual;
584 auto node = std::make_unique<BinaryExpr>(std::move(expr), binOp, std::move(right));
585 node->line = op.line;
586 node->column = op.column;
587 expr = std::move(node);
588 }
589
590 return expr;
591}
592
593std::unique_ptr<Expression> Parser::comparison()
594{
595 auto expr = term();
596
598 (peek().lexeme == "<" || peek().lexeme == ">" || peek().lexeme == "<=" || peek().lexeme == ">="))
599 {
600 Token op = advance();
601 auto right = term();
602 BinaryOp binOp;
603 if (op.lexeme == "<")
604 binOp = BinaryOp::LessThan;
605 else if (op.lexeme == ">")
606 binOp = BinaryOp::GreaterThan;
607 else if (op.lexeme == "<=")
608 binOp = BinaryOp::LessEqual;
609 else
610 binOp = BinaryOp::GreaterEqual;
611
612 auto node = std::make_unique<BinaryExpr>(std::move(expr), binOp, std::move(right));
613 node->line = op.line;
614 node->column = op.column;
615 expr = std::move(node);
616 }
617
618 return expr;
619}
620
621std::unique_ptr<Expression> Parser::term()
622{
623 auto expr = factor();
624
625 while (check(Phasor::TokenType::Symbol) && (peek().lexeme == "+" || peek().lexeme == "-"))
626 {
627 Token op = advance();
628 auto right = factor();
629 BinaryOp binOp = (op.lexeme == "+") ? BinaryOp::Add : BinaryOp::Subtract;
630 auto node = std::make_unique<BinaryExpr>(std::move(expr), binOp, std::move(right));
631 node->line = op.line;
632 node->column = op.column;
633 expr = std::move(node);
634 }
635
636 return expr;
637}
638
639std::unique_ptr<Expression> Parser::factor()
640{
641 auto expr = unary();
642
643 while (check(Phasor::TokenType::Symbol) && (peek().lexeme == "*" || peek().lexeme == "/" || peek().lexeme == "%"))
644 {
645 Token op = advance();
646 auto right = unary();
647 BinaryOp binOp;
648 if (op.lexeme == "*")
649 binOp = BinaryOp::Multiply;
650 else if (op.lexeme == "/")
651 binOp = BinaryOp::Divide;
652 else
653 binOp = BinaryOp::Modulo;
654
655 auto node = std::make_unique<BinaryExpr>(std::move(expr), binOp, std::move(right));
656 node->line = op.line;
657 node->column = op.column;
658 expr = std::move(node);
659 }
660
661 return expr;
662}
663
664std::unique_ptr<Expression> Parser::unary()
665{
666 if (check(Phasor::TokenType::Symbol) && (peek().lexeme == "!" || peek().lexeme == "-"))
667 {
668 Token op = advance();
669 auto right = unary();
670 UnaryOp uOp = (op.lexeme == "!") ? UnaryOp::Not : UnaryOp::Negate;
671 auto node = std::make_unique<UnaryExpr>(uOp, std::move(right));
672 node->line = op.line;
673 node->column = op.column;
674 return node;
675 }
676 if (check(Phasor::TokenType::Symbol) && peek().lexeme == "&")
677 {
678 Token op = advance();
679 auto right = unary();
680 auto node = std::make_unique<UnaryExpr>(UnaryOp::AddressOf, std::move(right));
681 node->line = op.line;
682 node->column = op.column;
683 return node;
684 }
685 if (check(Phasor::TokenType::Symbol) && peek().lexeme == "*")
686 {
687 Token op = advance();
688 auto right = unary();
689 auto node = std::make_unique<UnaryExpr>(UnaryOp::Dereference, std::move(right));
690 node->line = op.line;
691 node->column = op.column;
692 return node;
693 }
694 return call();
695}
696
697std::unique_ptr<Expression> Parser::call()
698{
699 auto expr = primary();
700
701 while (true)
702 {
704 {
705 Token op = previous();
706 expr = finishCall(std::move(expr));
707 expr->line = op.line;
708 expr->column = op.column;
709 }
710 else if (match(Phasor::TokenType::Symbol, "."))
711 {
712 Token op = previous();
713 expr = fieldAccess(std::move(expr));
714 expr->line = op.line;
715 expr->column = op.column;
716 }
717 else if (match(Phasor::TokenType::Symbol, "++"))
718 {
719 Token op = previous();
720 auto node = std::make_unique<PostfixExpr>(PostfixOp::Increment, std::move(expr));
721 node->line = op.line;
722 node->column = op.column;
723 expr = std::move(node);
724 }
725 else if (match(Phasor::TokenType::Symbol, "--"))
726 {
727 Token op = previous();
728 auto node = std::make_unique<PostfixExpr>(PostfixOp::Decrement, std::move(expr));
729 node->line = op.line;
730 node->column = op.column;
731 expr = std::move(node);
732 }
733 else if (match(Phasor::TokenType::Symbol, "["))
734 {
735 Token op = previous();
736 auto index = expression();
737 consume(Phasor::TokenType::Symbol, "]", "Expect ']' after index.");
738 auto node = std::make_unique<ArrayAccessExpr>(std::move(expr), std::move(index));
739 node->line = op.line;
740 node->column = op.column;
741 expr = std::move(node);
742 }
743 else
744 {
745 break;
746 }
747 }
748
749 return expr;
750}
751
752std::unique_ptr<Expression> Parser::finishCall(std::unique_ptr<Expression> callee)
753{
754 std::vector<std::unique_ptr<Expression>> arguments;
755 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != ")")
756 {
757 do
758 {
759 arguments.push_back(expression());
760 } while (match(Phasor::TokenType::Symbol, ","));
761 }
762 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after arguments.");
763
764 // For now, we only support direct function calls by name, or calls on field access which are
765 // rewritten to pass the object as the first argument.
766 if (auto ident = dynamic_cast<IdentifierExpr *>(callee.get()))
767 {
768 auto node = std::make_unique<CallExpr>(ident->name, std::move(arguments));
769 node->line = ident->line;
770 node->column = ident->column;
771 return node;
772 }
773 else if (auto field = dynamic_cast<FieldAccessExpr *>(callee.get()))
774 {
775 // Transform obj.method(args) -> method(obj, args)
776 std::string methodName = field->fieldName;
777 size_t fline = field->line, fcol = field->column;
778 arguments.insert(arguments.begin(), std::move(field->object));
779 auto node = std::make_unique<CallExpr>(methodName, std::move(arguments));
780 node->line = fline;
781 node->column = fcol;
782 return node;
783 }
784 lastError = {"Can only call named functions.", peek().line, peek().column};
785 throw std::runtime_error("Can only call named functions.");
786}
787
788std::unique_ptr<Expression> Parser::primary()
789{
791 {
792 Token t = previous();
793 auto node = std::make_unique<NumberExpr>(t.lexeme);
794 node->line = t.line;
795 node->column = t.column;
796 return node;
797 }
799 {
800 Token t = previous();
801 auto node = std::make_unique<StringExpr>(t.lexeme);
802 node->line = t.line;
803 node->column = t.column;
804 return node;
805 }
807 {
808 // Look ahead for struct instance syntax: Name{ ... }
809 Token identTok = peek();
810 if (!isAtEnd() && peekNext().type == Phasor::TokenType::Symbol && peekNext().lexeme == "{")
811 {
812 return structInstance();
813 }
814 advance();
815 auto node = std::make_unique<IdentifierExpr>(identTok.lexeme);
816 node->line = identTok.line;
817 node->column = identTok.column;
818 return node;
819 }
821 {
822 Token start = previous();
823 std::vector<std::unique_ptr<Expression>> elements;
824 if (!check(Phasor::TokenType::Symbol) || peek().lexeme != "]")
825 {
826 do
827 {
828 elements.push_back(expression());
829 } while (match(Phasor::TokenType::Symbol, ","));
830 }
831 consume(Phasor::TokenType::Symbol, "]", "Expect ']' after array elements.");
832 auto node = std::make_unique<ArrayLiteralExpr>(std::move(elements));
833 node->line = start.line;
834 node->column = start.column;
835 return node;
836 }
838 {
839 Token t = previous();
840 auto node = std::make_unique<BooleanExpr>(true);
841 node->line = t.line;
842 node->column = t.column;
843 return node;
844 }
845 if (match(Phasor::TokenType::Keyword, "false"))
846 {
847 Token t = previous();
848 auto node = std::make_unique<BooleanExpr>(false);
849 node->line = t.line;
850 node->column = t.column;
851 return node;
852 }
854 {
855 Token t = previous();
856 auto node = std::make_unique<NullExpr>();
857 node->line = t.line;
858 node->column = t.column;
859 return node;
860 }
862 {
863 auto expr = expression();
864 consume(Phasor::TokenType::Symbol, ")", "Expect ')' after expression.");
865 return expr;
866 }
867 std::cerr << "Error: Expect expression at '" << peek().lexeme << "'";
868 std::cerr << " (line " << peek().line << ", column " << peek().column << ")\n";
869 lastError = {"Expect expression", peek().line, peek().column};
870 throw std::runtime_error("Expect expression.");
871}
872
873// Struct declaration
874// struct Point { x: int, y: int }
875std::unique_ptr<StructDecl> Parser::structDecl()
876{
877 // 'struct' keyword
878 Token start = peek();
879 consume(Phasor::TokenType::Keyword, "struct", "Expected 'struct'");
880 Token nameTok = consume(Phasor::TokenType::Identifier, "Expected struct name");
881 consume(Phasor::TokenType::Symbol, "{", "Expected '{' in struct declaration");
882
883 std::vector<StructField> fields;
884 while (!check(Phasor::TokenType::Symbol) || peek().lexeme != "}")
885 {
886 if (isAtEnd())
887 {
888 lastError = {"Unterminated struct declaration", peek().line, peek().column};
889 throw std::runtime_error("Unterminated struct declaration.");
890 }
891
892 Token fieldNameTok = consume(Phasor::TokenType::Identifier, "Expected field name");
893 consume(Phasor::TokenType::Symbol, ":", "Expected ':' after field name");
894 auto type = parseType();
895 fields.emplace_back(fieldNameTok.lexeme, std::move(type));
896
898 {
899 break;
900 }
901 }
902
903 consume(Phasor::TokenType::Symbol, "}", "Expected '}' after struct fields");
904 auto node = std::make_unique<StructDecl>(nameTok.lexeme, std::move(fields));
905 node->line = start.line;
906 node->column = start.column;
907 return node;
908}
909
910// Struct instantiation
911// Point{ x: 10, y: 20 }
912std::unique_ptr<StructInstanceExpr> Parser::structInstance()
913{
914 Token nameTok = consume(Phasor::TokenType::Identifier, "Expected struct name");
915 consume(Phasor::TokenType::Symbol, "{", "Expected '{' in struct instance");
916
917 std::vector<std::pair<std::string, std::unique_ptr<Expression>>> fields;
918 while (!check(Phasor::TokenType::Symbol) || peek().lexeme != "}")
919 {
920 if (isAtEnd())
921 {
922 lastError = {"Unterminated struct instance.", peek().line, peek().column};
923 throw std::runtime_error("Unterminated struct instance.");
924 }
925 Token fieldNameTok = consume(Phasor::TokenType::Identifier, "Expected field name");
926 consume(Phasor::TokenType::Symbol, ":", "Expected ':' after field name");
927 auto value = expression();
928 fields.emplace_back(fieldNameTok.lexeme, std::move(value));
929
931 {
932 break;
933 }
934 }
935
936 consume(Phasor::TokenType::Symbol, "}", "Expected '}' after struct fields");
937 auto node = std::make_unique<StructInstanceExpr>(nameTok.lexeme, std::move(fields));
938 node->line = nameTok.line;
939 node->column = nameTok.column;
940 return node;
941}
942
943// Field access
944// point.x
945std::unique_ptr<Expression> Parser::fieldAccess(std::unique_ptr<Expression> object)
946{
947 Token nameTok = consume(Phasor::TokenType::Identifier, "Expected field name after '.'");
948 auto node = std::make_unique<FieldAccessExpr>(std::move(object), nameTok.lexeme);
949 node->line = nameTok.line;
950 node->column = nameTok.column;
951 return node;
952}
953
955{
956 return tokens[current];
957}
958
960{
961 if (current + 1 >= static_cast<int>(tokens.size()))
962 {
963 return tokens[current];
964 }
965 return tokens[current + 1];
966}
967
969{
970 return tokens[current - 1];
971}
972
974{
975 if (!isAtEnd())
976 current++;
977 return previous();
978}
979
981{
983}
984
986{
987 if (isAtEnd())
988 return false;
989 return peek().type == type;
990}
991
993{
994 if (check(type))
995 {
996 advance();
997 return true;
998 }
999 return false;
1000}
1001
1002Token Parser::consume(TokenType type, std::string message)
1003{
1004 if (check(type))
1005 return advance();
1006
1007 std::cerr << "Error: " << message << " at '" << peek().lexeme << "'";
1008 std::cerr << " (line " << peek().line << ", column " << peek().column << ")";
1009 if (!currentFunction.empty())
1010 std::cerr << " [in function '" << currentFunction << "']";
1011 std::cerr << "\n";
1012 lastError = {message, peek().line, peek().column};
1013 throw std::runtime_error(message);
1014}
1015
1016bool Parser::match(TokenType type, std::string lexeme)
1017{
1018 if (check(type) && peek().lexeme == lexeme)
1019 {
1020 advance();
1021 return true;
1022 }
1023 return false;
1024}
1025
1026Token Parser::consume(TokenType type, std::string lexeme, std::string message)
1027{
1028 if (check(type) && peek().lexeme == lexeme)
1029 {
1030 return advance();
1031 }
1032
1033 std::cerr << "Error: " << message << " at '" << peek().lexeme << "'";
1034 std::cerr << " (line " << peek().line << ", column " << peek().column << ")";
1035 if (!currentFunction.empty())
1036 std::cerr << " [in function '" << currentFunction << "']";
1037 std::cerr << "\n";
1038
1039 lastError = {message, peek().line, peek().column};
1040 throw std::runtime_error(message);
1041}
1042
1043Token Parser::expect(TokenType type, const std::string &message)
1044{
1045 if (check(type))
1046 {
1047 return advance();
1048 }
1049 lastError = {message, peek().line, peek().column};
1050 throw std::runtime_error(message);
1051}
1052} // namespace Phasor
Lexer.
Definition Lexer.hpp:13
std::vector< Token > tokenize()
Definition Lexer.cpp:26
Parser.
Definition Parser.hpp:13
Parser(const std::vector< Token > &tokens)
Definition Parser.cpp:65
std::unique_ptr< AST::Statement > returnStatement()
Definition Parser.cpp:449
std::unique_ptr< AST::Expression > equality()
Definition Parser.cpp:575
std::unique_ptr< AST::Expression > logicalAnd()
Definition Parser.cpp:558
bool isAtEnd()
Definition Parser.cpp:980
std::filesystem::path sourcePath
Definition Parser.hpp:40
Token previous()
Definition Parser.cpp:968
std::unique_ptr< AST::Expression > unary()
Definition Parser.cpp:664
std::unique_ptr< AST::Expression > factor()
Definition Parser.cpp:639
std::unique_ptr< AST::Statement > ifStatement()
Definition Parser.cpp:320
Token consume(Phasor::TokenType type, std::string message)
Definition Parser.cpp:1002
std::unique_ptr< AST::StructDecl > structDecl()
Definition Parser.cpp:875
std::unique_ptr< AST::Statement > whileStatement()
Definition Parser.cpp:335
std::unique_ptr< AST::Statement > expressionStatement()
Definition Parser.cpp:508
std::unique_ptr< AST::Expression > fieldAccess(std::unique_ptr< AST::Expression > object)
Definition Parser.cpp:945
std::vector< Token > tokens
Definition Parser.hpp:36
Token peek()
Definition Parser.cpp:954
std::unique_ptr< AST::TypeNode > parseType()
Definition Parser.cpp:171
std::unique_ptr< AST::Expression > expression()
Definition Parser.cpp:519
std::unique_ptr< AST::Statement > declaration()
Definition Parser.cpp:86
std::unique_ptr< AST::Statement > varDeclaration()
Definition Parser.cpp:194
std::unique_ptr< AST::Expression > assignment()
Definition Parser.cpp:524
Token peekNext()
Definition Parser.cpp:959
std::string currentFunction
Definition Parser.hpp:38
std::unique_ptr< AST::Program > parse()
Definition Parser.cpp:73
std::unique_ptr< AST::Statement > importStatement()
Definition Parser.cpp:491
std::unique_ptr< AST::BlockStmt > block()
Definition Parser.cpp:467
std::unique_ptr< AST::Statement > unsafeStatement()
Definition Parser.cpp:461
bool check(Phasor::TokenType type)
Definition Parser.cpp:985
std::unique_ptr< AST::Statement > functionDeclaration()
Definition Parser.cpp:131
std::unique_ptr< AST::Statement > exportStatement()
Definition Parser.cpp:501
std::unique_ptr< AST::Statement > switchStatement()
Definition Parser.cpp:385
std::unique_ptr< AST::Expression > comparison()
Definition Parser.cpp:593
std::unique_ptr< AST::Expression > finishCall(std::unique_ptr< AST::Expression > callee)
std::unique_ptr< AST::Expression > logicalOr()
Definition Parser.cpp:541
std::unique_ptr< AST::Statement > forStatement()
Definition Parser.cpp:344
std::unique_ptr< AST::StructInstanceExpr > structInstance()
Definition Parser.cpp:912
std::unique_ptr< AST::Statement > printStatement()
Definition Parser.cpp:483
std::unique_ptr< AST::Statement > statement()
Definition Parser.cpp:209
bool match(Phasor::TokenType type)
Definition Parser.cpp:992
std::unique_ptr< AST::Expression > primary()
Definition Parser.cpp:788
std::unique_ptr< AST::Expression > term()
Definition Parser.cpp:621
std::optional< Error > lastError
Definition Parser.hpp:39
Token expect(Phasor::TokenType type, const std::string &message)
Definition Parser.cpp:1043
Token advance()
Definition Parser.cpp:973
std::unique_ptr< AST::Expression > call()
Definition Parser.cpp:697
UnaryOp
Unary operator types.
Definition AST.hpp:159
BinaryOp
Binary operator types.
Definition AST.hpp:168
The Phasor Programming Language and Runtime.
Definition AST.hpp:11
static std::vector< std::unique_ptr< AST::Statement > > resolveIncludes(std::vector< std::unique_ptr< AST::Statement > > &stmts, const std::filesystem::path &baseDir)
Definition Parser.cpp:57
TokenType
Token types for the lexer.
Definition AST.hpp:14
static std::vector< std::unique_ptr< AST::Statement > > resolveIncludesInternal(std::vector< std::unique_ptr< AST::Statement > > &stmts, const std::filesystem::path &baseDir)
Definition Parser.cpp:28
static std::vector< Token > tokenizeFile(const std::filesystem::path &path)
Definition Parser.cpp:10
Field Access Expression Node.
Definition AST.hpp:714
Identifier Expression Node.
Definition AST.hpp:124
Include Statement Node.
Definition AST.hpp:449
Token structure.
Definition AST.hpp:25
size_t line
Definition AST.hpp:28
std::string lexeme
Definition AST.hpp:27
TokenType type
Definition AST.hpp:26
size_t column
Definition AST.hpp:29