11static std::vector<Token>
tokenizeFile(
const std::filesystem::path &path)
13 std::ifstream file(path);
16 throw std::runtime_error(
"Could not open file " + path.string());
18 std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
25static std::vector<std::unique_ptr<AST::Statement>>
resolveIncludes(std::vector<std::unique_ptr<AST::Statement>> &stmts,
26 const std::filesystem::path &baseDir);
29 std::vector<std::unique_ptr<AST::Statement>> &stmts,
const std::filesystem::path &baseDir)
31 std::vector<std::unique_ptr<AST::Statement>> result;
37 auto includePath = (baseDir / includeStmt->modulePath).lexically_normal();
39 Parser parser(tokens, includePath);
40 auto program = parser.
parse();
42 auto resolved =
resolveIncludes(program->statements, includePath.parent_path());
43 for (
auto &stmt : resolved)
45 result.push_back(std::move(stmt));
50 result.push_back(std::move(i));
57static std::vector<std::unique_ptr<AST::Statement>>
resolveIncludes(std::vector<std::unique_ptr<AST::Statement>> &stmts,
58 const std::filesystem::path &baseDir)
76 auto program = std::make_unique<Program>();
94 node->line = start.
line;
95 node->column = start.
column;
103 node->line = start.
line;
104 node->column = start.
column;
112 node->line = start.
line;
113 node->column = start.
column;
121 node->line = start.
line;
122 node->column = start.
column;
136 std::vector<FunctionDecl::Param> params;
144 params.push_back({paramName.
lexeme, std::move(type)});
149 std::unique_ptr<TypeNode> returnType =
nullptr;
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;
175 bool isPointer =
false;
182 std::vector<int> dims;
186 dims.push_back(std::stoi(size.
lexeme));
189 auto node = std::make_unique<TypeNode>(typeName.
lexeme, isPointer, dims);
190 node->line = start.
line;
191 node->column = start.
column;
198 std::unique_ptr<Expression> initializer =
nullptr;
204 auto node = std::make_unique<VarDecl>(name.
lexeme, std::move(initializer));
205 node->line = name.
line;
206 node->column = name.
column;
217 node->line = start.
line;
218 node->column = start.
column;
226 node->line = start.
line;
227 node->column = start.
column;
235 node->line = start.
line;
236 node->column = start.
column;
244 node->line = start.
line;
245 node->column = start.
column;
253 node->line = start.
line;
254 node->column = start.
column;
262 node->line = start.
line;
263 node->column = start.
column;
271 auto node = std::make_unique<BreakStmt>();
272 node->line = start.
line;
273 node->column = start.
column;
281 auto node = std::make_unique<ContinueStmt>();
282 node->line = start.
line;
283 node->column = start.
column;
295 auto node = std::make_unique<IncludeStmt>(pathToken.
lexeme);
296 node->line = start.
line;
297 node->column = start.
column;
305 node->line = start.
line;
306 node->column = start.
column;
314 blk->line = start.
line;
315 blk->column = start.
column;
327 std::unique_ptr<Statement> elseBranch =
nullptr;
332 return std::make_unique<IfStmt>(std::move(condition), std::move(thenBranch), std::move(elseBranch));
342 return std::make_unique<WhileStmt>(std::move(condition), std::move(body));
349 std::unique_ptr<Statement> initializer =
nullptr;
367 std::unique_ptr<Expression> condition =
nullptr;
374 std::unique_ptr<Expression> increment =
nullptr;
382 return std::make_unique<ForStmt>(std::move(initializer), std::move(condition), std::move(increment),
393 std::vector<CaseClause> cases;
394 std::vector<std::unique_ptr<Statement>> defaultStmts;
401 throw std::runtime_error(
"Unterminated switch statement.");
410 std::vector<std::unique_ptr<Statement>> stmts;
417 throw std::runtime_error(
"Unterminated case clause.");
421 cases.emplace_back(std::move(caseValue), std::move(stmts));
434 throw std::runtime_error(
"Unterminated default clause.");
442 throw std::runtime_error(
"Expected 'case' or 'default' in switch statement.");
447 return std::make_unique<SwitchStmt>(std::move(expr), std::move(cases), std::move(defaultStmts));
452 std::unique_ptr<Expression> value =
nullptr;
458 return std::make_unique<ReturnStmt>(std::move(value));
465 return std::make_unique<UnsafeBlockStmt>(
block());
470 std::vector<std::unique_ptr<Statement>> statements;
476 throw std::runtime_error(
"Unterminated block.");
481 return std::make_unique<BlockStmt>(std::move(statements));
488 return std::make_unique<PrintStmt>(std::move(expr));
496 auto node = std::make_unique<ImportStmt>(path.
lexeme);
497 node->line = path.
line;
498 node->column = path.
column;
504 auto node = std::make_unique<ExportStmt>(
declaration());
514 auto node = std::make_unique<ExpressionStmt>(std::move(expr));
515 node->line = start.
line;
516 node->column = start.
column;
533 auto node = std::make_unique<AssignmentExpr>(std::move(expr), std::move(value));
534 node->line = op.
line;
550 auto node = std::make_unique<BinaryExpr>(std::move(expr), BinaryOp::Or, std::move(right));
551 node->line = op.
line;
553 expr = std::move(node);
567 auto node = std::make_unique<BinaryExpr>(std::move(expr), BinaryOp::And, std::move(right));
568 node->line = op.
line;
570 expr = std::move(node);
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;
588 expr = std::move(node);
599 (
peek().lexeme ==
"<" ||
peek().lexeme ==
">" ||
peek().lexeme ==
"<=" ||
peek().lexeme ==
">="))
606 binOp = BinaryOp::LessThan;
608 else if (op.
lexeme ==
">")
610 binOp = BinaryOp::GreaterThan;
612 else if (op.
lexeme ==
"<=")
614 binOp = BinaryOp::LessEqual;
618 binOp = BinaryOp::GreaterEqual;
621 auto node = std::make_unique<BinaryExpr>(std::move(expr), binOp, std::move(right));
622 node->line = op.
line;
624 expr = std::move(node);
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;
642 expr = std::move(node);
655 auto right =
unary();
659 binOp = BinaryOp::Multiply;
661 else if (op.
lexeme ==
"/")
663 binOp = BinaryOp::Divide;
667 binOp = BinaryOp::Modulo;
670 auto node = std::make_unique<BinaryExpr>(std::move(expr), binOp, std::move(right));
671 node->line = op.
line;
673 expr = std::move(node);
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;
694 auto right =
unary();
695 auto node = std::make_unique<UnaryExpr>(UnaryOp::AddressOf, std::move(right));
696 node->line = op.
line;
703 auto right =
unary();
704 auto node = std::make_unique<UnaryExpr>(UnaryOp::Dereference, std::move(right));
705 node->line = op.
line;
722 expr->line = op.
line;
729 expr->line = op.
line;
735 auto node = std::make_unique<PostfixExpr>(PostfixOp::Increment, std::move(expr));
736 node->line = op.
line;
738 expr = std::move(node);
743 auto node = std::make_unique<PostfixExpr>(PostfixOp::Decrement, std::move(expr));
744 node->line = op.
line;
746 expr = std::move(node);
753 auto node = std::make_unique<ArrayAccessExpr>(std::move(expr), std::move(index));
754 node->line = op.
line;
756 expr = std::move(node);
769 std::vector<std::unique_ptr<Expression>> arguments;
783 auto node = std::make_unique<CallExpr>(ident->name, std::move(arguments));
784 node->line = ident->line;
785 node->column = ident->column;
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));
800 throw std::runtime_error(
"Can only call named functions.");
808 auto node = std::make_unique<NumberExpr>(t.
lexeme);
816 auto node = std::make_unique<StringExpr>(t.
lexeme);
830 auto node = std::make_unique<IdentifierExpr>(identTok.
lexeme);
831 node->line = identTok.
line;
832 node->column = identTok.
column;
838 std::vector<std::unique_ptr<Expression>> elements;
847 auto node = std::make_unique<ArrayLiteralExpr>(std::move(elements));
848 node->line = start.
line;
849 node->column = start.
column;
855 auto node = std::make_unique<BooleanExpr>(
true);
863 auto node = std::make_unique<BooleanExpr>(
false);
871 auto node = std::make_unique<NullExpr>();
882 std::cerr <<
"Error: Expect expression at '" <<
peek().
lexeme <<
"'";
885 throw std::runtime_error(
"Expect expression.");
898 std::vector<StructField> fields;
904 throw std::runtime_error(
"Unterminated struct declaration.");
910 fields.emplace_back(fieldNameTok.
lexeme, std::move(type));
919 auto node = std::make_unique<StructDecl>(nameTok.
lexeme, std::move(fields));
920 node->line = start.
line;
921 node->column = start.
column;
932 std::vector<std::pair<std::string, std::unique_ptr<Expression>>> fields;
938 throw std::runtime_error(
"Unterminated struct instance.");
943 fields.emplace_back(fieldNameTok.
lexeme, std::move(value));
952 auto node = std::make_unique<StructInstanceExpr>(nameTok.
lexeme, std::move(fields));
953 node->line = nameTok.
line;
954 node->column = nameTok.
column;
963 auto node = std::make_unique<FieldAccessExpr>(std::move(
object), nameTok.
lexeme);
964 node->line = nameTok.
line;
965 node->column = nameTok.
column;
1028 std::cerr <<
"Error: " << message <<
" at '" <<
peek().
lexeme <<
"'";
1036 throw std::runtime_error(message);
1041 if (
check(type) &&
peek().lexeme == lexeme)
1051 if (
check(type) &&
peek().lexeme == lexeme)
1056 std::cerr <<
"Error: " << message <<
" at '" <<
peek().
lexeme <<
"'";
1065 throw std::runtime_error(message);
1075 throw std::runtime_error(message);
std::vector< Token > tokenize()
std::unique_ptr< AST::Expression > finishCall(std::unique_ptr< AST::Expression > callee)
Parser(const std::vector< Token > &tokens)
std::unique_ptr< AST::Statement > returnStatement()
std::unique_ptr< AST::Expression > equality()
std::unique_ptr< AST::Expression > logicalAnd()
std::filesystem::path sourcePath
std::unique_ptr< AST::Expression > unary()
std::unique_ptr< AST::Expression > factor()
std::unique_ptr< AST::Statement > ifStatement()
std::unique_ptr< AST::StructDecl > structDecl()
std::unique_ptr< AST::Statement > whileStatement()
std::unique_ptr< AST::Statement > expressionStatement()
Token consume(Phasor::TokenType type, const std::string &message)
std::unique_ptr< AST::Expression > fieldAccess(std::unique_ptr< AST::Expression > object)
std::vector< Token > tokens
std::unique_ptr< AST::TypeNode > parseType()
std::unique_ptr< AST::Expression > expression()
std::unique_ptr< AST::Statement > declaration()
std::unique_ptr< AST::Statement > varDeclaration()
std::unique_ptr< AST::Expression > assignment()
std::string currentFunction
std::unique_ptr< AST::Program > parse()
std::unique_ptr< AST::Statement > importStatement()
std::unique_ptr< AST::BlockStmt > block()
std::unique_ptr< AST::Statement > unsafeStatement()
bool check(Phasor::TokenType type)
std::unique_ptr< AST::Statement > functionDeclaration()
std::unique_ptr< AST::Statement > exportStatement()
std::unique_ptr< AST::Statement > switchStatement()
std::unique_ptr< AST::Expression > comparison()
std::unique_ptr< AST::Expression > logicalOr()
std::unique_ptr< AST::Statement > forStatement()
std::unique_ptr< AST::StructInstanceExpr > structInstance()
std::unique_ptr< AST::Statement > printStatement()
std::unique_ptr< AST::Statement > statement()
bool match(Phasor::TokenType type)
std::unique_ptr< AST::Expression > primary()
std::unique_ptr< AST::Expression > term()
std::optional< Error > lastError
Token expect(Phasor::TokenType type, const std::string &message)
std::unique_ptr< AST::Expression > call()
UnaryOp
Unary operator types.
BinaryOp
Binary operator types.
The Phasor Programming Language and Runtime.
static std::vector< std::unique_ptr< AST::Statement > > resolveIncludes(std::vector< std::unique_ptr< AST::Statement > > &stmts, const std::filesystem::path &baseDir)
TokenType
Token types for the lexer.
static std::vector< std::unique_ptr< AST::Statement > > resolveIncludesInternal(std::vector< std::unique_ptr< AST::Statement > > &stmts, const std::filesystem::path &baseDir)
static std::vector< Token > tokenizeFile(const std::filesystem::path &path)
Field Access Expression Node.
Identifier Expression Node.