diff --git a/lib/include/artichoke/Parser/AST/AST.hpp b/lib/include/artichoke/Parser/AST/AST.hpp index c44d640..4b41795 100644 --- a/lib/include/artichoke/Parser/AST/AST.hpp +++ b/lib/include/artichoke/Parser/AST/AST.hpp @@ -28,4 +28,6 @@ namespace arti::lang::ast { return std::make_unique(); } + std::string toString(const AST &tree, std::size_t padding = 0); + } // namespace arti::lang::ast diff --git a/lib/include/artichoke/Parser/Parser.hpp b/lib/include/artichoke/Parser/Parser.hpp index e69de29..9539643 100644 --- a/lib/include/artichoke/Parser/Parser.hpp +++ b/lib/include/artichoke/Parser/Parser.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include +#include + +namespace arti::lang { + + struct Parser { + Parser(std::string source) noexcept; + + Parser(std::string unitName, std::string source) noexcept; + + Parser(Parser &&) noexcept; + Parser &operator=(Parser &&) noexcept; + + Parser(const Parser &) noexcept = delete; + Parser &operator=(const Parser &) noexcept = delete; + + Expected parse(); + + Expected> + parseTopLevelDeclaration(); + + Expected + parseImportDeclaration(); + + Expected + parseAliasDeclaration(); + + Expected + parseModuleDeclaration(); + + Expected + parseStructDeclaration(); + + Expected + parseEnumDeclaration(); + + Expected> + parseGenericParamsList(); + + Expected + parseGenericParam(); + + Expected> + parseStructMembersList(); + + Expected + parseStructMember(); + + Expected> + parseEnumMembersList(); + + Expected + parseEnumMember(); + + Expected + parseFunctionDeclaration(); + + Expected + parseNamespacedIdentifier(); + + Expected + parseType(); + + Expected> + parseTypeQualifiers(); + + Expected> + parseGenericArgumentsList(); + + private: + std::string unitName; + std::string sourceCode; + Tokenizer tokenizer; + }; + +} diff --git a/lib/include/artichoke/Util/Expected.hpp b/lib/include/artichoke/Util/Expected.hpp index 2c2a20b..d439e41 100644 --- a/lib/include/artichoke/Util/Expected.hpp +++ b/lib/include/artichoke/Util/Expected.hpp @@ -17,6 +17,10 @@ namespace arti::lang { ecInvalidCharacter, ecInvalidIndex, ecInvalidComment, + ecUnexpectedToken, + ecExpectedSemicolon, + ecImportInsideModule, + ecUnimplemented, }; struct Exception { @@ -71,6 +75,24 @@ namespace arti::lang { else if constexpr (code == ecInvalidComment) { return "Invalid comment found, missing '*/' end of comment"; } + else if constexpr (code == ecUnexpectedToken) { + return std::format( + "Found unexpected token '{}', expected {}", + std::forward(args)... + ); + } + else if constexpr (code == ecExpectedSemicolon) { + return std::format( + "Expected ';', got '{}'", + std::forward(args)... + ); + } + else if constexpr (code == ecImportInsideModule) { + return "Cannot use import statements inside a module declaration"; + } + else if constexpr (code == ecUnimplemented) { + return "Unimplemented"; + } else { return "Unknown error"; } diff --git a/lib/src/Parser/AST/AST.cpp b/lib/src/Parser/AST/AST.cpp new file mode 100644 index 0000000..7242f01 --- /dev/null +++ b/lib/src/Parser/AST/AST.cpp @@ -0,0 +1,1742 @@ +#include + +#include +#include +#include + +#include + +namespace arti::lang::ast { + std::string createPadding(std::size_t padding) { + return std::views::repeat(' ') + | std::views::take(padding) + | std::ranges::to(); + } + + std::string toString(const ModuleDeclNode &, std::size_t); + std::string toString(const StructDeclNode &, std::size_t); + std::string toString(const EnumDeclNode &, std::size_t); + std::string toString(const FunctionDeclNode &, std::size_t); + std::string toString(const ImportDeclNode &, std::size_t); + std::string toString(const AliasDeclNode &, std::size_t); + std::string toString(const EnumMemberNode &, std::size_t); + std::string toString(const StructMemberNode &, std::size_t); + std::string toString(const GenericParamNode &, std::size_t); + std::string toString(const FunctionParamNode &, std::size_t); + std::string toString(const TopLevelDeclNode &, std::size_t); + std::string toString(const ModuleInnerDeclNode &, std::size_t); + std::string toString(const TypeNode &, std::size_t); + std::string toString(const GenericTypeNode &, std::size_t); + std::string toString(const IdentifierTypeNode &, std::size_t); + std::string toString(const NamespacedTypeNode &, std::size_t); + std::string toString(const NamespacedIdentifierNode &, std::size_t); + std::string toString(const TypeExpressionNode &, std::size_t); + std::string toString(const CharLtrlNode &, std::size_t); + std::string toString(const NullLtrlNode &, std::size_t); + std::string toString(const StringLtrlNode &, std::size_t); + std::string toString(const FloatLtrlNode &, std::size_t); + std::string toString(const IntegerLtrlNode &, std::size_t); + std::string toString(const BooleanLtrlNode &, std::size_t); + std::string toString(const StructLtrlNode &, std::size_t); + std::string toString(const SliceLtrlNode &, std::size_t); + std::string toString(const StructLtrlNamedFieldInitNode &, std::size_t); + std::string toString(const StructLtrlPositionalInitNode &, std::size_t); + std::string toString(const StructLtrlNamedInitializerNode &, std::size_t); + std::string toString(const StructLtrlPositionalInitializerNode &,std::size_t); + std::string toString(const StructLtrlInitializerNode &, std::size_t); + std::string toString(const IdentifierExprNode &, std::size_t); + std::string toString(const UnaryExprNode &, std::size_t); + std::string toString(const BinaryExprNode &, std::size_t); + std::string toString(const AssignExprNode &, std::size_t); + std::string toString(const CompoundAssignExprNode &, std::size_t); + std::string toString(const FunctionCallExprNode &, std::size_t); + std::string toString(const SliceAccessExprNode &, std::size_t); + std::string toString(const SliceRangeExprNode &, std::size_t); + std::string toString(const MemberAccessExprNode &, std::size_t); + std::string toString(const PointerAccessExprNode &, std::size_t); + std::string toString(const ScopeAccessExprNode &, std::size_t); + std::string toString(const ReflectionExprNode &, std::size_t); + std::string toString(const SliceCreationExprNode &, std::size_t); + std::string toString(const SliceLengthExprNode &, std::size_t); + std::string toString(const SlicePtrExprNode &, std::size_t); + std::string toString(const ExpressionNode &, std::size_t); + std::string toString(const CodeBlockStmtNode &, std::size_t); + std::string toString(const VariableStmtNode &, std::size_t); + std::string toString(const IfStmtNode &, std::size_t); + std::string toString(const ElseStmtNode &, std::size_t); + std::string toString(const DeferStmtNode &, std::size_t); + std::string toString(const ErrDeferStmtNode &, std::size_t); + std::string toString(const ReturnStmtNode &, std::size_t); + std::string toString(const BreakStmtNode &, std::size_t); + std::string toString(const ContinueStmtNode &, std::size_t); + std::string toString(const MatchStmtNode &, std::size_t); + std::string toString(const SwitchStmtNode &, std::size_t); + std::string toString(const CForStmtNode &, std::size_t); + std::string toString(const RangeForStmtNode &, std::size_t); + std::string toString(const WhileStmtNode &, std::size_t); + std::string toString(const DoWhileStmtNode &, std::size_t); + std::string toString(const InfLoopStmtNode &, std::size_t); + std::string toString(const ExpressionStmtNode &, std::size_t); + std::string toString(const MatchCaseNode &, std::size_t); + std::string toString(const SwitchCaseNode &, std::size_t); + std::string toString(const StatementNode &, std::size_t); + std::string toString(const ElseBranchNode &, std::size_t); + std::string toString(const DeferableNode &, std::size_t); + std::string toString(const PreLoopStmtNode &, std::size_t); + std::string toString(UnaryOperator op); + std::string toString(BinaryOperator op); + std::string toString(CompoundAssignOperator op); + + std::string toString(const AST &tree, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + std::vector childs; + + ss << std::format("- CompilationUnit {}", tree->unitName); + + for (const auto &d : tree->declarations) { + ss << std::format("\n{} - {}", paddingStr, toString(d, padding + 2)); + } + + return ss.str(); + } + + std::string toString(const TopLevelDeclNode &tlDecl, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const ModuleDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const StructDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const EnumDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const FunctionDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ImportDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const AliasDeclNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, tlDecl); + } + + std::string toString(const ModuleDeclNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "Module {} {}", + toString(node->name, padding), + node->isExported ? "[exported]" : "" + ); + + if (! node->aliasDeclarations.empty()) { + ss << std::format("\n{} - AliasedTypes", paddingStr); + + for (const auto &al : node->aliasDeclarations) { + ss + << std::format("\n{} - {}", paddingStr, toString(al, padding + 4)); + } + } + + if (! node->innerDeclarations.empty()) { + ss << std::format("\n{} - InnerDeclarations", paddingStr); + + for (const auto &id : node->innerDeclarations) { + ss + << std::format("\n{} - {}", paddingStr, toString(id, padding + 4)); + } + } + + if (! node->childModules.empty()) { + ss << std::format("\n{} - ChildModules", paddingStr); + + for (const auto &cm : node->childModules) { + ss + << std::format("\n{} - {}", paddingStr, toString(cm, padding + 4)); + } + } + + return ss.str(); + } + + std::string toString(const StructDeclNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "Struct {} {}", + node->name, + node->isExported ? "[exported]" : "" + ); + + if (! node->genericParams.empty()) { + ss << std::format("\n{} - GenericParams", paddingStr); + + for (const auto &gp : node->genericParams) { + ss + << std::format("\n{} - {}", paddingStr, toString(gp, padding + 4)); + } + } + + if (! node->structMembers.empty()) { + ss << std::format("\n{} - FieldMembers", paddingStr); + + for (const auto &sm : node->structMembers) { + ss + << std::format("\n{} - {}", paddingStr, toString(sm, padding + 4)); + } + } + + return ss.str(); + } + + std::string toString(const EnumDeclNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "Enum {} {}", + node->name, + node->isExported ? "[exported]" : "" + ); + + if (! node->genericParams.empty()) { + ss << std::format("\n{} - GenericParams", paddingStr); + + for (const auto &gp : node->genericParams) { + ss + << std::format("\n{} - {}", paddingStr, toString(gp, padding + 4)); + } + } + + ss << std::format("\n{} - EnumValues", paddingStr); + + for (const auto &em : node->enumMembers) { + ss << std::format("\n{} - {}", paddingStr, toString(em, padding + 4)); + } + + return ss.str(); + } + + std::string toString(const FunctionDeclNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "Function {} {}", + node->name, + node->isExported ? "[exported]" : "" + ); + + if (node->returnType) { + ss << std::format("\n{} - ReturnType", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->returnType, padding + 4) + ); + } + + if (! node->genericParams.empty()) { + ss << std::format("\n{} - GenericParams", paddingStr); + + for (const auto &gp : node->genericParams) { + ss + << std::format("\n{} - {}", paddingStr, toString(gp, padding + 4)); + } + } + + if (! node->functionParams.empty()) { + ss << std::format("\n{} - FunctionParams", paddingStr); + + for (const auto &gp : node->functionParams) { + ss + << std::format("\n{} - {}", paddingStr, toString(gp, padding + 4)); + } + } + + ss << std::format("\n{} - FunctionBody", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->functionBody, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const ImportDeclNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "Import {} {}", + toString(node->importTarget, padding), + node->importAll ? "::*" : "" + ); + + return ss.str(); + } + + std::string toString(const AliasDeclNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "Alias {}", + node->alias + ); + + ss << std::format("\n{} - AliasedType", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->target, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const EnumMemberNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "EnumMember {}", + node->name + ); + + if (node->type) { + ss << std::format("\n{} - StorageType", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->type, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const StructMemberNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << std::format( + "StructMember {}", + node->name + ); + + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->type, padding + 2) + ); + + return ss.str(); + } + + std::string toString(const GenericParamNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("typename {}", node->name); + } + + std::string toString(const FunctionParamNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + if (node->isThis) { + ss << std::format( + "This", + paddingStr + ); + } + else { + ss << std::format( + "Param {}", + node->name + ); + } + + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->type, padding + 2) + ); + + return ss.str(); + } + + std::string toString(const ModuleInnerDeclNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const StructDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const EnumDeclNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const FunctionDeclNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const TypeNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "Type"; + + if (!node->qualifiers.empty()) { + ss << std::format("\n{} - Qualifiers", paddingStr); + + for (const auto &q : node->qualifiers) { + switch(q) { + case TypeQualifier::Pointer: + ss << std::format("\n{} - Pointer (*)", paddingStr); + break; + case TypeQualifier::Slice: + ss << std::format("\n{} - Slice ([])", paddingStr); + break; + case TypeQualifier::Mutable: + ss << std::format("\n{} - Mutable ($)", paddingStr); + break; + case TypeQualifier::Optional: + ss << std::format("\n{} - Optional (?)", paddingStr); + break; + default: + break; + } + } + } + + ss << std::format("\n{} - BaseType", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->baseType, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const GenericTypeNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "GenericType"; + ss << std::format("\n{} - BaseType", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->baseType, padding + 4) + ); + + if (!node->genericArgs.empty()) { + ss << std::format("\n{} - GenericArgs", paddingStr); + for (const auto &ga : node->genericArgs) { + ss + << std::format("\n{} - {}", paddingStr, toString(ga, padding + 4)); + } + } + + return ss.str(); + } + + std::string toString(const IdentifierTypeNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "IdentifierType"; + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->typeName, padding + 2) + ); + + return ss.str(); + } + + std::string toString(const NamespacedTypeNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "NamespacedType"; + + ss << std::format("\n{} - BaseType", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->baseType, padding + 4) + ); + + ss << std::format("\n{} - TypeName", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + node->typeName + ); + + return ss.str(); + } + + std::string + toString(const NamespacedIdentifierNode &node, std::size_t padding) { + std::ignore = padding; + return node->identParts + | std::views::join_with(std::string_view{"::"}) + | std::ranges::to(); + } + + std::string toString(const TypeExpressionNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const GenericTypeNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const IdentifierTypeNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const NamespacedTypeNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const CharLtrlNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("CharLiteral '{}'", node->value); + } + + std::string toString(const NullLtrlNode &node, std::size_t padding) { + std::ignore = node; + std::ignore = padding; + return std::format("NullLiteral 'null'"); + } + + std::string toString(const StringLtrlNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("StringLiteral \"{}\"", node->value); + } + + std::string toString(const FloatLtrlNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("FloatLiteral {}", node->value); + } + + std::string toString(const IntegerLtrlNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("IntegerLiteral {}", node->value); + } + + std::string toString(const BooleanLtrlNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("BooleanLiteral {}", node->value ? "true" : "false"); + } + + std::string toString(const StructLtrlNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "StructLiteral"; + + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->type, padding + 2) + ); + + if (node->initializer) { + ss << std::format("\n{} - Elements", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->initializer, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const SliceLtrlNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SliceLiteral"; + + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->type, padding + 4) + ); + + if (node->initializer) { + ss << std::format("\n{} - Elements", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->initializer, padding + 4) + ); + } + + return ss.str(); + } + + std::string + toString(const StructLtrlNamedFieldInitNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "FieldInitializer"; + + ss << std::format("\n{} - Field '{}'", paddingStr, node->fieldName); + ss << std::format("\n{} - Value", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->fieldValue, padding + 4) + ); + + return ss.str(); + } + + std::string + toString(const StructLtrlPositionalInitNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "PositionalInitializer"; + + ss << std::format("\n{} - Value", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->fieldValue, padding + 4) + ); + + return ss.str(); + } + + std::string + toString(const StructLtrlNamedInitializerNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "InitializerList"; + ss << std::format("\n{} - Elements", paddingStr); + + for (const auto &ele : node->fields) { + ss << std::format( + "\n{} - {}", + paddingStr, + toString(ele, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString( + const StructLtrlPositionalInitializerNode &node, + std::size_t padding + ) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "InitializerList"; + ss << std::format("\n{} - Elements", paddingStr); + + for (const auto &[idx, ele] : std::views::enumerate(node->fields)) { + ss << std::format( + "\n{} - [{}] {}", + paddingStr, + idx, + toString(ele, padding + 4) + ); + } + + return ss.str(); + } + + std::string + toString(const StructLtrlInitializerNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const StructLtrlNamedInitializerNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const StructLtrlPositionalInitializerNode &node) + -> std::string { return toString(node, padding); }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const IdentifierExprNode &node, std::size_t padding) { + std::ignore = padding; + return std::format("Identifier {}", node->identifierName); + } + + std::string toString(const UnaryExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "UnaryExpression"; + ss << std::format("\n{} - Operator {}", paddingStr, toString(node->op)); + + ss << std::format("\n{} - Operand", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->right, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const BinaryExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "BinaryExpression"; + ss << std::format("\n{} - Operator {}", paddingStr, toString(node->op)); + + ss << std::format("\n{} - Left", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->left, padding + 4) + ); + + ss << std::format("\n{} - Right", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->right, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const AssignExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "AssignExpression"; + ss << std::format("\n{} - Left", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->left, padding + 4) + ); + + ss << std::format("\n{} - Right", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->right, padding + 4) + ); + + return ss.str(); + } + + std::string + toString(const CompoundAssignExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "CompoundAssignExpression"; + ss << std::format("\n{} - Operator {}", paddingStr, toString(node->op)); + + ss << std::format("\n{} - Left", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->left, padding + 4) + ); + + ss << std::format("\n{} - Right", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->left, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const FunctionCallExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "FunctionCallExpression"; + ss << std::format("\n{} - Callee", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->callee, padding + 4) + ); + + if (! node->arguments.empty()) { + ss << std::format("\n{} - Arguments", paddingStr); + + for (const auto &arg : node->arguments) { + ss << std::format( + "\n{} - {}", + paddingStr, + toString(arg, padding + 4) + ); + } + } + + return ss.str(); + } + + std::string toString(const SliceAccessExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SliceAccessExpression"; + ss << std::format("\n{} - Slice", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->slice, padding + 4) + ); + + ss << std::format("\n{} - Index", paddingStr); + + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->index, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const SliceRangeExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SliceRangeExpression"; + ss << std::format("\n{} - Slice", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->slice, padding + 4) + ); + + if (node->start) { + ss << std::format("\n{} - Start", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->start, padding + 4) + ); + } + + if (node->end) { + ss << std::format("\n{} - End", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->end, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const MemberAccessExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "MemberAccessExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->object, padding + 4) + ); + + ss << std::format("\n{} - Member '{}'", paddingStr, node->memberName); + + return ss.str(); + } + + std::string toString(const PointerAccessExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "PointerAccessExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->object, padding + 4) + ); + + ss << std::format("\n{} - Member '{}'", paddingStr, node->memberName); + + return ss.str(); + } + + std::string toString(const ScopeAccessExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ScopeAccessExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->scope, padding + 4) + ); + + if (! node->genericParams.empty()) { + ss << std::format("\n{} - GenericParams", paddingStr); + + for (const auto &gp : node->genericParams) { + ss + << std::format("\n{} - {}", paddingStr, toString(gp, padding + 4)); + } + } + + ss << std::format("\n{} - Member '{}'", paddingStr, node->memberName); + + return ss.str(); + } + + std::string toString(const ReflectionExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ReflectionExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->object, padding + 4) + ); + + if (node->attribute) { + ss + << std::format("\n{} - Attribute '{}'", paddingStr, *node->attribute); + } + + return ss.str(); + } + + std::string toString(const SliceCreationExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SliceCreationExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->object, padding + 4) + ); + + ss << std::format("\n{} - Length", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->length, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const SliceLengthExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SliceLengthExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->object, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const SlicePtrExprNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SlicePtrExpression"; + ss << std::format("\n{} - Object", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->object, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const ExpressionNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const CharLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const NullLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const StringLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const FloatLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const IntegerLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const BooleanLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const StructLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SliceLtrlNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const IdentifierExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const UnaryExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const BinaryExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const AssignExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const CompoundAssignExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const FunctionCallExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SliceAccessExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SliceRangeExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const MemberAccessExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const PointerAccessExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ScopeAccessExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SliceCreationExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SliceLengthExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SlicePtrExprNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ReflectionExprNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const CodeBlockStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "CodeBlock"; + + for (const auto &gp : node->statements) { + ss << std::format("\n{} - {}", paddingStr, toString(gp, padding + 2)); + } + + return ss.str(); + } + + std::string toString(const VariableStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "VariableDeclaration"; + ss << std::format("\n{} - Name '{}'", paddingStr, node->name); + ss << std::format( + "\n{} - Mutability '{}'", + paddingStr, + node->mutability == Mutability::Mutable ? "let" : "def" + ); + + if (node->type) { + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->type, padding + 4) + ); + } + + if (node->initializer) { + ss << std::format("\n{} - Initializer", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->initializer, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const IfStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "IfStatement"; + + if (node->unwrappedVar) { + ss << std::format( + "\n{} - UnwrappedVar '{}'", + paddingStr, + *node->unwrappedVar + ); + } + + ss << std::format("\n{} - Condition", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->condition, padding + 4) + ); + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + if (node->elseBranch) { + ss << std::format("\n{} - ElseBranch", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->elseBranch, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const ElseStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ElseStatement"; + + if (node->unwrappedVar) { + ss << std::format( + "\n{} - UnwrappedVar '{}'", + paddingStr, + *node->unwrappedVar + ); + } + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const DeferStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "DeferStatement"; + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const ErrDeferStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ErrDeferStatement"; + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const ReturnStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ReturnStatement"; + + if (node->value) { + ss << std::format("\n{} - Expression", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->value, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const BreakStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "BreakStatement"; + + if (node->label) { + ss << std::format("\n{} - Label '{}'", paddingStr, *node->label); + } + + return ss.str(); + } + + std::string toString(const ContinueStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ContinueStatement"; + + if (node->label) { + ss << std::format("\n{} - Label '{}'", paddingStr, *node->label); + } + + return ss.str(); + } + + std::string toString(const MatchStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "MatchStatement"; + + ss << std::format("\n{} - Value", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->value, padding + 4) + ); + + if (!node->matchCases.empty()) { + ss << std::format("\n{} - Cases", paddingStr); + for (const auto &cas : node->matchCases) { + ss << std::format( + "\n{} - {}", + paddingStr, + toString(cas, padding + 4) + ); + } + } + + if (node->defaultCase) { + ss << std::format("\n{} - DefaultCase", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->defaultCase, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const SwitchStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "SwitchStatement"; + + ss << std::format("\n{} - Value", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->value, padding + 4) + ); + + if (!node->switchCases.empty()) { + ss << std::format("\n{} - Cases", paddingStr); + for (const auto &cas : node->switchCases) { + ss << std::format( + "\n{} - {}", + paddingStr, + toString(cas, padding + 4) + ); + } + } + + if (node->defaultCase) { + ss << std::format("\n{} - DefaultCase", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->defaultCase, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const CForStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "CForStatement"; + + if (node->label) { + ss << std::format( + "\n{} - Label '{}'", + paddingStr, + *node->label + ); + } + + if (node->preLoop) { + ss << std::format("\n{} - PreLoop", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->preLoop, padding + 4) + ); + } + + ss << std::format("\n{} - Condition", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->condition, padding + 4) + ); + + if (node->postLoop) { + ss << std::format("\n{} - PostLoop", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->postLoop, padding + 4) + ); + } + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const RangeForStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ForRangeStatement"; + + if (node->label) { + ss << std::format( + "\n{} - Label '{}'", + paddingStr, + *node->label + ); + } + + ss << std::format( + "\n{} - Variable '{}'{}", + paddingStr, + node->varName, + node->varMutability == Mutability::Mutable + ? " [mut]" + : "" + ); + + ss << std::format("\n{} - Range", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->range, padding + 4) + ); + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const WhileStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "WhileStatement"; + + if (node->label) { + ss << std::format( + "\n{} - Label '{}'", + paddingStr, + *node->label + ); + } + + if (node->unwrappedVar) { + ss << std::format( + "\n{} - UnwrappedVar '{}'", + paddingStr, + *node->unwrappedVar + ); + } + + ss << std::format("\n{} - Condition", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->condition, padding + 4) + ); + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + if (node->elseBranch) { + ss << std::format("\n{} - ElseBranch", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(*node->elseBranch, padding + 4) + ); + } + + return ss.str(); + } + + std::string toString(const DoWhileStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "DoWhileStatement"; + + if (node->label) { + ss << std::format( + "\n{} - Label '{}'", + paddingStr, + *node->label + ); + } + + ss << std::format("\n{} - Condition", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->condition, padding + 4) + ); + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const InfLoopStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "InfLoopStatement"; + + if (node->label) { + ss << std::format( + "\n{} - Label '{}'", + paddingStr, + *node->label + ); + } + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const ExpressionStmtNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "ExpressionStatement"; + + ss << std::format("\n{} - Expression", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->expression, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const MatchCaseNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "MatchCase"; + + if (node->unwrappedVar) { + ss << std::format( + "\n{} - UnwrappedVar '{}'", + paddingStr, + *node->unwrappedVar + ); + } + + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->matchType, padding + 2) + ); + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const SwitchCaseNode &node, std::size_t padding) { + std::stringstream ss; + auto paddingStr = createPadding(padding); + + ss << "MatchCase"; + + ss << std::format("\n{} - Matcher", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->matchExpr, padding + 4) + ); + + ss << std::format("\n{} - Body", paddingStr); + ss << std::format( + "\n{} - {}", + paddingStr, + toString(node->body, padding + 4) + ); + + return ss.str(); + } + + std::string toString(const StatementNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const VariableStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const IfStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const DeferStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ErrDeferStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ReturnStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const BreakStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ContinueStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const MatchStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const SwitchStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const CForStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const RangeForStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const WhileStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const DoWhileStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const InfLoopStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ExpressionStmtNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const ElseBranchNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const ElseStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const IfStmtNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const DeferableNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const ExpressionStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const CodeBlockStmtNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(const PreLoopStmtNode &node, std::size_t padding) { + auto visitor = OverloadSet{ + [padding](const VariableStmtNode &node) -> std::string { + return toString(node, padding); + }, + [padding](const ExpressionStmtNode &node) -> std::string { + return toString(node, padding); + }, + }; + + return std::visit(visitor, node); + } + + std::string toString(UnaryOperator op) { + using enum UnaryOperator; + + switch (op) { + case Not: return "Not (!)"; + case Minus: return "Minus (-)"; + case BitNot: return "BitNot (~)"; + case Ampersand: return "Ampersand (&)"; + case Star: return "Star (*)"; + default: std::unreachable(); break; + } + + std::unreachable(); + } + + std::string toString(BinaryOperator op) { + using enum BinaryOperator; + + switch (op) { + case Equal: return "Equal (==)"; + case NotEqual: return "NotEqual (!=)"; + case GreaterThan: return "GreaterThan (>)"; + case LessThan: return "LessThan (<)"; + case GreaterEqual: return "GreaterEqual (>=)"; + case LessEqual: return "LessEqual (<=)"; + case BitAnd: return "BitAnd (&)"; + case BitXor: return "BitXor (^)"; + case BitOr: return "BitOr (|)"; + case LeftShift: return "LeftShift (<<)"; + case RightShift: return "RightShift (>>)"; + case Adition: return "Adition (+)"; + case Substraction: return "Substraction (-)"; + case Multiplication: return "Multiplication (*)"; + case Division: return "Division (/)"; + case Modulo: return "Modulo (%)"; + case BoolAnd: return "BoolAnd (&&)"; + case BoolOr: return "BoolOr (||)"; + default: std::unreachable(); break; + } + + std::unreachable(); + } + + std::string toString(CompoundAssignOperator op) { + using enum CompoundAssignOperator; + + switch (op) { + case Addition: return "Addition (+)"; + case Substraction: return "Substraction (-)"; + case Multiplication: return "Multiplication (*)"; + case Division: return "Division (/)"; + case Modulo: return "Modulo (%)"; + case BitAnd: return "BitAnd (&)"; + case BitOr: return "BitOr (|)"; + case LeftShift: return "LeftShift (<<)"; + case RightShift: return "RightShift (>>)"; + case BoolAnd: return "BoolAnd (&&)"; + case BoolOr: return "BoolOr (||)"; + default: std::unreachable(); break; + } + + std::unreachable(); + } + +} // namespace arti::lang::ast diff --git a/lib/src/Parser/Declarations.cpp b/lib/src/Parser/Declarations.cpp new file mode 100644 index 0000000..f42fbc3 --- /dev/null +++ b/lib/src/Parser/Declarations.cpp @@ -0,0 +1,755 @@ +#include + +namespace arti::lang { + + Expected> + Parser::parseTopLevelDeclaration() { + auto peekToken = tokenizer.peek(); + + bool exportable = false; + + if (! peekToken) { + return Unexpected<>{ std::move(peekToken).error() }; + } + + if (peekToken->value == TokenV::kwExport) { + exportable = true; + std::ignore = tokenizer.consume(); + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected<>{ std::move(peekToken).error() }; + } + } + + if (peekToken->value == TokenV::kwImport) { + if (exportable) { + return langException( + peekToken->line, + peekToken->column, + toString(*peekToken), + "exportable declaration, ie. Struct, Enum, Function, Module" + ); + } + + auto node = parseImportDeclaration(); + + if (! node) { + return Unexpected<>{ std::move(node).error() }; + } + + return ast::TopLevelDeclNode{ std::move(node).value() }; + } + else if (peekToken->value == TokenV::kwUsing) { + if (exportable) { + return langException( + peekToken->line, + peekToken->column, + toString(*peekToken), + "exportable declaration, ie. Struct, Enum, Function, Module" + ); + } + + auto node = parseAliasDeclaration(); + + if (! node) { + return Unexpected<>{ std::move(node).error() }; + } + + return ast::TopLevelDeclNode{ std::move(node).value() }; + } + else if (peekToken->value == TokenV::kwModule) { + auto node = parseModuleDeclaration(); + + if (! node) { + return Unexpected<>{ std::move(node).error() }; + } + + (*node)->isExported = exportable; + + return ast::TopLevelDeclNode{ std::move(node).value() }; + } + else if (peekToken->value == TokenV::kwStruct) { + auto node = parseStructDeclaration(); + + if (! node) { + return Unexpected<>{ std::move(node).error() }; + } + + (*node)->isExported = exportable; + + return ast::TopLevelDeclNode{ std::move(node).value() }; + } + else if (peekToken->value == TokenV::kwEnum) { + auto node = parseEnumDeclaration(); + + if (! node) { + return Unexpected<>{ std::move(node).error() }; + } + + (*node)->isExported = exportable; + + return ast::TopLevelDeclNode{ std::move(node).value() }; + } + else if (peekToken->value == TokenV::kwFn) { + auto node = parseFunctionDeclaration(); + + if (! node) { + return Unexpected<>{ std::move(node).error() }; + } + + (*node)->isExported = exportable; + + return ast::TopLevelDeclNode{ std::move(node).value() }; + } + else if (peekToken->value != TokenV::tkEOF) { + return langException( + peekToken->line, + peekToken->column, + toString(*peekToken), + "top level declaration" + ); + } + + return std::nullopt; + } + + Expected Parser::parseImportDeclaration() { + auto node = ast::MakeNode(); + node->importAll = false; + + auto kw = tokenizer.peek(); + + if (! kw) { + return Unexpected<>{ std::move(kw).error() }; + } + + node->location.line = kw->line; + node->location.column = kw->column; + + std::ignore = tokenizer.consume(); + + auto target = parseNamespacedIdentifier(); + + if (! target) { + return Unexpected<>{ std::move(target).error() }; + } + + node->importTarget = std::move(target).value(); + + auto peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + + if (peekNext->value == TokenV::opAccess) { + auto peekStar = tokenizer.peek(1); + + if (! peekStar) { + return Unexpected<>{ std::move(peekStar).error() }; + } + + if (peekStar->value != TokenV::opStar) { + return langException( + peekStar->line, + peekStar->column, + toString(*peekStar), + "identifier or '*'" + ); + } + + node->importAll = true; + std::ignore = tokenizer.consume(2); + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + + if (peekNext->value != TokenV::opSemicolon) { + return langException( + peekNext->line, + peekNext->column, + toString(*peekNext) + ); + } + + std::ignore = tokenizer.consume(); + + return node; + } + + Expected Parser::parseAliasDeclaration() { + auto node = ast::MakeNode(); + + auto kw = tokenizer.peek(); + + if (! kw) { + return Unexpected<>{ std::move(kw).error() }; + } + + node->location.line = kw->line; + node->location.column = kw->column; + + std::ignore = tokenizer.consume(); + + auto aliased = tokenizer.peek(); + + if (! aliased) { + return Unexpected<>{ std::move(aliased).error() }; + } + + if (aliased->value != TokenV::tkIdentifier) { + return langException( + aliased->line, + aliased->column, + toString(*aliased), + "identifier" + ); + } + std::ignore = tokenizer.consume(); + + node->alias = aliased->strValue; + + auto eq = tokenizer.peekExpect(0, TokenV::opAssign); + + if (! eq) { + return Unexpected{ std::move(eq).error() }; + } + + std::ignore = tokenizer.consume(); + + auto type = parseType(); + + if (! type) { + return Unexpected{ std::move(type).error() }; + } + + node->target = std::move(type).value(); + + auto semicolon = tokenizer.peekExpect(0, TokenV::opSemicolon); + + if (! semicolon) { + return Unexpected{ std::move(semicolon).error() }; + } + + std::ignore = tokenizer.consume(); + + return node; + } + + Expected Parser::parseModuleDeclaration() { + auto node = ast::MakeNode(); + + auto kw = tokenizer.peek(); + + if (! kw) { + return Unexpected<>{ std::move(kw).error() }; + } + + node->location.line = kw->line; + node->location.column = kw->column; + + std::ignore = tokenizer.consume(); + + auto moduleName = parseNamespacedIdentifier(); + + if (! moduleName) { + return Unexpected<>{ std::move(moduleName).error() }; + } + + node->name = std::move(moduleName).value(); + + auto lsquirly = tokenizer.peekExpect(0, TokenV::opLSquirly); + + if (! lsquirly) { + return Unexpected{ std::move(lsquirly).error() }; + } + + std::ignore = tokenizer.consume(); + + bool keepParsing = true; + auto decl = ast::Optional{}; + + while (keepParsing) { + auto idecl = parseTopLevelDeclaration(); + + if (! idecl) { + return Unexpected<>{ std::move(idecl).error() }; + } + + decl = std::move(idecl).value(); + + if (! decl.has_value()) { + keepParsing = false; + } + else { + if (std::holds_alternative(*decl)) { + node->childModules.push_back( + std::get(std::move(*decl)) + ); + } + else if (std::holds_alternative(*decl)) { + node->innerDeclarations.push_back( + std::get(std::move(*decl)) + ); + } + else if (std::holds_alternative(*decl)) { + node->innerDeclarations.push_back( + std::get(std::move(*decl)) + ); + } + else if (std::holds_alternative(*decl)) { + node->innerDeclarations.push_back( + std::get(std::move(*decl)) + ); + } + else if (std::holds_alternative(*decl)) { + node->aliasDeclarations.push_back( + std::get(std::move(*decl)) + ); + } + else if (std::holds_alternative(*decl)) { + auto importDecl = std::get(std::move(*decl)); + + return langException( + importDecl->location.line, + importDecl->location.column + ); + } + } + } + + auto rsquirly = tokenizer.peekExpect(0, TokenV::opRSquirly); + + if (! rsquirly) { + return Unexpected{ std::move(rsquirly).error() }; + } + + std::ignore = tokenizer.consume(); + + return node; + } + + Expected Parser::parseStructDeclaration() { + auto node = ast::MakeNode(); + + auto kw = tokenizer.peek(); + + if (! kw) { + return Unexpected<>{ std::move(kw).error() }; + } + + node->location.line = kw->line; + node->location.column = kw->column; + + std::ignore = tokenizer.consume(); + + auto name = tokenizer.peek(); + + if (! name) { + return Unexpected<>{ std::move(name).error() }; + } + + if (name->value != TokenV::tkIdentifier) { + return langException( + name->line, + name->column, + toString(*name), + "identifier" + ); + } + std::ignore = tokenizer.consume(); + + node->name = name->strValue; + + auto peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + + if (peekNext->value == TokenV::opLt) { + std::ignore = tokenizer.consume(); + + auto generics = parseGenericParamsList(); + + if (! generics) { + return Unexpected<>{ std::move(generics).error() }; + } + + node->genericParams = std::move(*generics); + + if (auto closeG = tokenizer.peekExpect(0, TokenV::opGt); ! closeG) { + return Unexpected{ std::move(closeG).error() }; + } + std::ignore = tokenizer.consume(); + + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + + if (peekNext->value != TokenV::opLSquirly) { + return langException( + peekNext->line, + peekNext->column, + toString(*peekNext), + "'{'" + ); + } + std::ignore = tokenizer.consume(); + + auto members = parseStructMembersList(); + + if (! members) { + return Unexpected<>{ std::move(members).error() }; + } + + node->structMembers = std::move(members).value(); + + if (auto closeS = tokenizer.peekExpect(0, TokenV::opRSquirly); ! closeS) { + return Unexpected{ std::move(closeS).error() }; + } + std::ignore = tokenizer.consume(); + + return node; + } + + Expected Parser::parseEnumDeclaration() { + auto node = ast::MakeNode(); + + auto kw = tokenizer.peek(); + + if (! kw) { + return Unexpected<>{ std::move(kw).error() }; + } + + node->location.line = kw->line; + node->location.column = kw->column; + + std::ignore = tokenizer.consume(); + + auto name = tokenizer.peek(); + + if (! name) { + return Unexpected<>{ std::move(name).error() }; + } + + if (name->value != TokenV::tkIdentifier) { + return langException( + name->line, + name->column, + toString(*name), + "identifier" + ); + } + std::ignore = tokenizer.consume(); + + node->name = name->strValue; + + auto peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + + if (peekNext->value == TokenV::opLt) { + std::ignore = tokenizer.consume(); + + auto generics = parseGenericParamsList(); + + if (! generics) { + return Unexpected<>{ std::move(generics).error() }; + } + + node->genericParams = std::move(*generics); + + if (auto closeG = tokenizer.peekExpect(0, TokenV::opGt); ! closeG) { + return Unexpected{ std::move(closeG).error() }; + } + std::ignore = tokenizer.consume(); + + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + + if (peekNext->value != TokenV::opLSquirly) { + return langException( + peekNext->line, + peekNext->column, + toString(*peekNext), + "'{'" + ); + } + std::ignore = tokenizer.consume(); + + auto members = parseEnumMembersList(); + + if (! members) { + return Unexpected<>{ std::move(members).error() }; + } + + node->enumMembers = std::move(members).value(); + + if (auto closeS = tokenizer.peekExpect(0, TokenV::opRSquirly); ! closeS) { + return Unexpected{ std::move(closeS).error() }; + } + std::ignore = tokenizer.consume(); + + return node; + } + + Expected> + Parser::parseGenericParamsList() { + auto paramsList = ast::Vector{}; + + auto peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + + while (peekToken->value != TokenV::opGt) { + auto param = parseGenericParam(); + + if (! param) { + return Unexpected{ std::move(param).error() }; + } + + paramsList.push_back(std::move(param).value()); + + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + } + + return paramsList; + } + + Expected Parser::parseGenericParam() { + auto node = ast::MakeNode(); + + if (auto kwTypename = tokenizer.peekExpect(0, TokenV::kwTypename); + ! kwTypename) { + return Unexpected{ std::move(kwTypename).error() }; + } + else { + node->location = { .line = kwTypename->line, + .column = kwTypename->column }; + } + std::ignore = tokenizer.consume(); + + if (auto ident = tokenizer.peekExpect(0, TokenV::tkIdentifier); ! ident) { + return Unexpected{ std::move(ident).error() }; + } + else { + node->name = ident->strValue; + } + std::ignore = tokenizer.consume(); + + auto sc = tokenizer.peek(); + + if (! sc) { + return Unexpected{ std::move(sc).error() }; + } + + if (sc->value == TokenV::opComma) { + std::ignore = tokenizer.consume(); + } + else if (sc->value != TokenV::opGt) { + return langException( + sc->line, + sc->column, + toString(*sc), + "'}' or ','" + ); + } + + return node; + } + + Expected> + Parser::parseStructMembersList() { + auto membersList = ast::Vector{}; + + auto peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + + while (peekToken->value != TokenV::opRSquirly) { + auto member = parseStructMember(); + + if (! member) { + return Unexpected{ std::move(member).error() }; + } + + membersList.push_back(std::move(member).value()); + + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + } + + return membersList; + } + + Expected Parser::parseStructMember() { + auto node = ast::MakeNode(); + + if (auto ident = tokenizer.peekExpect(0, TokenV::tkIdentifier); ! ident) { + return Unexpected{ std::move(ident).error() }; + } + else { + node->location = { .line = ident->line, .column = ident->column }; + + node->name = ident->strValue; + } + std::ignore = tokenizer.consume(); + + if (auto colon = tokenizer.peekExpect(0, TokenV::opColon); ! colon) { + return Unexpected{ std::move(colon).error() }; + } + std::ignore = tokenizer.consume(); + + auto type = parseType(); + + if (! type) { + return Unexpected{ std::move(type).error() }; + } + + node->type = std::move(type).value(); + + auto sc = tokenizer.peek(); + + if (! sc) { + return Unexpected{ std::move(sc).error() }; + } + + if (sc->value == TokenV::opComma) { + std::ignore = tokenizer.consume(); + } + else if (sc->value != TokenV::opRSquirly) { + return langException( + sc->line, + sc->column, + toString(*sc), + "'}' or ','" + ); + } + + return node; + } + + Expected> Parser::parseEnumMembersList() { + auto membersList = ast::Vector{}; + + auto peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + + while (peekToken->value != TokenV::opRSquirly) { + auto member = parseEnumMember(); + + if (! member) { + return Unexpected{ std::move(member).error() }; + } + + membersList.push_back(std::move(member).value()); + + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + } + + return membersList; + } + + Expected Parser::parseEnumMember() { + auto node = ast::MakeNode(); + + if (auto ident = tokenizer.peekExpect(0, TokenV::tkIdentifier); ! ident) { + return Unexpected{ std::move(ident).error() }; + } + else { + node->location = { .line = ident->line, .column = ident->column }; + + node->name = ident->strValue; + } + std::ignore = tokenizer.consume(); + + auto sc = tokenizer.peek(); + + if (! sc) { + return Unexpected{ std::move(sc).error() }; + } + + if (sc->value == TokenV::opLParen) { + std::ignore = tokenizer.consume(); + + auto type = parseType(); + + if (! type) { + return Unexpected{ std::move(type).error() }; + } + + node->type = std::move(type).value(); + + if (auto closeP = tokenizer.peekExpect(0, TokenV::opRParen); ! closeP) { + return Unexpected{ std::move(closeP).error() }; + } + std::ignore = tokenizer.consume(); + + sc = tokenizer.peek(); + + if (! sc) { + return Unexpected{ std::move(sc).error() }; + } + } + + if (sc->value == TokenV::opComma) { + std::ignore = tokenizer.consume(); + } + else if (sc->value != TokenV::opRSquirly) { + return langException( + sc->line, + sc->column, + toString(*sc), + "'}' or ','" + ); + } + + return node; + } + + Expected Parser::parseFunctionDeclaration() { + auto peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected<>{ std::move(peekToken).error() }; + } + + return langException( + peekToken->line, + peekToken->column + ); + } + +} // namespace arti::lang diff --git a/lib/src/Parser/Expressions.cpp b/lib/src/Parser/Expressions.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/Parser/Literals.cpp b/lib/src/Parser/Literals.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/Parser/Parser.cpp b/lib/src/Parser/Parser.cpp index e69de29..c27476f 100644 --- a/lib/src/Parser/Parser.cpp +++ b/lib/src/Parser/Parser.cpp @@ -0,0 +1,47 @@ +#include + +namespace arti::lang { + + Parser::Parser(std::string source) noexcept + : unitName{} + , sourceCode{ source } + , tokenizer{ source } { } + + Parser::Parser(std::string unitName, std::string source) noexcept + : unitName{ unitName } + , sourceCode{ source } + , tokenizer{ source } { } + + Expected Parser::parse() { + auto unit = ast::MakeNode(); + auto tlDecl = ast::Optional{}; + bool keepParsing = true; + + unit->unitName = this->unitName; + + while (keepParsing) { + if (auto ok = parseTopLevelDeclaration(); ok) { + tlDecl = std::move(ok).value(); + + if (! tlDecl.has_value()) { + keepParsing = false; + } + else { + unit->declarations.push_back(std::move(tlDecl).value()); + } + } + else { + return Unexpected<>{ std::move(ok).error() }; + } + } + + auto eof = tokenizer.peekExpect(0, TokenV::tkEOF); + + if (! eof) { + return Unexpected<>{ std::move(eof).error() }; + } + + return unit; + } + +} // namespace arti::lang diff --git a/lib/src/Parser/Statements.cpp b/lib/src/Parser/Statements.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/Parser/Types.cpp b/lib/src/Parser/Types.cpp new file mode 100644 index 0000000..c7b4053 --- /dev/null +++ b/lib/src/Parser/Types.cpp @@ -0,0 +1,299 @@ +#include + +namespace arti::lang { + + Expected Parser::parseNamespacedIdentifier() { + auto node = ast::MakeNode(); + + auto ident = tokenizer.peekExpect(0, TokenV::tkIdentifier); + + if (! ident) { + return Unexpected<>{ std::move(ident).error() }; + } + else { + node->location = { .line = ident->line, .column = ident->column }; + + node->identParts.emplace_back(ident->strValue); + } + std::ignore = tokenizer.consume(); + + auto peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + + while (peekNext->value == TokenV::opAccess) { + std::ignore = tokenizer.consume(); + + ident = tokenizer.peekExpect(0, TokenV::tkIdentifier); + + if (! ident) { + return Unexpected<>{ std::move(ident).error() }; + } + else { + node->identParts.emplace_back(ident->strValue); + } + std::ignore = tokenizer.consume(); + + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + + return node; + } + + Expected Parser::parseType() { + auto node = ast::MakeNode(); + + if (auto peekNext = tokenizer.peek(); ! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + else { + node->location = { .line = peekNext->line, .column = peekNext->column }; + + if (peekNext->value != TokenV::tkIdentifier) { + auto qualifiers = parseTypeQualifiers(); + + if (! qualifiers) { + return Unexpected<>{ std::move(qualifiers).error() }; + } + + node->qualifiers = std::move(qualifiers).value(); + } + } + + auto identType = parseNamespacedIdentifier(); + + if (! identType) { + return Unexpected<>{ std::move(identType).error() }; + } + + auto currentNode = ast::TypeExpressionNode{}; + + currentNode = ast::MakeNode(); + + std::get(currentNode)->location = + (*identType)->location; + + std::get(currentNode)->typeName = + std::move(identType).value(); + + auto peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + + if (peekNext->value == TokenV::opLt) { + std::ignore = tokenizer.consume(); + + auto args = parseGenericArgumentsList(); + + if (! args) { + return Unexpected<>{ std::move(args).error() }; + } + + if (auto closeG = tokenizer.peekExpect(0, TokenV::opGt); ! closeG) { + return Unexpected<>{ std::move(closeG).error() }; + } + std::ignore = tokenizer.consume(); + + auto newNode = ast::MakeNode(); + + newNode->location = std::visit( + [](const auto &node) { return node->location; }, + currentNode + ); + + newNode->baseType = std::move(currentNode); + newNode->genericArgs = std::move(args).value(); + currentNode = std::move(newNode); + + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + + while (peekNext->value == TokenV::opAccess) { + std::ignore = tokenizer.consume(); + + auto ident = tokenizer.peekExpect(0, TokenV::tkIdentifier); + + if (! ident) { + return Unexpected<>{ std::move(ident).error() }; + } + else { + std::ignore = tokenizer.consume(); + + auto newNode = ast::MakeNode(); + + newNode->location = std::visit( + [](const auto &node) { return node->location; }, + currentNode + ); + + newNode->typeName = ident->strValue; + newNode->baseType = std::move(currentNode); + currentNode = std::move(newNode); + + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + + if (peekNext->value == TokenV::opLt) { + std::ignore = tokenizer.consume(); + + auto args = parseGenericArgumentsList(); + + if (! args) { + return Unexpected<>{ std::move(args).error() }; + } + + if (auto closeG = tokenizer.peekExpect(0, TokenV::opGt); ! closeG) { + return Unexpected<>{ std::move(closeG).error() }; + } + std::ignore = tokenizer.consume(); + + auto newNode = ast::MakeNode(); + + newNode->location = std::visit( + [](const auto &node) { return node->location; }, + currentNode + ); + + newNode->baseType = std::move(currentNode); + newNode->genericArgs = std::move(args).value(); + currentNode = std::move(newNode); + + peekNext = tokenizer.peek(); + + if (! peekNext) { + return Unexpected<>{ std::move(peekNext).error() }; + } + } + } + + node->baseType = std::move(currentNode); + + return node; + } + + Expected> Parser::parseTypeQualifiers() { + auto qualifs = ast::Vector{}; + + auto peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected<>{ std::move(peekToken).error() }; + } + + enum { None, AfterOptional, AfterMutable } state = None; + + while (true) { + switch (peekToken->value) { + using enum TokenV; + + case opStar: + qualifs.push_back(ast::TypeQualifier::Pointer); + state = None; + break; + case opMut: + if (state == AfterMutable) { + return langException( + peekToken->line, + peekToken->column, + toString(*peekToken), + "non mutable type qualifier, i.e. any of ( *, ?, [] )" + ); + } + qualifs.push_back(ast::TypeQualifier::Mutable); + state = AfterMutable; + break; + case opOpt: + if (state == AfterOptional) { + return langException( + peekToken->line, + peekToken->column, + toString(*peekToken), + "non optional type qualifier, i.e. any of ( *, $, [] )" + ); + } + qualifs.push_back(ast::TypeQualifier::Optional); + state = AfterOptional; + break; + case opLBracket: + std::ignore = tokenizer.consume(); + + peekToken = tokenizer.peekExpect(0, opRBracket); + + if (! peekToken) { + return Unexpected<>{ std::move(peekToken).error() }; + } + + qualifs.push_back(ast::TypeQualifier::Slice); + state = None; + break; + default: + return qualifs; + } + + std::ignore = tokenizer.consume(); + + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected<>{ std::move(peekToken).error() }; + } + } + + return qualifs; + } + + Expected> Parser::parseGenericArgumentsList() { + auto args = ast::Vector{}; + + auto peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + + while (peekToken->value != TokenV::opGt) { + auto type = parseType(); + + if (! type) { + return Unexpected<>{ std::move(type).error() }; + } + + args.push_back(std::move(type).value()); + + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + + if (peekToken->value == TokenV::opComma) { + std::ignore = tokenizer.consume(); + + peekToken = tokenizer.peek(); + + if (! peekToken) { + return Unexpected{ std::move(peekToken).error() }; + } + } + } + + return args; + } + +} // namespace arti::lang diff --git a/lib/src/Tokenizer/Tokenizer.cpp b/lib/src/Tokenizer/Tokenizer.cpp index d919078..f93e51d 100644 --- a/lib/src/Tokenizer/Tokenizer.cpp +++ b/lib/src/Tokenizer/Tokenizer.cpp @@ -112,16 +112,12 @@ namespace arti::lang { auto tokenAt = tokensBuffer.at(n); if (tokenAt.value != tokenType) { - return Unexpected<> { - Exception{ - .line = tokenAt.line, - .column = tokenAt.column, - .message = std::format( - "Expected token of type {}, got {}", - toString(tokenType), toString(tokenAt) - ) - } - }; + return langException( + tokenAt.line, + tokenAt.column, + toString(tokenAt), + toString(tokenType) + ); } return tokenAt; @@ -147,16 +143,12 @@ namespace arti::lang { } if (token->value != tokenType) { - return Unexpected<> { - Exception{ - .line = token->line, - .column = token->column, - .message = std::format( - "Expected token of type {}, got {}", - toString(tokenType), toString(*token) - ) - } - }; + return langException( + token->line, + token->column, + toString(*token), + toString(tokenType) + ); } return *token;