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