diff --git a/lib/parser/IParser.hpp b/lib/parser/IParser.hpp new file mode 100644 index 0000000..50bb764 --- /dev/null +++ b/lib/parser/IParser.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_IPARSER_HPP_ +#define PARSER_IPARSER_HPP_ + +#include + +#include "ast/nodes/decls/Module.hpp" +#include "diagnostics/IDiagnosticSink.hpp" +#include "tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class IParser { +public: + virtual ~IParser() = default; + virtual std::unique_ptr Parse(ITokenStream& ts, IDiagnosticSink& diags) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IPARSER_HPP_ diff --git a/lib/parser/ParserFsm.cpp b/lib/parser/ParserFsm.cpp new file mode 100644 index 0000000..79fa76e --- /dev/null +++ b/lib/parser/ParserFsm.cpp @@ -0,0 +1,65 @@ +#include "ParserFsm.hpp" + +#include +#include + +#include "context/ContextParser.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/states/base/IState.hpp" +#include "lib/parser/states/base/StateError.hpp" +#include "lib/parser/states/base/StateRegistry.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" +#include "recovery/SimpleRecovery.hpp" + +namespace ovum::compiler::parser { + +ParserFsm::ParserFsm(std::unique_ptr expr, + std::unique_ptr typep, + std::unique_ptr factory) : + expr_parser_(std::move(expr)), type_parser_(std::move(typep)), factory_(std::move(factory)) { +} + +std::unique_ptr ParserFsm::Parse(ITokenStream& token_stream, IDiagnosticSink& diagnostics) { + ContextParser context; + context.SetDiagnostics(&diagnostics); + context.SetExpr(expr_parser_.get()); + context.SetTypeParser(type_parser_.get()); + context.SetFactory(factory_.get()); + + SimpleRecovery recovery; + + context.PushState(StateRegistry::Module()); + + while (const IState* state = context.CurrentState()) { + auto step = state->TryStep(context, token_stream); + + if (!step.has_value()) { + const auto& message = step.error().Message(); + diagnostics.Error("P0001", message.empty() ? "parse error" : message); + recovery.SyncToStatementEnd(token_stream); + context.PopState(); + continue; + } + + if (!*step) { + context.PopState(); + } + } + + std::unique_ptr root = context.PopNode(); + + if (!root) { + return std::make_unique(); + } + + auto* as_module = dynamic_cast(root.get()); + + if (as_module != nullptr) { + root.release(); + return std::unique_ptr(as_module); + } + + return std::make_unique(); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ParserFsm.hpp b/lib/parser/ParserFsm.hpp new file mode 100644 index 0000000..a4cba9a --- /dev/null +++ b/lib/parser/ParserFsm.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_PARSERFSM_HPP_ +#define PARSER_PARSERFSM_HPP_ + +#include + +#include "IParser.hpp" +#include "ast/IAstFactory.hpp" +#include "pratt/IExpressionParser.hpp" +#include "type_parser/ITypeParser.hpp" + +namespace ovum::compiler::parser { + +class ParserFsm : public IParser { +public: + ParserFsm(std::unique_ptr expr, + std::unique_ptr typep, + std::unique_ptr factory); + + ~ParserFsm() override = default; + + std::unique_ptr Parse(ITokenStream& ts, IDiagnosticSink& diags) override; + +private: + std::unique_ptr expr_parser_; + std::unique_ptr type_parser_; + std::unique_ptr factory_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_PARSERFSM_HPP_ diff --git a/lib/parser/ast/AstVisitor.hpp b/lib/parser/ast/AstVisitor.hpp new file mode 100644 index 0000000..a260ca1 --- /dev/null +++ b/lib/parser/ast/AstVisitor.hpp @@ -0,0 +1,98 @@ +#ifndef PARSER_ASTVISITOR_HPP_ +#define PARSER_ASTVISITOR_HPP_ + +#include "nodes/class_members/CallDecl.hpp" +#include "nodes/class_members/DestructorDecl.hpp" +#include "nodes/class_members/FieldDecl.hpp" +#include "nodes/class_members/MethodDecl.hpp" +#include "nodes/class_members/StaticFieldDecl.hpp" +#include "nodes/decls/ClassDecl.hpp" +#include "nodes/decls/FunctionDecl.hpp" +#include "nodes/decls/GlobalVarDecl.hpp" +#include "nodes/decls/InterfaceDecl.hpp" +#include "nodes/decls/Module.hpp" +#include "nodes/decls/TypeAliasDecl.hpp" +#include "nodes/exprs/Assign.hpp" +#include "nodes/exprs/Binary.hpp" +#include "nodes/exprs/Call.hpp" +#include "nodes/exprs/CastAs.hpp" +#include "nodes/exprs/Elvis.hpp" +#include "nodes/exprs/FieldAccess.hpp" +#include "nodes/exprs/IdentRef.hpp" +#include "nodes/exprs/IndexAccess.hpp" +#include "nodes/exprs/NamespaceRef.hpp" +#include "nodes/exprs/SafeCall.hpp" +#include "nodes/exprs/TypeTestIs.hpp" +#include "nodes/exprs/Unary.hpp" +#include "nodes/exprs/literals/BoolLit.hpp" +#include "nodes/exprs/literals/CharLit.hpp" +#include "nodes/exprs/literals/FloatLit.hpp" +#include "nodes/exprs/literals/IntLit.hpp" +#include "nodes/exprs/literals/NullLit.hpp" +#include "nodes/exprs/literals/StringLit.hpp" +#include "nodes/stmts/BreakStmt.hpp" +#include "nodes/stmts/ContinueStmt.hpp" +#include "nodes/stmts/ExprStmt.hpp" +#include "nodes/stmts/ForStmt.hpp" +#include "nodes/stmts/IfStmt.hpp" +#include "nodes/stmts/ReturnStmt.hpp" +#include "nodes/stmts/UnsafeBlock.hpp" +#include "nodes/stmts/VarDeclStmt.hpp" +#include "nodes/stmts/WhileStmt.hpp" + +namespace ovum::compiler::parser { + +class AstVisitor { +public: + virtual ~AstVisitor() = default; + + // Decls + virtual void Visit(Module&) = 0; + virtual void Visit(FunctionDecl&) = 0; + virtual void Visit(ClassDecl&) = 0; + virtual void Visit(InterfaceMethod&) = 0; + virtual void Visit(InterfaceDecl&) = 0; + virtual void Visit(TypeAliasDecl&) = 0; + virtual void Visit(GlobalVarDecl&) = 0; + virtual void Visit(FieldDecl&) = 0; + virtual void Visit(StaticFieldDecl&) = 0; + virtual void Visit(MethodDecl&) = 0; + virtual void Visit(CallDecl&) = 0; + virtual void Visit(DestructorDecl&) = 0; + + // Stmts + virtual void Visit(Block&) = 0; + virtual void Visit(VarDeclStmt&) = 0; + virtual void Visit(ExprStmt&) = 0; + virtual void Visit(ReturnStmt&) = 0; + virtual void Visit(BreakStmt&) = 0; + virtual void Visit(ContinueStmt&) = 0; + virtual void Visit(IfStmt&) = 0; + virtual void Visit(WhileStmt&) = 0; + virtual void Visit(ForStmt&) = 0; + virtual void Visit(UnsafeBlock&) = 0; + + // Exprs + virtual void Visit(Binary&) = 0; + virtual void Visit(Unary&) = 0; + virtual void Visit(Assign&) = 0; + virtual void Visit(Call&) = 0; + virtual void Visit(FieldAccess&) = 0; + virtual void Visit(IndexAccess&) = 0; + virtual void Visit(NamespaceRef&) = 0; + virtual void Visit(SafeCall&) = 0; + virtual void Visit(Elvis&) = 0; + virtual void Visit(CastAs&) = 0; + virtual void Visit(TypeTestIs&) = 0; + virtual void Visit(IdentRef&) = 0; + virtual void Visit(IntLit&) = 0; + virtual void Visit(FloatLit&) = 0; + virtual void Visit(StringLit&) = 0; + virtual void Visit(CharLit&) = 0; + virtual void Visit(BoolLit&) = 0; + virtual void Visit(NullLit&) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ASTVISITOR_HPP_ diff --git a/lib/parser/ast/BuilderAstFactory.cpp b/lib/parser/ast/BuilderAstFactory.cpp new file mode 100644 index 0000000..59672e8 --- /dev/null +++ b/lib/parser/ast/BuilderAstFactory.cpp @@ -0,0 +1,428 @@ +#include "BuilderAstFactory.hpp" + +#include + +#include "nodes/builders/base/ParserBuilder.hpp" + +namespace ovum::compiler::parser { + +// Decls / Module + +std::unique_ptr BuilderAstFactory::MakeModule(std::string name, + SourceId source_id, + std::vector> decls, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithName(std::move(name)) + .WithSource(source_id) + .WithDecls(std::move(decls)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeFunction(bool is_pure, + std::string name, + std::vector params, + std::unique_ptr return_type, + std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsPure(is_pure) + .WithName(std::move(name)) + .WithParams(std::move(params)) + .WithReturnType(std::move(return_type)) + .WithBody(std::move(body)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeClass(std::string name, + std::vector implements, + std::vector> members, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithName(std::move(name)) + .WithImplements(std::move(implements)) + .WithMembers(std::move(members)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeInterface(std::string name, + std::vector> methods, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithName(std::move(name)) + .WithMethods(std::move(methods)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeInterfaceMethod( + std::string name, + std::vector params, + std::unique_ptr return_type, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithName(std::move(name)) + .WithParams(std::move(params)) + .WithReturnType(std::move(return_type)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeTypeAlias(std::string name, + TypeReference aliased_type, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithName(std::move(name)) + .WithAliasedType(std::move(aliased_type)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeGlobalVar(bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsVar(is_var) + .WithName(std::move(name)) + .WithType(std::move(type)) + .WithInit(std::move(init)); + return b.Build(); +} + +// Class members + +std::unique_ptr BuilderAstFactory::MakeField(bool is_public, + bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsPublic(is_public) + .WithIsVar(is_var) + .WithName(std::move(name)) + .WithType(std::move(type)) + .WithInit(std::move(init)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeStaticField(bool is_public, + bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsPublic(is_public) + .WithIsVar(is_var) + .WithName(std::move(name)) + .WithType(std::move(type)) + .WithInit(std::move(init)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeMethod(bool is_public, + bool is_override, + bool is_static, + bool is_pure, + std::string name, + std::vector params, + std::unique_ptr ret_type, + std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsPublic(is_public) + .WithIsOverride(is_override) + .WithIsStatic(is_static) + .WithIsPure(is_pure) + .WithName(std::move(name)) + .WithParams(std::move(params)) + .WithReturnType(std::move(ret_type)) + .WithBody(std::move(body)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeCallDecl(bool is_public, + std::vector params, + std::unique_ptr ret_type, + std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsPublic(is_public) + .WithParams(std::move(params)) + .WithReturnType(std::move(ret_type)) + .WithBody(std::move(body)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeDestructor(bool is_public, + std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsPublic(is_public) + .WithBody(std::move(body)); + return b.Build(); +} + +// Statements + +std::unique_ptr BuilderAstFactory::MakeBlock(std::vector> stmts, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithStatements(std::move(stmts)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeVarDeclStmt(bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIsVar(is_var) + .WithName(std::move(name)) + .WithType(std::move(type)) + .WithInit(std::move(init)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeExprStmt(std::unique_ptr expr, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithExpr(std::move(expr)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeReturnStmt(std::unique_ptr value, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithValue(std::move(value)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeBreakStmt(SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeContinueStmt(SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeIfStmt(std::vector branches, + std::unique_ptr else_block, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithBranches(std::move(branches)) + .WithElse(std::move(else_block)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeWhileStmt(std::unique_ptr cond, + std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithCondition(std::move(cond)) + .WithBody(std::move(body)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeForStmt(std::string iter_name, + std::unique_ptr iter_expr, + std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithIteratorName(std::move(iter_name)) + .WithIteratorExpr(std::move(iter_expr)) + .WithBody(std::move(body)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeUnsafeBlock(std::unique_ptr body, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithBody(std::move(body)); + return b.Build(); +} + +// Expressions + +std::unique_ptr BuilderAstFactory::MakeBinary(const IBinaryOpTag& op, + std::unique_ptr lhs, + std::unique_ptr rhs, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithOp(op) + .WithLhs(std::move(lhs)) + .WithRhs(std::move(rhs)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeUnary(const IUnaryOpTag& op, + std::unique_ptr operand, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithOp(op) + .WithOperand(std::move(operand)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeAssign(const IAssignOpTag& op, + std::unique_ptr target, + std::unique_ptr value, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithKind(op) + .WithTarget(std::move(target)) + .WithValue(std::move(value)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeCall(std::unique_ptr callee, + std::vector> args, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithCallee(std::move(callee)) + .WithArgs(std::move(args)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeFieldAccess(std::unique_ptr object, + std::string name, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithObject(std::move(object)) + .WithName(std::move(name)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeIndexAccess(std::unique_ptr object, + std::unique_ptr index, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithObject(std::move(object)) + .WithIndex(std::move(index)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeNamespaceRef(std::unique_ptr ns, + std::string name, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithNamespace(std::move(ns)) + .WithName(std::move(name)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeSafeCall(std::unique_ptr object, + std::string method, + std::vector> args, + std::optional inferred_type, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithObject(std::move(object)) + .WithMethod(std::move(method)) + .WithArgs(std::move(args)) + .WithInferredType(std::move(inferred_type)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeElvis(std::unique_ptr lhs, + std::unique_ptr rhs, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithLhs(std::move(lhs)) + .WithRhs(std::move(rhs)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeCastAs(std::unique_ptr expr, + TypeReference type, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithExpr(std::move(expr)) + .WithType(std::move(type)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeTypeTestIs(std::unique_ptr expr, + TypeReference type, + SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span) + .WithExpr(std::move(expr)) + .WithType(std::move(type)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeIdent(std::string name, SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithName(std::move(name)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeInt(long long v, SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithValue(v); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeFloat(long double v, SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithValue(v); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeString(std::string v, SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithValue(std::move(v)); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeChar(char v, SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithValue(v); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeBool(bool v, SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span).WithValue(v); + return b.Build(); +} + +std::unique_ptr BuilderAstFactory::MakeNull(SourceSpan span) { + auto b = ParserBuilder::Make(); + b.WithSpan(span); + return b.Build(); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/BuilderAstFactory.hpp b/lib/parser/ast/BuilderAstFactory.hpp new file mode 100644 index 0000000..1da7dc2 --- /dev/null +++ b/lib/parser/ast/BuilderAstFactory.hpp @@ -0,0 +1,160 @@ +#ifndef PARSER_BUILDERASTFACTORY_HPP_ +#define PARSER_BUILDERASTFACTORY_HPP_ + +#include +#include +#include +#include + +#include "IAstFactory.hpp" + +namespace ovum::compiler::parser { + +class BuilderAstFactory : public IAstFactory { +public: + ~BuilderAstFactory() override = default; + + // Module / Decls + std::unique_ptr MakeModule(std::string name, + SourceId source_id, + std::vector> decls, + SourceSpan span) override; + + std::unique_ptr MakeFunction(bool is_pure, + std::string name, + std::vector params, + std::unique_ptr return_type, + std::unique_ptr body, + SourceSpan span) override; + + std::unique_ptr MakeClass(std::string name, + std::vector implements, + std::vector> members, + SourceSpan span) override; + + std::unique_ptr MakeInterface(std::string name, + std::vector> methods, + SourceSpan span) override; + + std::unique_ptr MakeInterfaceMethod(std::string name, + std::vector params, + std::unique_ptr return_type, + SourceSpan span) override; + + std::unique_ptr MakeTypeAlias(std::string name, TypeReference aliased_type, SourceSpan span) override; + + std::unique_ptr MakeGlobalVar( + bool is_var, std::string name, TypeReference type, std::unique_ptr init, SourceSpan span) override; + + // Class members + std::unique_ptr MakeField(bool is_public, + bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) override; + + std::unique_ptr MakeStaticField(bool is_public, + bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) override; + + std::unique_ptr MakeMethod(bool is_public, + bool is_override, + bool is_static, + bool is_pure, + std::string name, + std::vector params, + std::unique_ptr ret_type, + std::unique_ptr body, + SourceSpan span) override; + + std::unique_ptr MakeCallDecl(bool is_public, + std::vector params, + std::unique_ptr ret_type, + std::unique_ptr body, + SourceSpan span) override; + + std::unique_ptr MakeDestructor(bool is_public, std::unique_ptr body, SourceSpan span) override; + + // Statements + std::unique_ptr MakeBlock(std::vector> stmts, SourceSpan span) override; + + std::unique_ptr MakeVarDeclStmt( + bool is_var, std::string name, TypeReference type, std::unique_ptr init, SourceSpan span) override; + + std::unique_ptr MakeExprStmt(std::unique_ptr expr, SourceSpan span) override; + + std::unique_ptr MakeReturnStmt(std::unique_ptr value, SourceSpan span) override; + + std::unique_ptr MakeBreakStmt(SourceSpan span) override; + std::unique_ptr MakeContinueStmt(SourceSpan span) override; + + std::unique_ptr MakeIfStmt(std::vector branches, + std::unique_ptr else_block, + SourceSpan span) override; + + std::unique_ptr MakeWhileStmt(std::unique_ptr cond, + std::unique_ptr body, + SourceSpan span) override; + + std::unique_ptr MakeForStmt(std::string iter_name, + std::unique_ptr iter_expr, + std::unique_ptr body, + SourceSpan span) override; + + std::unique_ptr MakeUnsafeBlock(std::unique_ptr body, SourceSpan span) override; + + // Expressions + std::unique_ptr MakeBinary(const IBinaryOpTag& op, + std::unique_ptr lhs, + std::unique_ptr rhs, + SourceSpan span) override; + + std::unique_ptr MakeUnary(const IUnaryOpTag& op, std::unique_ptr operand, SourceSpan span) override; + + std::unique_ptr MakeAssign(const IAssignOpTag& op, + std::unique_ptr target, + std::unique_ptr value, + SourceSpan span) override; + + std::unique_ptr MakeCall(std::unique_ptr callee, + std::vector> args, + SourceSpan span) override; + + std::unique_ptr MakeFieldAccess(std::unique_ptr object, + std::string name, + SourceSpan span) override; + + std::unique_ptr MakeIndexAccess(std::unique_ptr object, + std::unique_ptr index, + SourceSpan span) override; + + std::unique_ptr MakeNamespaceRef(std::unique_ptr ns, std::string name, SourceSpan span) override; + + std::unique_ptr MakeSafeCall(std::unique_ptr object, + std::string method, + std::vector> args, + std::optional inferred_type, + SourceSpan span) override; + + std::unique_ptr MakeElvis(std::unique_ptr lhs, std::unique_ptr rhs, SourceSpan span) override; + + std::unique_ptr MakeCastAs(std::unique_ptr expr, TypeReference type, SourceSpan span) override; + + std::unique_ptr MakeTypeTestIs(std::unique_ptr expr, TypeReference type, SourceSpan span) override; + + std::unique_ptr MakeIdent(std::string name, SourceSpan span) override; + std::unique_ptr MakeInt(long long v, SourceSpan span) override; + std::unique_ptr MakeFloat(long double v, SourceSpan span) override; + std::unique_ptr MakeString(std::string v, SourceSpan span) override; + std::unique_ptr MakeChar(char v, SourceSpan span) override; + std::unique_ptr MakeBool(bool v, SourceSpan span) override; + std::unique_ptr MakeNull(SourceSpan span) override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BUILDERASTFACTORY_HPP_ diff --git a/lib/parser/ast/IAstFactory.hpp b/lib/parser/ast/IAstFactory.hpp new file mode 100644 index 0000000..1121465 --- /dev/null +++ b/lib/parser/ast/IAstFactory.hpp @@ -0,0 +1,213 @@ +#ifndef PARSER_IASTFACTORY_HPP_ +#define PARSER_IASTFACTORY_HPP_ + +#include +#include +#include +#include + +#include "nodes/class_members/CallDecl.hpp" +#include "nodes/class_members/DestructorDecl.hpp" +#include "nodes/class_members/FieldDecl.hpp" +#include "nodes/class_members/MethodDecl.hpp" +#include "nodes/class_members/StaticFieldDecl.hpp" +#include "nodes/decls/ClassDecl.hpp" +#include "nodes/decls/FunctionDecl.hpp" +#include "nodes/decls/GlobalVarDecl.hpp" +#include "nodes/decls/InterfaceDecl.hpp" +#include "nodes/decls/Module.hpp" +#include "nodes/decls/TypeAliasDecl.hpp" +#include "nodes/exprs/Assign.hpp" +#include "nodes/exprs/Binary.hpp" +#include "nodes/exprs/Call.hpp" +#include "nodes/exprs/CastAs.hpp" +#include "nodes/exprs/Elvis.hpp" +#include "nodes/exprs/FieldAccess.hpp" +#include "nodes/exprs/IdentRef.hpp" +#include "nodes/exprs/IndexAccess.hpp" +#include "nodes/exprs/NamespaceRef.hpp" +#include "nodes/exprs/SafeCall.hpp" +#include "nodes/exprs/TypeTestIs.hpp" +#include "nodes/exprs/Unary.hpp" +#include "nodes/exprs/literals/BoolLit.hpp" +#include "nodes/exprs/literals/CharLit.hpp" +#include "nodes/exprs/literals/FloatLit.hpp" +#include "nodes/exprs/literals/IntLit.hpp" +#include "nodes/exprs/literals/NullLit.hpp" +#include "nodes/exprs/literals/StringLit.hpp" +#include "nodes/stmts/Block.hpp" +#include "nodes/stmts/BreakStmt.hpp" +#include "nodes/stmts/ContinueStmt.hpp" +#include "nodes/stmts/ExprStmt.hpp" +#include "nodes/stmts/ForStmt.hpp" +#include "nodes/stmts/IfStmt.hpp" +#include "nodes/stmts/ReturnStmt.hpp" +#include "nodes/stmts/UnsafeBlock.hpp" +#include "nodes/stmts/VarDeclStmt.hpp" +#include "nodes/stmts/WhileStmt.hpp" + +#include "lib/parser/ast/nodes/exprs/tags/IAssignOpTag.hpp" +#include "lib/parser/ast/nodes/exprs/tags/IBinaryOpTag.hpp" +#include "lib/parser/ast/nodes/exprs/tags/IUnaryOpTag.hpp" +#include "lib/parser/tokens/SourceSpan.hpp" +#include "lib/parser/types/Param.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class IAstFactory { +public: + virtual ~IAstFactory() = default; + + // Module / Decls + virtual std::unique_ptr MakeModule(std::string name, + SourceId source_id, + std::vector> decls, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeFunction(bool is_pure, + std::string name, + std::vector params, + std::unique_ptr return_type, + std::unique_ptr body, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeClass(std::string name, + std::vector implements, + std::vector> members, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeInterface(std::string name, + std::vector> methods, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeInterfaceMethod(std::string name, + std::vector params, + std::unique_ptr return_type, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeTypeAlias(std::string name, + TypeReference aliased_type, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeGlobalVar( + bool is_var, std::string name, TypeReference type, std::unique_ptr init, SourceSpan span) = 0; + + // Class members + virtual std::unique_ptr MakeField(bool is_public, + bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeStaticField(bool is_public, + bool is_var, + std::string name, + TypeReference type, + std::unique_ptr init, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeMethod(bool is_public, + bool is_override, + bool is_static, + bool is_pure, + std::string name, + std::vector params, + std::unique_ptr ret_type, + std::unique_ptr body, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeCallDecl(bool is_public, + std::vector params, + std::unique_ptr ret_type, + std::unique_ptr body, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeDestructor(bool is_public, + std::unique_ptr body, + SourceSpan span) = 0; + + // Statements + virtual std::unique_ptr MakeBlock(std::vector> stmts, SourceSpan span) = 0; + + virtual std::unique_ptr MakeVarDeclStmt( + bool is_var, std::string name, TypeReference type, std::unique_ptr init, SourceSpan span) = 0; + + virtual std::unique_ptr MakeExprStmt(std::unique_ptr expr, SourceSpan span) = 0; + + virtual std::unique_ptr MakeReturnStmt(std::unique_ptr value, SourceSpan span) = 0; + + virtual std::unique_ptr MakeBreakStmt(SourceSpan span) = 0; + virtual std::unique_ptr MakeContinueStmt(SourceSpan span) = 0; + + virtual std::unique_ptr MakeIfStmt(std::vector branches, + std::unique_ptr else_block, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeWhileStmt(std::unique_ptr cond, + std::unique_ptr body, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeForStmt(std::string iter_name, + std::unique_ptr iter_expr, + std::unique_ptr body, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeUnsafeBlock(std::unique_ptr body, SourceSpan span) = 0; + + // Expressions + virtual std::unique_ptr MakeBinary(const IBinaryOpTag& op, + std::unique_ptr lhs, + std::unique_ptr rhs, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeUnary(const IUnaryOpTag& op, std::unique_ptr operand, SourceSpan span) = 0; + + virtual std::unique_ptr MakeAssign(const IAssignOpTag& op, + std::unique_ptr target, + std::unique_ptr value, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeCall(std::unique_ptr callee, + std::vector> args, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeFieldAccess(std::unique_ptr object, + std::string name, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeIndexAccess(std::unique_ptr object, + std::unique_ptr index, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeNamespaceRef(std::unique_ptr ns, + std::string name, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeSafeCall(std::unique_ptr object, + std::string method, + std::vector> args, + std::optional inferred_type, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeElvis(std::unique_ptr lhs, std::unique_ptr rhs, SourceSpan span) = 0; + + virtual std::unique_ptr MakeCastAs(std::unique_ptr expr, TypeReference type, SourceSpan span) = 0; + + virtual std::unique_ptr MakeTypeTestIs(std::unique_ptr expr, + TypeReference type, + SourceSpan span) = 0; + + virtual std::unique_ptr MakeIdent(std::string name, SourceSpan span) = 0; + virtual std::unique_ptr MakeInt(long long v, SourceSpan span) = 0; + virtual std::unique_ptr MakeFloat(long double v, SourceSpan span) = 0; + virtual std::unique_ptr MakeString(std::string v, SourceSpan span) = 0; + virtual std::unique_ptr MakeChar(char v, SourceSpan span) = 0; + virtual std::unique_ptr MakeBool(bool v, SourceSpan span) = 0; + virtual std::unique_ptr MakeNull(SourceSpan span) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IASTFACTORY_HPP_ diff --git a/lib/parser/ast/nodes/base/AstNode.cpp b/lib/parser/ast/nodes/base/AstNode.cpp new file mode 100644 index 0000000..da2c826 --- /dev/null +++ b/lib/parser/ast/nodes/base/AstNode.cpp @@ -0,0 +1,20 @@ +#include "lib/parser/ast/nodes/base/AstNode.hpp" + +namespace ovum::compiler::parser { +const SourceSpan& AstNode::Span() const noexcept { + return span_; +} + +void AstNode::SetSpan(SourceSpan span) { + span_ = std::move(span); +} + +void AstNode::SetSpanParts(SourceId id, TokenPosition begin, TokenPosition end) { + span_ = SourceSpan(std::move(id), begin, end); +} + +void AstNode::UnionSpan(const SourceSpan& other) { + span_ = SourceSpan::Union(span_, other); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/base/AstNode.hpp b/lib/parser/ast/nodes/base/AstNode.hpp new file mode 100644 index 0000000..ab57997 --- /dev/null +++ b/lib/parser/ast/nodes/base/AstNode.hpp @@ -0,0 +1,27 @@ +#ifndef PARSER_ASTNODE_HPP_ +#define PARSER_ASTNODE_HPP_ + +#include "lib/parser/tokens/SourceSpan.hpp" + +namespace ovum::compiler::parser { + +class AstVisitor; // forward + +class AstNode { +public: + virtual ~AstNode() = default; + + const SourceSpan& Span() const noexcept; + void SetSpan(SourceSpan span); + void SetSpanParts(SourceId id, TokenPosition begin, TokenPosition end); + void UnionSpan(const SourceSpan& other); + + virtual void Accept(AstVisitor& visitor) = 0; + +private: + SourceSpan span_{}; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ASTNODE_HPP_ diff --git a/lib/parser/ast/nodes/base/Decl.hpp b/lib/parser/ast/nodes/base/Decl.hpp new file mode 100644 index 0000000..26ac67e --- /dev/null +++ b/lib/parser/ast/nodes/base/Decl.hpp @@ -0,0 +1,12 @@ +#ifndef PARSER_DECL_HPP_ +#define PARSER_DECL_HPP_ + +#include "AstNode.hpp" + +namespace ovum::compiler::parser { + +class Decl : public AstNode {}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_DECL_HPP_ diff --git a/lib/parser/ast/nodes/base/Expr.hpp b/lib/parser/ast/nodes/base/Expr.hpp new file mode 100644 index 0000000..2d1917f --- /dev/null +++ b/lib/parser/ast/nodes/base/Expr.hpp @@ -0,0 +1,12 @@ +#ifndef PARSER_EXPR_HPP_ +#define PARSER_EXPR_HPP_ + +#include "AstNode.hpp" + +namespace ovum::compiler::parser { + +class Expr : public AstNode {}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_EXPR_HPP_ diff --git a/lib/parser/ast/nodes/base/Stmt.hpp b/lib/parser/ast/nodes/base/Stmt.hpp new file mode 100644 index 0000000..19a7b2d --- /dev/null +++ b/lib/parser/ast/nodes/base/Stmt.hpp @@ -0,0 +1,12 @@ +#ifndef PARSER_STMT_HPP_ +#define PARSER_STMT_HPP_ + +#include "AstNode.hpp" + +namespace ovum::compiler::parser { + +class Stmt : public AstNode {}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STMT_HPP_ diff --git a/lib/parser/ast/nodes/builders/base/BuilderTraits.hpp b/lib/parser/ast/nodes/builders/base/BuilderTraits.hpp new file mode 100644 index 0000000..3e762c8 --- /dev/null +++ b/lib/parser/ast/nodes/builders/base/BuilderTraits.hpp @@ -0,0 +1,313 @@ +#ifndef PARSER_BUILDERTRAITS_HPP_ +#define PARSER_BUILDERTRAITS_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.hpp" + +#include "lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.hpp" +#include "lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.hpp" +#include "lib/parser/ast/nodes/builders/decls/ModuleBuilder.hpp" +#include "lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.hpp" + +#include "lib/parser/ast/nodes/builders/exprs/AssignBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/BinaryBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/CallExprBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/CastAsBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/ElvisBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/UnaryBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.hpp" +#include "lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.hpp" + +#include "lib/parser/ast/nodes/builders/stmts/BlockBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.hpp" +#include "lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.hpp" + +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" + +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/decls/GlobalVarDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" +#include "lib/parser/ast/nodes/decls/TypeAliasDecl.hpp" + +#include "lib/parser/ast/nodes/exprs/Assign.hpp" +#include "lib/parser/ast/nodes/exprs/Binary.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" +#include "lib/parser/ast/nodes/exprs/CastAs.hpp" +#include "lib/parser/ast/nodes/exprs/Elvis.hpp" +#include "lib/parser/ast/nodes/exprs/FieldAccess.hpp" +#include "lib/parser/ast/nodes/exprs/IdentRef.hpp" +#include "lib/parser/ast/nodes/exprs/IndexAccess.hpp" +#include "lib/parser/ast/nodes/exprs/NamespaceRef.hpp" +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" +#include "lib/parser/ast/nodes/exprs/TypeTestIs.hpp" +#include "lib/parser/ast/nodes/exprs/Unary.hpp" +#include "lib/parser/ast/nodes/exprs/literals/BoolLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/CharLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/FloatLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/IntLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/NullLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/StringLit.hpp" + +#include "lib/parser/ast/nodes/stmts/BreakStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ContinueStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ExprStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ForStmt.hpp" +#include "lib/parser/ast/nodes/stmts/IfStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ReturnStmt.hpp" +#include "lib/parser/ast/nodes/stmts/UnsafeBlock.hpp" +#include "lib/parser/ast/nodes/stmts/VarDeclStmt.hpp" +#include "lib/parser/ast/nodes/stmts/WhileStmt.hpp" + +namespace ovum::compiler::parser { + +template +struct BuilderFor; + +// Decls +template<> +struct BuilderFor { + using type = ModuleBuilder; +}; + +template<> +struct BuilderFor { + using type = FunctionDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = ClassDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = GlobalVarDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = InterfaceDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = InterfaceMethodBuilder; +}; + +template<> +struct BuilderFor { + using type = TypeAliasDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = FieldDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = StaticFieldDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = MethodDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = CallDeclBuilder; +}; + +template<> +struct BuilderFor { + using type = DestructorDeclBuilder; +}; + +// Stmts +template<> +struct BuilderFor { + using type = BlockBuilder; +}; + +template<> +struct BuilderFor { + using type = BreakStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = ContinueStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = ExprStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = ForStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = IfStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = ReturnStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = UnsafeBlockBuilder; +}; + +template<> +struct BuilderFor { + using type = VarDeclStmtBuilder; +}; + +template<> +struct BuilderFor { + using type = WhileStmtBuilder; +}; + +// Exprs +template<> +struct BuilderFor { + using type = AssignBuilder; +}; + +template<> +struct BuilderFor { + using type = BinaryBuilder; +}; + +template<> +struct BuilderFor { + using type = CallExprBuilder; +}; + +template<> +struct BuilderFor { + using type = CastAsBuilder; +}; + +template<> +struct BuilderFor { + using type = ElvisBuilder; +}; + +template<> +struct BuilderFor { + using type = FieldAccessBuilder; +}; + +template<> +struct BuilderFor { + using type = IdentRefBuilder; +}; + +template<> +struct BuilderFor { + using type = IndexAccessBuilder; +}; + +template<> +struct BuilderFor { + using type = NamespaceRefBuilder; +}; + +template<> +struct BuilderFor { + using type = SafeCallBuilder; +}; + +template<> +struct BuilderFor { + using type = TypeTestIsBuilder; +}; + +template<> +struct BuilderFor { + using type = UnaryBuilder; +}; + +// Literals +template<> +struct BuilderFor { + using type = BoolLitBuilder; +}; + +template<> +struct BuilderFor { + using type = CharLitBuilder; +}; + +template<> +struct BuilderFor { + using type = FloatLitBuilder; +}; + +template<> +struct BuilderFor { + using type = IntLitBuilder; +}; + +template<> +struct BuilderFor { + using type = NullLitBuilder; +}; + +template<> +struct BuilderFor { + using type = StringLitBuilder; +}; + +template +struct HasBuilder : std::false_type {}; + +template +struct HasBuilder::type>> : std::true_type {}; + +template +inline constexpr bool kHasBuilderV = HasBuilder::value; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BUILDERTRAITS_HPP_ diff --git a/lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp b/lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp new file mode 100644 index 0000000..e94d561 --- /dev/null +++ b/lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp @@ -0,0 +1,44 @@ +#ifndef PARSER_NODEBUILDERBASE_HPP_ +#define PARSER_NODEBUILDERBASE_HPP_ + +#include + +#include "TokenPosition.hpp" +#include "lib/parser/tokens/SourceId.hpp" +#include "lib/parser/tokens/SourceSpan.hpp" + +namespace ovum::compiler::parser { + +template +class NodeBuilderBase { +public: + NodeBuilderBase() : node_(std::make_unique()) { + } + + explicit NodeBuilderBase(std::unique_ptr node) : node_(std::move(node)) { + } + + NodeBuilderBase& WithSpan(const SourceSpan& span) { + node_->SetSpan(span); + return *this; + } + + NodeBuilderBase& WithSpanParts(SourceId id, TokenPosition begin, TokenPosition end) { + node_->SetSpanParts(std::move(id), begin, end); + return *this; + } + + std::unique_ptr Finish() { + return std::move(node_); + } + + T* Raw() { + return node_.get(); + } + +protected: + std::unique_ptr node_; +}; +} // namespace ovum::compiler::parser + +#endif // PARSER_NODEBUILDERBASE_HPP_ diff --git a/lib/parser/ast/nodes/builders/base/ParserBuilder.hpp b/lib/parser/ast/nodes/builders/base/ParserBuilder.hpp new file mode 100644 index 0000000..a55951f --- /dev/null +++ b/lib/parser/ast/nodes/builders/base/ParserBuilder.hpp @@ -0,0 +1,24 @@ +#ifndef PARSER_PARSERBUILDER_HPP_ +#define PARSER_PARSERBUILDER_HPP_ + +#include "BuilderTraits.hpp" + +namespace ovum::compiler::parser { + +class ParserBuilder { +public: + ParserBuilder() = delete; + + template + using BuilderType = typename BuilderFor::type; + + template + static BuilderType Make() { + static_assert(kHasBuilderV, "No builder registered for this AST node type"); + return BuilderType{}; + } +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_PARSERBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.cpp b/lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.cpp new file mode 100644 index 0000000..534b914 --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.cpp @@ -0,0 +1,25 @@ +#include "CallDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +CallDeclBuilder& CallDeclBuilder::WithPublic(bool is_public) { + node_->SetPublic(is_public); + return *this; +} + +CallDeclBuilder& CallDeclBuilder::AddParam(Param parameter) { + node_->MutableParams().push_back(std::move(parameter)); + return *this; +} + +CallDeclBuilder& CallDeclBuilder::WithReturnType(std::unique_ptr type) { + node_->SetReturnType(std::move(type)); + return *this; +} + +CallDeclBuilder& CallDeclBuilder::WithBody(std::unique_ptr body) { + node_->SetBody(std::move(body)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.hpp b/lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.hpp new file mode 100644 index 0000000..da0e58e --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/CallDeclBuilder.hpp @@ -0,0 +1,24 @@ +#ifndef PARSER_CALLDECLBUILDER_HPP_ +#define PARSER_CALLDECLBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/types/Param.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class CallDeclBuilder : public NodeBuilderBase { +public: + CallDeclBuilder& WithPublic(bool is_public); + CallDeclBuilder& AddParam(Param parameter); + CallDeclBuilder& WithReturnType(std::unique_ptr type); + CallDeclBuilder& WithBody(std::unique_ptr body); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CALLDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.cpp b/lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.cpp new file mode 100644 index 0000000..471399e --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.cpp @@ -0,0 +1,15 @@ +#include "DestructorDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +DestructorDeclBuilder& DestructorDeclBuilder::WithPublic(bool is_public) { + node_->SetPublic(is_public); + return *this; +} + +DestructorDeclBuilder& DestructorDeclBuilder::WithBody(std::unique_ptr body) { + node_->SetBody(std::move(body)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.hpp b/lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.hpp new file mode 100644 index 0000000..cfeb5d1 --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/DestructorDeclBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_DESTRUCTORDECLBUILDER_HPP_ +#define PARSER_DESTRUCTORDECLBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" + +namespace ovum::compiler::parser { + +class DestructorDeclBuilder : public NodeBuilderBase { +public: + DestructorDeclBuilder& WithPublic(bool is_public); + DestructorDeclBuilder& WithBody(std::unique_ptr body); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_DESTRUCTORDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.cpp b/lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.cpp new file mode 100644 index 0000000..b4162a9 --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.cpp @@ -0,0 +1,30 @@ +#include "FieldDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +FieldDeclBuilder& FieldDeclBuilder::WithPublic(bool is_public) { + node_->SetPublic(is_public); + return *this; +} + +FieldDeclBuilder& FieldDeclBuilder::WithVar(bool is_var) { + node_->SetVar(is_var); + return *this; +} + +FieldDeclBuilder& FieldDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +FieldDeclBuilder& FieldDeclBuilder::WithType(TypeReference type) { + node_->SetType(std::move(type)); + return *this; +} + +FieldDeclBuilder& FieldDeclBuilder::WithInit(std::unique_ptr init) { + node_->SetInit(std::move(init)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.hpp b/lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.hpp new file mode 100644 index 0000000..78c981b --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/FieldDeclBuilder.hpp @@ -0,0 +1,25 @@ +#ifndef PARSER_FIELDDECLBUILDER_HPP_ +#define PARSER_FIELDDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class FieldDeclBuilder : public NodeBuilderBase { +public: + FieldDeclBuilder& WithPublic(bool is_public); + FieldDeclBuilder& WithVar(bool is_var); + FieldDeclBuilder& WithName(std::string name); + FieldDeclBuilder& WithType(TypeReference type); + FieldDeclBuilder& WithInit(std::unique_ptr init); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FIELDDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.cpp b/lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.cpp new file mode 100644 index 0000000..90ae03d --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.cpp @@ -0,0 +1,45 @@ +#include "MethodDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +MethodDeclBuilder& MethodDeclBuilder::WithPublic(bool is_public) { + node_->SetPublic(is_public); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::WithOverride(bool is_override) { + node_->SetOverride(is_override); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::WithStatic(bool is_static) { + node_->SetStatic(is_static); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::WithPure(bool is_pure) { + node_->SetPure(is_pure); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::AddParam(Param parameter) { + node_->MutableParams().push_back(std::move(parameter)); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::WithReturnType(std::unique_ptr type) { + node_->SetReturnType(std::move(type)); + return *this; +} + +MethodDeclBuilder& MethodDeclBuilder::WithBody(std::unique_ptr body) { + node_->SetBody(std::move(body)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.hpp b/lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.hpp new file mode 100644 index 0000000..30522ed --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/MethodDeclBuilder.hpp @@ -0,0 +1,29 @@ +#ifndef PARSER_METHODDECLBUILDER_HPP_ +#define PARSER_METHODDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/types/Param.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class MethodDeclBuilder : public NodeBuilderBase { +public: + MethodDeclBuilder& WithPublic(bool is_public); + MethodDeclBuilder& WithOverride(bool is_override); + MethodDeclBuilder& WithStatic(bool is_static); + MethodDeclBuilder& WithPure(bool is_pure); + MethodDeclBuilder& WithName(std::string name); + MethodDeclBuilder& AddParam(Param parameter); + MethodDeclBuilder& WithReturnType(std::unique_ptr type); + MethodDeclBuilder& WithBody(std::unique_ptr body); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_METHODDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.cpp b/lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.cpp new file mode 100644 index 0000000..d27ed7f --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.cpp @@ -0,0 +1,30 @@ +#include "StaticFieldDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +StaticFieldDeclBuilder& StaticFieldDeclBuilder::WithPublic(bool is_public) { + node_->SetPublic(is_public); + return *this; +} + +StaticFieldDeclBuilder& StaticFieldDeclBuilder::WithVar(bool is_var) { + node_->SetVar(is_var); + return *this; +} + +StaticFieldDeclBuilder& StaticFieldDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +StaticFieldDeclBuilder& StaticFieldDeclBuilder::WithType(TypeReference type) { + node_->SetType(std::move(type)); + return *this; +} + +StaticFieldDeclBuilder& StaticFieldDeclBuilder::WithInit(std::unique_ptr init) { + node_->SetInit(std::move(init)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.hpp b/lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.hpp new file mode 100644 index 0000000..4efe233 --- /dev/null +++ b/lib/parser/ast/nodes/builders/class_members/StaticFieldDeclBuilder.hpp @@ -0,0 +1,24 @@ +#ifndef PARSER_STATICFIELDDECLBUILDER_HPP_ +#define PARSER_STATICFIELDDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class StaticFieldDeclBuilder : public NodeBuilderBase { +public: + StaticFieldDeclBuilder& WithPublic(bool is_public); + StaticFieldDeclBuilder& WithVar(bool is_var); + StaticFieldDeclBuilder& WithName(std::string name); + StaticFieldDeclBuilder& WithType(TypeReference type); + StaticFieldDeclBuilder& WithInit(std::unique_ptr init); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATICFIELDDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.cpp b/lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.cpp new file mode 100644 index 0000000..d06eafe --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.cpp @@ -0,0 +1,20 @@ +#include "ClassDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +ClassDeclBuilder& ClassDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +ClassDeclBuilder& ClassDeclBuilder::AddImplements(TypeReference iface) { + node_->MutableImplements().push_back(std::move(iface)); + return *this; +} + +ClassDeclBuilder& ClassDeclBuilder::AddMember(std::unique_ptr member) { + node_->MutableMembers().push_back(std::move(member)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.hpp b/lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.hpp new file mode 100644 index 0000000..421bd2f --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/ClassDeclBuilder.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_CLASSDECLBUILDER_HPP_ +#define PARSER_CLASSDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class ClassDeclBuilder : public NodeBuilderBase { +public: + ClassDeclBuilder& WithName(std::string name); + ClassDeclBuilder& AddImplements(TypeReference iface); + ClassDeclBuilder& AddMember(std::unique_ptr member); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CLASSDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.cpp b/lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.cpp new file mode 100644 index 0000000..6360f47 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.cpp @@ -0,0 +1,30 @@ +#include "FunctionDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +FunctionDeclBuilder& FunctionDeclBuilder::WithPure(bool is_pure) { + node_->SetPure(is_pure); + return *this; +} + +FunctionDeclBuilder& FunctionDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +FunctionDeclBuilder& FunctionDeclBuilder::AddParam(Param parameter) { + node_->MutableParams().push_back(std::move(parameter)); + return *this; +} + +FunctionDeclBuilder& FunctionDeclBuilder::WithReturnType(std::unique_ptr type) { + node_->SetReturnType(std::move(type)); + return *this; +} + +FunctionDeclBuilder& FunctionDeclBuilder::WithBody(std::unique_ptr body) { + node_->SetBody(std::move(body)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.hpp b/lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.hpp new file mode 100644 index 0000000..052d993 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/FunctionDeclBuilder.hpp @@ -0,0 +1,26 @@ +#ifndef PARSER_FUNCTIONDECLBUILDER_HPP_ +#define PARSER_FUNCTIONDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/types/Param.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class FunctionDeclBuilder : public NodeBuilderBase { +public: + FunctionDeclBuilder& WithPure(bool is_pure); + FunctionDeclBuilder& WithName(std::string name); + FunctionDeclBuilder& AddParam(Param parameter); + FunctionDeclBuilder& WithReturnType(std::unique_ptr type); + FunctionDeclBuilder& WithBody(std::unique_ptr body); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FUNCTIONDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.cpp b/lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.cpp new file mode 100644 index 0000000..0f292ba --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.cpp @@ -0,0 +1,25 @@ +#include "GlobalVarDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +GlobalVarDeclBuilder& GlobalVarDeclBuilder::WithVar(bool is_var) { + node_->SetVar(is_var); + return *this; +} + +GlobalVarDeclBuilder& GlobalVarDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +GlobalVarDeclBuilder& GlobalVarDeclBuilder::WithType(TypeReference type) { + node_->SetType(std::move(type)); + return *this; +} + +GlobalVarDeclBuilder& GlobalVarDeclBuilder::WithInit(std::unique_ptr init) { + node_->SetInit(std::move(init)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.hpp b/lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.hpp new file mode 100644 index 0000000..1f5cc4a --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/GlobalVarDeclBuilder.hpp @@ -0,0 +1,24 @@ +#ifndef PARSER_GLOBALVARDECLBUILDER_HPP_ +#define PARSER_GLOBALVARDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/GlobalVarDecl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class GlobalVarDeclBuilder : public NodeBuilderBase { +public: + GlobalVarDeclBuilder& WithVar(bool is_var); + GlobalVarDeclBuilder& WithName(std::string name); + GlobalVarDeclBuilder& WithType(TypeReference type); + GlobalVarDeclBuilder& WithInit(std::unique_ptr init); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_GLOBALVARDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.cpp b/lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.cpp new file mode 100644 index 0000000..80dc0b9 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.cpp @@ -0,0 +1,15 @@ +#include "InterfaceDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +InterfaceDeclBuilder& InterfaceDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +InterfaceDeclBuilder& InterfaceDeclBuilder::AddMethod(std::unique_ptr method) { + node_->MutableMembers().push_back(std::move(method)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.hpp b/lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.hpp new file mode 100644 index 0000000..eb7b68b --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/InterfaceDeclBuilder.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_INTERFACEDECLBUILDER_HPP_ +#define PARSER_INTERFACEDECLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" + +namespace ovum::compiler::parser { + +class InterfaceDeclBuilder : public NodeBuilderBase { +public: + InterfaceDeclBuilder& WithName(std::string name); + InterfaceDeclBuilder& AddMethod(std::unique_ptr method); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INTERFACEDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.cpp b/lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.cpp new file mode 100644 index 0000000..27ea020 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.cpp @@ -0,0 +1,20 @@ +#include "InterfaceMethodBuilder.hpp" + +namespace ovum::compiler::parser { + +InterfaceMethodBuilder& InterfaceMethodBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +InterfaceMethodBuilder& InterfaceMethodBuilder::AddParam(InterfaceMethod::Param parameter) { + node_->MutableParams().push_back(std::move(parameter)); + return *this; +} + +InterfaceMethodBuilder& InterfaceMethodBuilder::WithReturnType(std::unique_ptr type) { + node_->SetReturnType(std::move(type)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.hpp b/lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.hpp new file mode 100644 index 0000000..6cace50 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/InterfaceMethodBuilder.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_INTERFACEMETHODBUILDER_HPP_ +#define PARSER_INTERFACEMETHODBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class InterfaceMethodBuilder : public NodeBuilderBase { +public: + InterfaceMethodBuilder& WithName(std::string name); + InterfaceMethodBuilder& AddParam(InterfaceMethod::Param parameter); + InterfaceMethodBuilder& WithReturnType(std::unique_ptr type); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INTERFACEMETHODBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/ModuleBuilder.cpp b/lib/parser/ast/nodes/builders/decls/ModuleBuilder.cpp new file mode 100644 index 0000000..3c9c23b --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/ModuleBuilder.cpp @@ -0,0 +1,20 @@ +#include "ModuleBuilder.hpp" + +namespace ovum::compiler::parser { + +ModuleBuilder& ModuleBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +ModuleBuilder& ModuleBuilder::WithSource(SourceId id) { + node_->SetSource(std::move(id)); + return *this; +} + +ModuleBuilder& ModuleBuilder::AddDecl(std::unique_ptr declaration) { + node_->AddDecl(std::move(declaration)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/ModuleBuilder.hpp b/lib/parser/ast/nodes/builders/decls/ModuleBuilder.hpp new file mode 100644 index 0000000..c813d62 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/ModuleBuilder.hpp @@ -0,0 +1,23 @@ +#ifndef PARSER_MODULEBUILDER_HPP_ +#define PARSER_MODULEBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" +#include "lib/parser/tokens/SourceId.hpp" + +namespace ovum::compiler::parser { + +class ModuleBuilder : public NodeBuilderBase { +public: + ModuleBuilder& WithName(std::string name); + ModuleBuilder& WithSource(SourceId id); + ModuleBuilder& AddDecl(std::unique_ptr declaration); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MODULEBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.cpp b/lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.cpp new file mode 100644 index 0000000..7d1db13 --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.cpp @@ -0,0 +1,15 @@ +#include "TypeAliasDeclBuilder.hpp" + +namespace ovum::compiler::parser { + +TypeAliasDeclBuilder& TypeAliasDeclBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +TypeAliasDeclBuilder& TypeAliasDeclBuilder::WithAliasedType(TypeReference type) { + node_->SetAliasedType(std::move(type)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.hpp b/lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.hpp new file mode 100644 index 0000000..4a76dde --- /dev/null +++ b/lib/parser/ast/nodes/builders/decls/TypeAliasDeclBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_TYPEALIASDECLBUILDER_HPP_ +#define PARSER_TYPEALIASDECLBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/decls/TypeAliasDecl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class TypeAliasDeclBuilder : public NodeBuilderBase { +public: + TypeAliasDeclBuilder& WithName(std::string name); + TypeAliasDeclBuilder& WithAliasedType(TypeReference type); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_TYPEALIASDECLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/AssignBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/AssignBuilder.cpp new file mode 100644 index 0000000..31fe680 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/AssignBuilder.cpp @@ -0,0 +1,20 @@ +#include "AssignBuilder.hpp" + +namespace ovum::compiler::parser { + +AssignBuilder& AssignBuilder::WithKind(const IAssignOpTag& kind) { + node_->SetKind(kind); + return *this; +} + +AssignBuilder& AssignBuilder::WithTarget(std::unique_ptr target) { + node_->SetTarget(std::move(target)); + return *this; +} + +AssignBuilder& AssignBuilder::WithValue(std::unique_ptr value) { + node_->SetValue(std::move(value)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/AssignBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/AssignBuilder.hpp new file mode 100644 index 0000000..8515f87 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/AssignBuilder.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_ASSIGNBUILDER_HPP_ +#define PARSER_ASSIGNBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/Assign.hpp" +#include "lib/parser/ast/nodes/exprs/tags/IAssignOpTag.hpp" + +namespace ovum::compiler::parser { + +class AssignBuilder : public NodeBuilderBase { +public: + AssignBuilder& WithKind(const IAssignOpTag& kind); + AssignBuilder& WithTarget(std::unique_ptr target); + AssignBuilder& WithValue(std::unique_ptr value); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ASSIGNBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/BinaryBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/BinaryBuilder.cpp new file mode 100644 index 0000000..85a4ab3 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/BinaryBuilder.cpp @@ -0,0 +1,20 @@ +#include "BinaryBuilder.hpp" + +namespace ovum::compiler::parser { + +BinaryBuilder& BinaryBuilder::WithOp(const IBinaryOpTag& op) { + node_->SetOp(op); + return *this; +} + +BinaryBuilder& BinaryBuilder::WithLhs(std::unique_ptr lhs) { + node_->SetLhs(std::move(lhs)); + return *this; +} + +BinaryBuilder& BinaryBuilder::WithRhs(std::unique_ptr rhs) { + node_->SetRhs(std::move(rhs)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/BinaryBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/BinaryBuilder.hpp new file mode 100644 index 0000000..5c401d1 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/BinaryBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_BINARYBUILDER_HPP_ +#define PARSER_BINARYBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/Binary.hpp" + +namespace ovum::compiler::parser { + +class BinaryBuilder : public NodeBuilderBase { +public: + BinaryBuilder& WithOp(const IBinaryOpTag& op); + BinaryBuilder& WithLhs(std::unique_ptr lhs); + BinaryBuilder& WithRhs(std::unique_ptr rhs); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BINARYBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/CallExprBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/CallExprBuilder.cpp new file mode 100644 index 0000000..8889044 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/CallExprBuilder.cpp @@ -0,0 +1,15 @@ +#include "CallExprBuilder.hpp" + +namespace ovum::compiler::parser { + +CallExprBuilder& CallExprBuilder::WithCallee(std::unique_ptr callee) { + node_->SetCallee(std::move(callee)); + return *this; +} + +CallExprBuilder& CallExprBuilder::AddArg(std::unique_ptr argument) { + node_->AddArg(std::move(argument)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/CallExprBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/CallExprBuilder.hpp new file mode 100644 index 0000000..abbc118 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/CallExprBuilder.hpp @@ -0,0 +1,19 @@ +#ifndef PARSER_CALLEXPRBUILDER_HPP_ +#define PARSER_CALLEXPRBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" + +namespace ovum::compiler::parser { + +class CallExprBuilder : public NodeBuilderBase { +public: + CallExprBuilder& WithCallee(std::unique_ptr callee); + CallExprBuilder& AddArg(std::unique_ptr argument); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CALLEXPRBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/CastAsBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/CastAsBuilder.cpp new file mode 100644 index 0000000..f9bcb73 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/CastAsBuilder.cpp @@ -0,0 +1,15 @@ +#include "CastAsBuilder.hpp" + +namespace ovum::compiler::parser { + +CastAsBuilder& CastAsBuilder::WithExpr(std::unique_ptr expression) { + node_->SetExpression(std::move(expression)); + return *this; +} + +CastAsBuilder& CastAsBuilder::WithType(TypeReference type) { + node_->SetType(std::move(type)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/CastAsBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/CastAsBuilder.hpp new file mode 100644 index 0000000..d821e19 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/CastAsBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_CASTASBUILDER_HPP_ +#define PARSER_CASTASBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/CastAs.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class CastAsBuilder : public NodeBuilderBase { +public: + CastAsBuilder& WithExpr(std::unique_ptr expression); + CastAsBuilder& WithType(TypeReference type); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CASTASBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/ElvisBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/ElvisBuilder.cpp new file mode 100644 index 0000000..4e85dd9 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/ElvisBuilder.cpp @@ -0,0 +1,15 @@ +#include "ElvisBuilder.hpp" + +namespace ovum::compiler::parser { + +ElvisBuilder& ElvisBuilder::WithLhs(std::unique_ptr lhs) { + node_->SetLhs(std::move(lhs)); + return *this; +} + +ElvisBuilder& ElvisBuilder::WithRhs(std::unique_ptr rhs) { + node_->SetRhs(std::move(rhs)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/ElvisBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/ElvisBuilder.hpp new file mode 100644 index 0000000..27a5267 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/ElvisBuilder.hpp @@ -0,0 +1,19 @@ +#ifndef PARSER_ELVISBUILDER_HPP_ +#define PARSER_ELVISBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/Elvis.hpp" + +namespace ovum::compiler::parser { + +class ElvisBuilder : public NodeBuilderBase { +public: + ElvisBuilder& WithLhs(std::unique_ptr lhs); + ElvisBuilder& WithRhs(std::unique_ptr rhs); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ELVISBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.cpp new file mode 100644 index 0000000..2c3419b --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.cpp @@ -0,0 +1,15 @@ +#include "FieldAccessBuilder.hpp" + +namespace ovum::compiler::parser { + +FieldAccessBuilder& FieldAccessBuilder::WithObject(std::unique_ptr object) { + node_->SetObject(std::move(object)); + return *this; +} + +FieldAccessBuilder& FieldAccessBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.hpp new file mode 100644 index 0000000..3822db0 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/FieldAccessBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_FIELDACCESSBUILDER_HPP_ +#define PARSER_FIELDACCESSBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/FieldAccess.hpp" + +namespace ovum::compiler::parser { + +class FieldAccessBuilder : public NodeBuilderBase { +public: + FieldAccessBuilder& WithObject(std::unique_ptr object); + FieldAccessBuilder& WithName(std::string name); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FIELDACCESSBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.cpp new file mode 100644 index 0000000..8b586d9 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.cpp @@ -0,0 +1,10 @@ +#include "IdentRefBuilder.hpp" + +namespace ovum::compiler::parser { + +IdentRefBuilder& IdentRefBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.hpp new file mode 100644 index 0000000..f8d6710 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/IdentRefBuilder.hpp @@ -0,0 +1,18 @@ +#ifndef PARSER_IDENTREFBUILDER_HPP_ +#define PARSER_IDENTREFBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/IdentRef.hpp" + +namespace ovum::compiler::parser { + +class IdentRefBuilder : public NodeBuilderBase { +public: + IdentRefBuilder& WithName(std::string name); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IDENTREFBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.cpp new file mode 100644 index 0000000..d809b5e --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.cpp @@ -0,0 +1,15 @@ +#include "IndexAccessBuilder.hpp" + +namespace ovum::compiler::parser { + +IndexAccessBuilder& IndexAccessBuilder::WithObject(std::unique_ptr object) { + node_->SetObject(std::move(object)); + return *this; +} + +IndexAccessBuilder& IndexAccessBuilder::WithIndex(std::unique_ptr index_expr) { + node_->SetIndexExpr(std::move(index_expr)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.hpp new file mode 100644 index 0000000..c8836ab --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/IndexAccessBuilder.hpp @@ -0,0 +1,19 @@ +#ifndef PARSER_INDEXACCESSBUILDER_HPP_ +#define PARSER_INDEXACCESSBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/IndexAccess.hpp" + +namespace ovum::compiler::parser { + +class IndexAccessBuilder : public NodeBuilderBase { +public: + IndexAccessBuilder& WithObject(std::unique_ptr object); + IndexAccessBuilder& WithIndex(std::unique_ptr index_expr); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INDEXACCESSBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.cpp new file mode 100644 index 0000000..553a87d --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.cpp @@ -0,0 +1,15 @@ +#include "NamespaceRefBuilder.hpp" + +namespace ovum::compiler::parser { + +NamespaceRefBuilder& NamespaceRefBuilder::WithNamespace(std::unique_ptr ns) { + node_->SetNamespaceExpr(std::move(ns)); + return *this; +} + +NamespaceRefBuilder& NamespaceRefBuilder::WithName(std::string name) { + node_->SetName(std::move(name)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.hpp new file mode 100644 index 0000000..7c15f88 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/NamespaceRefBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_NAMESPACEREFBUILDER_HPP_ +#define PARSER_NAMESPACEREFBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/NamespaceRef.hpp" + +namespace ovum::compiler::parser { + +class NamespaceRefBuilder : public NodeBuilderBase { +public: + NamespaceRefBuilder& WithNamespace(std::unique_ptr ns); + NamespaceRefBuilder& WithName(std::string name); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_NAMESPACEREFBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.cpp new file mode 100644 index 0000000..4f69aaf --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.cpp @@ -0,0 +1,25 @@ +#include "SafeCallBuilder.hpp" + +namespace ovum::compiler::parser { + +SafeCallBuilder& SafeCallBuilder::WithObject(std::unique_ptr object) { + node_->SetObject(std::move(object)); + return *this; +} + +SafeCallBuilder& SafeCallBuilder::WithMethod(std::string method) { + node_->SetMethod(std::move(method)); + return *this; +} + +SafeCallBuilder& SafeCallBuilder::AddArg(std::unique_ptr argument) { + node_->AddArg(std::move(argument)); + return *this; +} + +SafeCallBuilder& SafeCallBuilder::ClearArgs() { + node_->ClearArgs(); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.hpp new file mode 100644 index 0000000..7854d1a --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/SafeCallBuilder.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_SAFECALLBUILDER_HPP_ +#define PARSER_SAFECALLBUILDER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" + +namespace ovum::compiler::parser { + +class SafeCallBuilder : public NodeBuilderBase { +public: + SafeCallBuilder& WithObject(std::unique_ptr object); + SafeCallBuilder& WithMethod(std::string method); + SafeCallBuilder& AddArg(std::unique_ptr argument); + SafeCallBuilder& ClearArgs(); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_SAFECALLBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.cpp new file mode 100644 index 0000000..de95fac --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.cpp @@ -0,0 +1,15 @@ +#include "TypeTestIsBuilder.hpp" + +namespace ovum::compiler::parser { + +TypeTestIsBuilder& TypeTestIsBuilder::WithExpr(std::unique_ptr expression) { + node_->SetExpression(std::move(expression)); + return *this; +} + +TypeTestIsBuilder& TypeTestIsBuilder::WithType(TypeReference type) { + node_->SetType(std::move(type)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.hpp new file mode 100644 index 0000000..54f4436 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/TypeTestIsBuilder.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_TYPETESTISBUILDER_HPP_ +#define PARSER_TYPETESTISBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/TypeTestIs.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class TypeTestIsBuilder : public NodeBuilderBase { +public: + TypeTestIsBuilder& WithExpr(std::unique_ptr expression); + TypeTestIsBuilder& WithType(TypeReference type); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_TYPETESTISBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/UnaryBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/UnaryBuilder.cpp new file mode 100644 index 0000000..e9dd79e --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/UnaryBuilder.cpp @@ -0,0 +1,15 @@ +#include "UnaryBuilder.hpp" + +namespace ovum::compiler::parser { + +UnaryBuilder& UnaryBuilder::WithOp(const IUnaryOpTag& op) { + node_->SetOp(op); + return *this; +} + +UnaryBuilder& UnaryBuilder::WithOperand(std::unique_ptr operand) { + node_->SetOperand(std::move(operand)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/UnaryBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/UnaryBuilder.hpp new file mode 100644 index 0000000..f397133 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/UnaryBuilder.hpp @@ -0,0 +1,19 @@ +#ifndef PARSER_UNARYBUILDER_HPP_ +#define PARSER_UNARYBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/Unary.hpp" + +namespace ovum::compiler::parser { + +class UnaryBuilder : public NodeBuilderBase { +public: + UnaryBuilder& WithOp(const IUnaryOpTag& op); + UnaryBuilder& WithOperand(std::unique_ptr operand); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_UNARYBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.cpp new file mode 100644 index 0000000..50f2f0e --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.cpp @@ -0,0 +1,10 @@ +#include "BoolLitBuilder.hpp" + +namespace ovum::compiler::parser { + +BoolLitBuilder& BoolLitBuilder::WithValue(bool value) { + node_->SetValue(value); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.hpp new file mode 100644 index 0000000..663e072 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/BoolLitBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_BOOLLITBUILDER_HPP_ +#define PARSER_BOOLLITBUILDER_HPP_ + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/literals/BoolLit.hpp" + +namespace ovum::compiler::parser { + +class BoolLitBuilder : public NodeBuilderBase { +public: + BoolLitBuilder& WithValue(bool value); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BOOLLITBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.cpp new file mode 100644 index 0000000..b62f3ee --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.cpp @@ -0,0 +1,10 @@ +#include "CharLitBuilder.hpp" + +namespace ovum::compiler::parser { + +CharLitBuilder& CharLitBuilder::WithValue(char value) { + node_->SetValue(value); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.hpp new file mode 100644 index 0000000..1e3f303 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/CharLitBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_CHARLITBUILDER_HPP_ +#define PARSER_CHARLITBUILDER_HPP_ + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/literals/CharLit.hpp" + +namespace ovum::compiler::parser { + +class CharLitBuilder : public NodeBuilderBase { +public: + CharLitBuilder& WithValue(char value); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CHARLITBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.cpp new file mode 100644 index 0000000..1c82cb8 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.cpp @@ -0,0 +1,10 @@ +#include "FloatLitBuilder.hpp" + +namespace ovum::compiler::parser { + +FloatLitBuilder& FloatLitBuilder::WithValue(double value) { + node_->SetValue(value); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.hpp new file mode 100644 index 0000000..5bae0a2 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/FloatLitBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_FLOATLITBUILDER_HPP_ +#define PARSER_FLOATLITBUILDER_HPP_ + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/literals/FloatLit.hpp" + +namespace ovum::compiler::parser { + +class FloatLitBuilder : public NodeBuilderBase { +public: + FloatLitBuilder& WithValue(double value); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FLOATLITBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.cpp new file mode 100644 index 0000000..386b960 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.cpp @@ -0,0 +1,10 @@ +#include "IntLitBuilder.hpp" + +namespace ovum::compiler::parser { + +IntLitBuilder& IntLitBuilder::WithValue(long long value) { + node_->SetValue(value); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.hpp new file mode 100644 index 0000000..fb9171a --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/IntLitBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_INTLITBUILDER_HPP_ +#define PARSER_INTLITBUILDER_HPP_ + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/literals/IntLit.hpp" + +namespace ovum::compiler::parser { + +class IntLitBuilder : public NodeBuilderBase { +public: + IntLitBuilder& WithValue(long long value); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INTLITBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.cpp new file mode 100644 index 0000000..5152319 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.cpp @@ -0,0 +1,9 @@ +#include "NullLitBuilder.hpp" + +namespace ovum::compiler::parser { + +NullLitBuilder& NullLitBuilder::Noop() { + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.hpp new file mode 100644 index 0000000..fa26b81 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/NullLitBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_NULLLITBUILDER_HPP_ +#define PARSER_NULLLITBUILDER_HPP_ + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/literals/NullLit.hpp" + +namespace ovum::compiler::parser { + +class NullLitBuilder : public NodeBuilderBase { +public: + NullLitBuilder& Noop(); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_NULLLITBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.cpp b/lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.cpp new file mode 100644 index 0000000..02d018b --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.cpp @@ -0,0 +1,10 @@ +#include "StringLitBuilder.hpp" + +namespace ovum::compiler::parser { + +StringLitBuilder& StringLitBuilder::WithValue(std::string value) { + node_->SetValue(std::move(value)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.hpp b/lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.hpp new file mode 100644 index 0000000..8e93528 --- /dev/null +++ b/lib/parser/ast/nodes/builders/exprs/literals/StringLitBuilder.hpp @@ -0,0 +1,19 @@ +#ifndef PARSER_STRINGLITBUILDER_HPP_ +#define PARSER_STRINGLITBUILDER_HPP_ + +#include + +#include "NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/exprs/literals/StringLit.hpp" + +namespace ovum::compiler::parser { + +class StringLitBuilder : public NodeBuilderBase { +public: + StringLitBuilder& WithValue(std::string value); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STRINGLITBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/BlockBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/BlockBuilder.cpp new file mode 100644 index 0000000..03f71ab --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/BlockBuilder.cpp @@ -0,0 +1,10 @@ +#include "BlockBuilder.hpp" + +namespace ovum::compiler::parser { + +BlockBuilder& BlockBuilder::Append(std::unique_ptr statement) { + node_->Append(std::move(statement)); + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/stmts/BlockBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/BlockBuilder.hpp new file mode 100644 index 0000000..376f6b3 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/BlockBuilder.hpp @@ -0,0 +1,18 @@ +#ifndef PARSER_BLOCKBUILDER_HPP_ +#define PARSER_BLOCKBUILDER_HPP_ + +#include + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" + +namespace ovum::compiler::parser { + +class BlockBuilder : public NodeBuilderBase { +public: + BlockBuilder& Append(std::unique_ptr statement); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BLOCKBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.cpp new file mode 100644 index 0000000..9b8b08f --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.cpp @@ -0,0 +1,9 @@ +#include "BreakStmtBuilder.hpp" + +namespace ovum::compiler::parser { + +BreakStmtBuilder& BreakStmtBuilder::Noop() { + return *this; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.hpp new file mode 100644 index 0000000..a5feab6 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/BreakStmtBuilder.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_BREAKSTMTBUILDER_HPP_ +#define PARSER_BREAKSTMTBUILDER_HPP_ + +#include "lib/parser/ast/nodes/builders/base/NodeBuilderBase.hpp" +#include "lib/parser/ast/nodes/stmts/BreakStmt.hpp" + +namespace ovum::compiler::parser { + +class BreakStmtBuilder : public NodeBuilderBase { +public: + BreakStmtBuilder& Noop(); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BREAKSTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.cpp new file mode 100644 index 0000000..a39f896 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.cpp @@ -0,0 +1 @@ +#include "ContinueStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.hpp new file mode 100644 index 0000000..4adb7b1 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ContinueStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef CONTINUESTMTBUILDER_HPP_ +#define CONTINUESTMTBUILDER_HPP_ + +class ContinueStmtBuilder { + +}; + +#endif // CONTINUESTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.cpp new file mode 100644 index 0000000..9941111 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.cpp @@ -0,0 +1 @@ +#include "ExprStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.hpp new file mode 100644 index 0000000..81ade8b --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ExprStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef EXPRSTMTBUILDER_HPP_ +#define EXPRSTMTBUILDER_HPP_ + +class ExprStmtBuilder { + +}; + +#endif // EXPRSTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.cpp new file mode 100644 index 0000000..17d1f70 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.cpp @@ -0,0 +1 @@ +#include "ForStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.hpp new file mode 100644 index 0000000..ef868f9 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ForStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef FORSTMTBUILDER_HPP_ +#define FORSTMTBUILDER_HPP_ + +class ForStmtBuilder { + +}; + +#endif // FORSTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.cpp new file mode 100644 index 0000000..58b0b84 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.cpp @@ -0,0 +1 @@ +#include "IfStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.hpp new file mode 100644 index 0000000..20104f4 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/IfStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef IFSTMTBUILDER_HPP_ +#define IFSTMTBUILDER_HPP_ + +class IfStmtBuilder { + +}; + +#endif // IFSTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.cpp new file mode 100644 index 0000000..9bbe233 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.cpp @@ -0,0 +1 @@ +#include "ReturnStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.hpp new file mode 100644 index 0000000..60a96b5 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/ReturnStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef RETURNSTMTBUILDER_HPP_ +#define RETURNSTMTBUILDER_HPP_ + +class ReturnStmtBuilder { + +}; + +#endif // RETURNSTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.cpp new file mode 100644 index 0000000..324bc24 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.cpp @@ -0,0 +1 @@ +#include "UnsafeBlockBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.hpp new file mode 100644 index 0000000..ef010ac --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/UnsafeBlockBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef UNSAFEBLOCKBUILDER_HPP_ +#define UNSAFEBLOCKBUILDER_HPP_ + +class UnsafeBlockBuilder { + +}; + +#endif // UNSAFEBLOCKBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.cpp new file mode 100644 index 0000000..6d2c45a --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.cpp @@ -0,0 +1 @@ +#include "VarDeclStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.hpp new file mode 100644 index 0000000..920ed08 --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/VarDeclStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef VARDECLSTMTBUILDER_HPP_ +#define VARDECLSTMTBUILDER_HPP_ + +class VarDeclStmtBuilder { + +}; + +#endif // VARDECLSTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.cpp b/lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.cpp new file mode 100644 index 0000000..01811ea --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.cpp @@ -0,0 +1 @@ +#include "WhileStmtBuilder.hpp" diff --git a/lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.hpp b/lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.hpp new file mode 100644 index 0000000..173fabd --- /dev/null +++ b/lib/parser/ast/nodes/builders/stmts/WhileStmtBuilder.hpp @@ -0,0 +1,8 @@ +#ifndef WHILESTMTBUILDER_HPP_ +#define WHILESTMTBUILDER_HPP_ + +class WhileStmtBuilder { + +}; + +#endif // WHILESTMTBUILDER_HPP_ diff --git a/lib/parser/ast/nodes/class_members/CallDecl.cpp b/lib/parser/ast/nodes/class_members/CallDecl.cpp new file mode 100644 index 0000000..a84e922 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/CallDecl.cpp @@ -0,0 +1,65 @@ +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void CallDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool CallDecl::IsPublic() const noexcept { + return is_public_; +} + +void CallDecl::SetPublic(bool v) noexcept { + is_public_ = v; +} + +const std::vector& CallDecl::Params() const noexcept { + return params_; +} + +std::vector& CallDecl::MutableParams() noexcept { + return params_; +} + +void CallDecl::AddParam(Param param) { + params_.emplace_back(std::move(param)); +} + +const TypeReference* CallDecl::ReturnType() const noexcept { + return ret_type_.get(); +} + +TypeReference* CallDecl::MutableReturnType() noexcept { + return ret_type_.get(); +} + +void CallDecl::SetReturnType(std::unique_ptr type) { + ret_type_ = std::move(type); +} + +std::unique_ptr CallDecl::ReleaseReturnType() { + return std::move(ret_type_); +} + +const Block* CallDecl::Body() const noexcept { + return body_.get(); +} + +Block* CallDecl::MutableBody() noexcept { + return body_.get(); +} + +void CallDecl::SetBody(std::unique_ptr block) { + body_ = std::move(block); +} + +std::unique_ptr CallDecl::ReleaseBody() { + return std::move(body_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/class_members/CallDecl.hpp b/lib/parser/ast/nodes/class_members/CallDecl.hpp new file mode 100644 index 0000000..6082620 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/CallDecl.hpp @@ -0,0 +1,44 @@ +#ifndef PARSER_CALLDECL_HPP_ +#define PARSER_CALLDECL_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/types/Param.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class CallDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsPublic() const noexcept; + void SetPublic(bool v) noexcept; + + const std::vector& Params() const noexcept; + std::vector& MutableParams() noexcept; + void AddParam(Param param); + + const TypeReference* ReturnType() const noexcept; + TypeReference* MutableReturnType() noexcept; + void SetReturnType(std::unique_ptr type); + std::unique_ptr ReleaseReturnType(); + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr block); + std::unique_ptr ReleaseBody(); + +private: + bool is_public_ = true; + std::vector params_; + std::unique_ptr ret_type_; + std::unique_ptr body_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CALLDECL_HPP_ diff --git a/lib/parser/ast/nodes/class_members/DestructorDecl.cpp b/lib/parser/ast/nodes/class_members/DestructorDecl.cpp new file mode 100644 index 0000000..f965f0a --- /dev/null +++ b/lib/parser/ast/nodes/class_members/DestructorDecl.cpp @@ -0,0 +1,37 @@ +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void DestructorDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool DestructorDecl::IsPublic() const noexcept { + return is_public_; +} + +void DestructorDecl::SetPublic(bool value) noexcept { + is_public_ = value; +} + +const Block* DestructorDecl::Body() const noexcept { + return body_.get(); +} + +Block* DestructorDecl::MutableBody() noexcept { + return body_.get(); +} + +void DestructorDecl::SetBody(std::unique_ptr block) { + body_ = std::move(block); +} + +std::unique_ptr DestructorDecl::ReleaseBody() { + return std::move(body_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/class_members/DestructorDecl.hpp b/lib/parser/ast/nodes/class_members/DestructorDecl.hpp new file mode 100644 index 0000000..24f780a --- /dev/null +++ b/lib/parser/ast/nodes/class_members/DestructorDecl.hpp @@ -0,0 +1,30 @@ +#ifndef PARSER_DESTRUCTORDECL_HPP_ +#define PARSER_DESTRUCTORDECL_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" + +namespace ovum::compiler::parser { + +class DestructorDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsPublic() const noexcept; + void SetPublic(bool value) noexcept; + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr block); + std::unique_ptr ReleaseBody(); + +private: + bool is_public_ = true; + std::unique_ptr body_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_DESTRUCTORDECL_HPP_ diff --git a/lib/parser/ast/nodes/class_members/FieldDecl.cpp b/lib/parser/ast/nodes/class_members/FieldDecl.cpp new file mode 100644 index 0000000..e073caa --- /dev/null +++ b/lib/parser/ast/nodes/class_members/FieldDecl.cpp @@ -0,0 +1,65 @@ +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void FieldDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool FieldDecl::IsPublic() const noexcept { + return is_public_; +} + +void FieldDecl::SetPublic(bool value) noexcept { + is_public_ = value; +} + +bool FieldDecl::IsVar() const noexcept { + return is_var_; +} + +void FieldDecl::SetVar(bool var) noexcept { + is_var_ = var; +} + +const std::string& FieldDecl::Name() const noexcept { + return name_; +} + +void FieldDecl::SetName(std::string name) { + name_ = std::move(name); +} + +const TypeReference& FieldDecl::Type() const noexcept { + return type_; +} + +TypeReference& FieldDecl::MutableType() noexcept { + return type_; +} + +void FieldDecl::SetType(TypeReference type) { + type_ = std::move(type); +} + +const Expr* FieldDecl::Init() const noexcept { + return init_.get(); +} + +Expr* FieldDecl::MutableInit() noexcept { + return init_.get(); +} + +void FieldDecl::SetInit(std::unique_ptr expr) { + init_ = std::move(expr); +} + +std::unique_ptr FieldDecl::ReleaseInit() { + return std::move(init_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/class_members/FieldDecl.hpp b/lib/parser/ast/nodes/class_members/FieldDecl.hpp new file mode 100644 index 0000000..aa63002 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/FieldDecl.hpp @@ -0,0 +1,45 @@ +#ifndef PARSER_FIELDDECL_HPP_ +#define PARSER_FIELDDECL_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class FieldDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsPublic() const noexcept; + void SetPublic(bool value) noexcept; + + bool IsVar() const noexcept; + void SetVar(bool var) noexcept; + + const std::string& Name() const noexcept; + void SetName(std::string name); + + const TypeReference& Type() const noexcept; + TypeReference& MutableType() noexcept; + void SetType(TypeReference type); + + const Expr* Init() const noexcept; + Expr* MutableInit() noexcept; + void SetInit(std::unique_ptr expr); + std::unique_ptr ReleaseInit(); + +private: + bool is_public_ = true; + bool is_var_ = false; + std::string name_; + TypeReference type_; + std::unique_ptr init_; // optional +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FIELDDECL_HPP_ diff --git a/lib/parser/ast/nodes/class_members/MethodDecl.cpp b/lib/parser/ast/nodes/class_members/MethodDecl.cpp new file mode 100644 index 0000000..8689d25 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/MethodDecl.cpp @@ -0,0 +1,96 @@ +#include "lib/parser/ast/AstVisitor.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" + +#include + +namespace ovum::compiler::parser { + +void MethodDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool MethodDecl::IsPublic() const noexcept { + return is_public_; +} + +void MethodDecl::SetPublic(bool is_public) noexcept { + is_public_ = is_public; +} + +bool MethodDecl::IsOverride() const noexcept { + return is_override_; +} + +void MethodDecl::SetOverride(bool is_override) noexcept { + is_override_ = is_override; +} + +bool MethodDecl::IsStatic() const noexcept { + return is_static_; +} + +void MethodDecl::SetStatic(bool is_static) noexcept { + is_static_ = is_static; +} + +bool MethodDecl::IsPure() const noexcept { + return is_pure_; +} + +void MethodDecl::SetPure(bool is_pure) noexcept { + is_pure_ = is_pure; +} + +const std::string& MethodDecl::Name() const noexcept { + return name; +} + +void MethodDecl::SetName(std::string new_name) { + name = std::move(new_name); +} + +const std::vector& MethodDecl::Params() const noexcept { + return params; +} + +std::vector& MethodDecl::MutableParams() noexcept { + return params; +} + +void MethodDecl::AddParam(Param param) { + params.emplace_back(std::move(param)); +} + +const TypeReference* MethodDecl::ReturnType() const noexcept { + return ret_type.get(); +} + +TypeReference* MethodDecl::MutableReturnType() noexcept { + return ret_type.get(); +} + +void MethodDecl::SetReturnType(std::unique_ptr type) { + ret_type = std::move(type); +} + +std::unique_ptr MethodDecl::ReleaseReturnType() { + return std::move(ret_type); +} + +const Block* MethodDecl::Body() const noexcept { + return body.get(); +} + +Block* MethodDecl::MutableBody() noexcept { + return body.get(); +} + +void MethodDecl::SetBody(std::unique_ptr block) { + body = std::move(block); +} + +std::unique_ptr MethodDecl::ReleaseBody() { + return std::move(body); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/class_members/MethodDecl.hpp b/lib/parser/ast/nodes/class_members/MethodDecl.hpp new file mode 100644 index 0000000..7702c00 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/MethodDecl.hpp @@ -0,0 +1,62 @@ +#ifndef PARSER_METHODDECL_HPP_ +#define PARSER_METHODDECL_HPP_ + +#include +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/types/Param.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class MethodDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsPublic() const noexcept; + void SetPublic(bool is_public) noexcept; + + bool IsOverride() const noexcept; + void SetOverride(bool is_override) noexcept; + + bool IsStatic() const noexcept; + void SetStatic(bool is_static) noexcept; + + bool IsPure() const noexcept; + void SetPure(bool is_pure) noexcept; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const std::vector& Params() const noexcept; + std::vector& MutableParams() noexcept; + void AddParam(Param param); + + const TypeReference* ReturnType() const noexcept; + TypeReference* MutableReturnType() noexcept; + void SetReturnType(std::unique_ptr type); + std::unique_ptr ReleaseReturnType(); + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr block); + std::unique_ptr ReleaseBody(); + +private: + bool is_public_ = true; + bool is_override_ = false; + bool is_static_ = false; + bool is_pure_ = false; + + std::string name; + std::vector params; + std::unique_ptr ret_type; + std::unique_ptr body; // optional +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_METHODDECL_HPP_ diff --git a/lib/parser/ast/nodes/class_members/StaticFieldDecl.cpp b/lib/parser/ast/nodes/class_members/StaticFieldDecl.cpp new file mode 100644 index 0000000..a2470b4 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/StaticFieldDecl.cpp @@ -0,0 +1,65 @@ +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void StaticFieldDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool StaticFieldDecl::IsPublic() const noexcept { + return is_public_; +} + +void StaticFieldDecl::SetPublic(bool is_public) noexcept { + is_public_ = is_public; +} + +bool StaticFieldDecl::IsVar() const noexcept { + return is_var_; +} + +void StaticFieldDecl::SetVar(bool is_var) noexcept { + is_var_ = is_var; +} + +const std::string& StaticFieldDecl::Name() const noexcept { + return name_; +} + +void StaticFieldDecl::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const TypeReference& StaticFieldDecl::Type() const noexcept { + return type_; +} + +TypeReference& StaticFieldDecl::MutableType() noexcept { + return type_; +} + +void StaticFieldDecl::SetType(TypeReference type) { + type_ = std::move(type); +} + +const Expr* StaticFieldDecl::Init() const noexcept { + return init_.get(); +} + +Expr* StaticFieldDecl::MutableInit() noexcept { + return init_.get(); +} + +void StaticFieldDecl::SetInit(std::unique_ptr expr) { + init_ = std::move(expr); +} + +std::unique_ptr StaticFieldDecl::ReleaseInit() { + return std::move(init_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp b/lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp new file mode 100644 index 0000000..09b5cd7 --- /dev/null +++ b/lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp @@ -0,0 +1,45 @@ +#ifndef PARSER_STATICFIELDDECL_HPP_ +#define PARSER_STATICFIELDDECL_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class StaticFieldDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsPublic() const noexcept; + void SetPublic(bool is_public) noexcept; + + bool IsVar() const noexcept; + void SetVar(bool is_var) noexcept; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const TypeReference& Type() const noexcept; + TypeReference& MutableType() noexcept; + void SetType(TypeReference type); + + const Expr* Init() const noexcept; + Expr* MutableInit() noexcept; + void SetInit(std::unique_ptr expr); + std::unique_ptr ReleaseInit(); + +private: + bool is_public_ = true; + bool is_var_ = false; + std::string name_; + TypeReference type_; + std::unique_ptr init_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATICFIELDDECL_HPP_ diff --git a/lib/parser/ast/nodes/decls/ClassDecl.cpp b/lib/parser/ast/nodes/decls/ClassDecl.cpp new file mode 100644 index 0000000..5f1f049 --- /dev/null +++ b/lib/parser/ast/nodes/decls/ClassDecl.cpp @@ -0,0 +1,53 @@ +#include "ClassDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void ClassDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& ClassDecl::Name() const noexcept { + return name_; +} + +void ClassDecl::SetName(std::string name) { + name_ = std::move(name); +} + +const std::vector& ClassDecl::Implements() const noexcept { + return implements_; +} + +std::vector& ClassDecl::MutableImplements() noexcept { + return implements_; +} + +void ClassDecl::AddImplements(TypeReference type) { + implements_.emplace_back(std::move(type)); +} + +const std::vector>& ClassDecl::Members() const noexcept { + return members_; +} + +std::vector>& ClassDecl::MutableMembers() noexcept { + return members_; +} + +void ClassDecl::AddMember(std::unique_ptr decl) { + members_.emplace_back(std::move(decl)); +} + +std::unique_ptr ClassDecl::ReleaseMember(std::size_t index) { + if (index >= members_.size()) { + return nullptr; + } + + auto old = std::move(members_[index]); + members_.erase(members_.begin() + static_cast(index)); + return old; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/ClassDecl.hpp b/lib/parser/ast/nodes/decls/ClassDecl.hpp new file mode 100644 index 0000000..6e93ebe --- /dev/null +++ b/lib/parser/ast/nodes/decls/ClassDecl.hpp @@ -0,0 +1,37 @@ +#ifndef PARSER_CLASSDECL_HPP_ +#define PARSER_CLASSDECL_HPP_ + +#include +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class ClassDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& Name() const noexcept; + void SetName(std::string name); + + const std::vector& Implements() const noexcept; + std::vector& MutableImplements() noexcept; + void AddImplements(TypeReference type); + + const std::vector>& Members() const noexcept; + std::vector>& MutableMembers() noexcept; + void AddMember(std::unique_ptr decl); + std::unique_ptr ReleaseMember(std::size_t index); + +private: + std::string name_; + std::vector implements_; + std::vector> members_; // Field/StaticField/Method/Call/Destructor +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CLASSDECL_HPP_ diff --git a/lib/parser/ast/nodes/decls/FunctionDecl.cpp b/lib/parser/ast/nodes/decls/FunctionDecl.cpp new file mode 100644 index 0000000..12afb59 --- /dev/null +++ b/lib/parser/ast/nodes/decls/FunctionDecl.cpp @@ -0,0 +1,70 @@ +#include "FunctionDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void FunctionDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool FunctionDecl::IsPure() const noexcept { + return is_pure_; +} + +void FunctionDecl::SetPure(bool is_pure) noexcept { + is_pure_ = is_pure; +} + +const std::string& FunctionDecl::Name() const noexcept { + return name_; +} + +void FunctionDecl::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const std::vector& FunctionDecl::Params() const noexcept { + return params_; +} + +std::vector& FunctionDecl::MutableParams() noexcept { + return params_; +} + +void FunctionDecl::AddParam(Param param) { + params_.emplace_back(std::move(param)); +} + +const TypeReference* FunctionDecl::ReturnType() const noexcept { + return return_type_.get(); +} +TypeReference* FunctionDecl::MutableReturnType() noexcept { + return return_type_.get(); +} + +void FunctionDecl::SetReturnType(std::unique_ptr type) { + return_type_ = std::move(type); +} + +std::unique_ptr FunctionDecl::ReleaseReturnType() { + return std::move(return_type_); +} + +const Block* FunctionDecl::Body() const noexcept { + return body_.get(); +} + +Block* FunctionDecl::MutableBody() noexcept { + return body_.get(); +} + +void FunctionDecl::SetBody(std::unique_ptr block) { + body_ = std::move(block); +} + +std::unique_ptr FunctionDecl::ReleaseBody() { + return std::move(body_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/FunctionDecl.hpp b/lib/parser/ast/nodes/decls/FunctionDecl.hpp new file mode 100644 index 0000000..198e234 --- /dev/null +++ b/lib/parser/ast/nodes/decls/FunctionDecl.hpp @@ -0,0 +1,50 @@ +#ifndef PARSER_FUNCTIONDECL_HPP_ +#define PARSER_FUNCTIONDECL_HPP_ + +#include +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/types/Param.hpp" + +namespace ovum::compiler::parser { + +class TypeReference; + +class FunctionDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsPure() const noexcept; + void SetPure(bool is_pure) noexcept; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const std::vector& Params() const noexcept; + std::vector& MutableParams() noexcept; + void AddParam(Param param); + + const TypeReference* ReturnType() const noexcept; + TypeReference* MutableReturnType() noexcept; + void SetReturnType(std::unique_ptr type); + std::unique_ptr ReleaseReturnType(); + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr block); + std::unique_ptr ReleaseBody(); + +private: + bool is_pure_ = false; + std::string name_; + std::vector params_; + std::unique_ptr return_type_; // optional + std::unique_ptr body_; // optional +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FUNCTIONDECL_HPP_ diff --git a/lib/parser/ast/nodes/decls/GlobalVarDecl.cpp b/lib/parser/ast/nodes/decls/GlobalVarDecl.cpp new file mode 100644 index 0000000..97964dd --- /dev/null +++ b/lib/parser/ast/nodes/decls/GlobalVarDecl.cpp @@ -0,0 +1,55 @@ +#include "GlobalVarDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void GlobalVarDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool GlobalVarDecl::IsVar() const noexcept { + return is_var_; +} + +void GlobalVarDecl::SetVar(bool is_var) noexcept { + is_var_ = is_var; +} + +const std::string& GlobalVarDecl::Name() const noexcept { + return name_; +} + +void GlobalVarDecl::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const TypeReference& GlobalVarDecl::Type() const noexcept { + return type_; +} + +TypeReference& GlobalVarDecl::MutableType() noexcept { + return type_; +} + +void GlobalVarDecl::SetType(TypeReference type) { + type_ = std::move(type); +} + +const Expr* GlobalVarDecl::Init() const noexcept { + return init_.get(); +} + +Expr* GlobalVarDecl::MutableInit() noexcept { + return init_.get(); +} + +void GlobalVarDecl::SetInit(std::unique_ptr expr) { + init_ = std::move(expr); +} + +std::unique_ptr GlobalVarDecl::ReleaseInit() { + return std::move(init_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/GlobalVarDecl.hpp b/lib/parser/ast/nodes/decls/GlobalVarDecl.hpp new file mode 100644 index 0000000..ebcba68 --- /dev/null +++ b/lib/parser/ast/nodes/decls/GlobalVarDecl.hpp @@ -0,0 +1,41 @@ +#ifndef PARSER_GLOBALVARDECL_HPP_ +#define PARSER_GLOBALVARDECL_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class GlobalVarDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + bool IsVar() const noexcept; + void SetVar(bool is_var) noexcept; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const TypeReference& Type() const noexcept; + TypeReference& MutableType() noexcept; + void SetType(TypeReference type); + + const Expr* Init() const noexcept; + Expr* MutableInit() noexcept; + void SetInit(std::unique_ptr expr); + std::unique_ptr ReleaseInit(); + +private: + bool is_var_ = false; // var=true, val=false + std::string name_; + TypeReference type_; + std::unique_ptr init_; // optional +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_GLOBALVARDECL_HPP_ diff --git a/lib/parser/ast/nodes/decls/InterfaceDecl.cpp b/lib/parser/ast/nodes/decls/InterfaceDecl.cpp new file mode 100644 index 0000000..8a36942 --- /dev/null +++ b/lib/parser/ast/nodes/decls/InterfaceDecl.cpp @@ -0,0 +1,41 @@ +#include "InterfaceDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void InterfaceDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& InterfaceDecl::Name() const noexcept { + return name_; +} + +void InterfaceDecl::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const std::vector>& InterfaceDecl::Members() const noexcept { + return methods_; +} + +std::vector>& InterfaceDecl::MutableMembers() noexcept { + return methods_; +} + +void InterfaceDecl::AddMember(std::unique_ptr method) { + methods_.emplace_back(std::move(method)); +} + +std::unique_ptr InterfaceDecl::ReleaseMember(std::size_t index) { + if (index >= methods_.size()) { + return nullptr; + } + + auto old = std::move(methods_[index]); + methods_.erase(methods_.begin() + static_cast(index)); + return old; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/InterfaceDecl.hpp b/lib/parser/ast/nodes/decls/InterfaceDecl.hpp new file mode 100644 index 0000000..752810a --- /dev/null +++ b/lib/parser/ast/nodes/decls/InterfaceDecl.hpp @@ -0,0 +1,33 @@ +#ifndef PARSER_INTERFACEDECL_HPP_ +#define PARSER_INTERFACEDECL_HPP_ + +#include +#include +#include + +#include "InterfaceMethod.hpp" +#include "lib/parser/ast/nodes/base/Decl.hpp" + +namespace ovum::compiler::parser { + +class InterfaceDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const std::vector>& Members() const noexcept; + std::vector>& MutableMembers() noexcept; + + void AddMember(std::unique_ptr method); + std::unique_ptr ReleaseMember(std::size_t index); + +private: + std::string name_; + std::vector> methods_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INTERFACEDECL_HPP_ diff --git a/lib/parser/ast/nodes/decls/InterfaceMethod.cpp b/lib/parser/ast/nodes/decls/InterfaceMethod.cpp new file mode 100644 index 0000000..a5d49bc --- /dev/null +++ b/lib/parser/ast/nodes/decls/InterfaceMethod.cpp @@ -0,0 +1,37 @@ +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void InterfaceMethod::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& InterfaceMethod::Name() const noexcept { + return name_; +} + +void InterfaceMethod::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const std::vector& InterfaceMethod::Params() const noexcept { + return params_; +} + +std::vector& InterfaceMethod::MutableParams() noexcept { + return params_; +} + +const TypeReference* InterfaceMethod::ReturnType() const noexcept { + return ret_type_.get(); +} + +void InterfaceMethod::SetReturnType(std::unique_ptr type) { + ret_type_ = std::move(type); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/InterfaceMethod.hpp b/lib/parser/ast/nodes/decls/InterfaceMethod.hpp new file mode 100644 index 0000000..b94dfbc --- /dev/null +++ b/lib/parser/ast/nodes/decls/InterfaceMethod.hpp @@ -0,0 +1,39 @@ +#ifndef PARSER_INTERFACEMETHOD_HPP_ +#define PARSER_INTERFACEMETHOD_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/AstNode.hpp" +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class InterfaceMethod : public Decl { +public: + struct Param { + std::string name; + TypeReference type; + }; + + void Accept(AstVisitor& visitor) override; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const std::vector& Params() const noexcept; + std::vector& MutableParams() noexcept; + + const TypeReference* ReturnType() const noexcept; + void SetReturnType(std::unique_ptr type); + +private: + std::string name_; + std::vector params_; + std::unique_ptr ret_type_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INTERFACEMETHOD_HPP_ diff --git a/lib/parser/ast/nodes/decls/Module.cpp b/lib/parser/ast/nodes/decls/Module.cpp new file mode 100644 index 0000000..1cfbb33 --- /dev/null +++ b/lib/parser/ast/nodes/decls/Module.cpp @@ -0,0 +1,49 @@ +#include "Module.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void Module::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& Module::Name() const noexcept { + return name_; +} + +void Module::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const SourceId& Module::Source() const noexcept { + return source_; +} + +void Module::SetSource(SourceId id) { + source_ = std::move(id); +} + +const std::vector>& Module::Decls() const noexcept { + return decls_; +} + +std::vector>& Module::MutableDecls() noexcept { + return decls_; +} + +void Module::AddDecl(std::unique_ptr decl) { + decls_.emplace_back(std::move(decl)); +} + +std::unique_ptr Module::ReleaseDecl(std::size_t index) { + if (index >= decls_.size()) { + return nullptr; + } + + auto old = std::move(decls_[index]); + decls_.erase(decls_.begin() + static_cast(index)); + return std::move(old); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/Module.hpp b/lib/parser/ast/nodes/decls/Module.hpp new file mode 100644 index 0000000..341b246 --- /dev/null +++ b/lib/parser/ast/nodes/decls/Module.hpp @@ -0,0 +1,37 @@ +#ifndef PARSER_MODULE_HPP_ +#define PARSER_MODULE_HPP_ + +#include +#include +#include + +#include "lib/parser/ast/nodes/base/AstNode.hpp" +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/tokens/SourceId.hpp" + +namespace ovum::compiler::parser { + +class Module : public AstNode { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const SourceId& Source() const noexcept; + void SetSource(SourceId id); + + const std::vector>& Decls() const noexcept; + std::vector>& MutableDecls() noexcept; + void AddDecl(std::unique_ptr decl); + std::unique_ptr ReleaseDecl(std::size_t index); + +private: + std::string name_; + SourceId source_; + std::vector> decls_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MODULE_HPP_ diff --git a/lib/parser/ast/nodes/decls/TypeAliasDecl.cpp b/lib/parser/ast/nodes/decls/TypeAliasDecl.cpp new file mode 100644 index 0000000..7cdc767 --- /dev/null +++ b/lib/parser/ast/nodes/decls/TypeAliasDecl.cpp @@ -0,0 +1,33 @@ +#include "lib/parser/ast/nodes/decls/TypeAliasDecl.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void TypeAliasDecl::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& TypeAliasDecl::Name() const noexcept { + return name_; +} + +void TypeAliasDecl::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const TypeReference& TypeAliasDecl::AliasedType() const noexcept { + return aliased_type_; +} + +TypeReference& TypeAliasDecl::MutableAliasedType() noexcept { + return aliased_type_; +} + +void TypeAliasDecl::SetAliasedType(TypeReference type) { + aliased_type_ = std::move(type); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/decls/TypeAliasDecl.hpp b/lib/parser/ast/nodes/decls/TypeAliasDecl.hpp new file mode 100644 index 0000000..352a355 --- /dev/null +++ b/lib/parser/ast/nodes/decls/TypeAliasDecl.hpp @@ -0,0 +1,29 @@ +#ifndef PARSER_TYPEALIASDECL_HPP_ +#define PARSER_TYPEALIASDECL_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Decl.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class TypeAliasDecl : public Decl { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const TypeReference& AliasedType() const noexcept; + TypeReference& MutableAliasedType() noexcept; + void SetAliasedType(TypeReference type); + +private: + std::string name_; + TypeReference aliased_type_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_TYPEALIASDECL_HPP_ diff --git a/lib/parser/ast/nodes/exprs/Assign.cpp b/lib/parser/ast/nodes/exprs/Assign.cpp new file mode 100644 index 0000000..c38d05e --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Assign.cpp @@ -0,0 +1,57 @@ +#include "lib/parser/ast/nodes/exprs/Assign.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void Assign::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const IAssignOpTag& Assign::Kind() const noexcept { + return *kind_; +} + +void Assign::SetKind(const IAssignOpTag& new_kind) noexcept { + kind_ = &new_kind; +} + +const Expr& Assign::Target() const noexcept { + return *target_; +} + +Expr& Assign::MutableTarget() noexcept { + return *target_; +} + +void Assign::SetTarget(std::unique_ptr new_target) { + target_ = std::move(new_target); +} + +std::unique_ptr Assign::ReplaceTarget(std::unique_ptr new_target) { + auto old_target = std::move(target_); + target_ = std::move(new_target); + return old_target; +} + +const Expr& Assign::Value() const noexcept { + return *value_; +} + +Expr& Assign::MutableValue() noexcept { + return *value_; +} + +void Assign::SetValue(std::unique_ptr new_value) { + value_ = std::move(new_value); +} + +std::unique_ptr Assign::ReplaceValue(std::unique_ptr new_value) { + auto old_value = std::move(value_); + value_ = std::move(new_value); + return old_value; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/Assign.hpp b/lib/parser/ast/nodes/exprs/Assign.hpp new file mode 100644 index 0000000..a49ae85 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Assign.hpp @@ -0,0 +1,37 @@ +#ifndef PARSER_ASSIGN_HPP_ +#define PARSER_ASSIGN_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "tags/IAssignOpTag.hpp" +#include "tags/OpTags.hpp" + +namespace ovum::compiler::parser { + +class Assign : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const IAssignOpTag& Kind() const noexcept; + void SetKind(const IAssignOpTag& new_kind) noexcept; + + const Expr& Target() const noexcept; + Expr& MutableTarget() noexcept; + void SetTarget(std::unique_ptr new_target); + std::unique_ptr ReplaceTarget(std::unique_ptr new_target); + + const Expr& Value() const noexcept; + Expr& MutableValue() noexcept; + void SetValue(std::unique_ptr new_value); + std::unique_ptr ReplaceValue(std::unique_ptr new_value); + +private: + const IAssignOpTag* kind_ = &OpTags::RefAssign(); + std::unique_ptr target_; + std::unique_ptr value_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ASSIGN_HPP_ diff --git a/lib/parser/ast/nodes/exprs/Binary.cpp b/lib/parser/ast/nodes/exprs/Binary.cpp new file mode 100644 index 0000000..c6e843e --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Binary.cpp @@ -0,0 +1,57 @@ +#include "lib/parser/ast/nodes/exprs/Binary.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void Binary::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const IBinaryOpTag& Binary::Op() const noexcept { + return *op_; +} + +void Binary::SetOp(const IBinaryOpTag& new_op) noexcept { + op_ = &new_op; +} + +const Expr& Binary::Lhs() const noexcept { + return *lhs_; +} + +Expr& Binary::MutableLhs() noexcept { + return *lhs_; +} + +void Binary::SetLhs(std::unique_ptr new_lhs) { + lhs_ = std::move(new_lhs); +} + +std::unique_ptr Binary::ReplaceLhs(std::unique_ptr new_lhs) { + auto old_lhs = std::move(lhs_); + lhs_ = std::move(new_lhs); + return old_lhs; +} + +const Expr& Binary::Rhs() const noexcept { + return *rhs_; +} + +Expr& Binary::MutableRhs() noexcept { + return *rhs_; +} + +void Binary::SetRhs(std::unique_ptr new_rhs) { + rhs_ = std::move(new_rhs); +} + +std::unique_ptr Binary::ReplaceRhs(std::unique_ptr new_rhs) { + auto old_rhs = std::move(rhs_); + rhs_ = std::move(new_rhs); + return old_rhs; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/Binary.hpp b/lib/parser/ast/nodes/exprs/Binary.hpp new file mode 100644 index 0000000..ac2dcf6 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Binary.hpp @@ -0,0 +1,37 @@ +#ifndef PARSER_BINARY_HPP_ +#define PARSER_BINARY_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "tags/IBinaryOpTag.hpp" +#include "tags/OpTags.hpp" + +namespace ovum::compiler::parser { + +class Binary : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const IBinaryOpTag& Op() const noexcept; + void SetOp(const IBinaryOpTag& new_op) noexcept; + + const Expr& Lhs() const noexcept; + Expr& MutableLhs() noexcept; + void SetLhs(std::unique_ptr new_lhs); + std::unique_ptr ReplaceLhs(std::unique_ptr new_lhs); + + const Expr& Rhs() const noexcept; + Expr& MutableRhs() noexcept; + void SetRhs(std::unique_ptr new_rhs); + std::unique_ptr ReplaceRhs(std::unique_ptr new_rhs); + +private: + const IBinaryOpTag* op_ = &OpTags::Add(); + std::unique_ptr lhs_; + std::unique_ptr rhs_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BINARY_HPP_ diff --git a/lib/parser/ast/nodes/exprs/Call.cpp b/lib/parser/ast/nodes/exprs/Call.cpp new file mode 100644 index 0000000..12f4417 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Call.cpp @@ -0,0 +1,46 @@ +#include "lib/parser/ast/AstVisitor.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" + +#include + +namespace ovum::compiler::parser { + +void Call::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& Call::Callee() const noexcept { + return *callee_; +} + +Expr& Call::MutableCallee() noexcept { + return *callee_; +} + +void Call::SetCallee(std::unique_ptr new_callee) { + callee_ = std::move(new_callee); +} + +std::unique_ptr Call::ReplaceCallee(std::unique_ptr new_callee) { + auto old_callee = std::move(callee_); + callee_ = std::move(new_callee); + return old_callee; +} + +const std::vector>& Call::Args() const noexcept { + return args_; +} + +std::vector>& Call::MutableArgs() noexcept { + return args_; +} + +void Call::AddArg(std::unique_ptr new_arg) { + args_.emplace_back(std::move(new_arg)); +} + +void Call::ClearArgs() { + args_.clear(); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/Call.hpp b/lib/parser/ast/nodes/exprs/Call.hpp new file mode 100644 index 0000000..6217740 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Call.hpp @@ -0,0 +1,32 @@ +#ifndef PARSER_CALL_HPP_ +#define PARSER_CALL_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class Call : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& Callee() const noexcept; + Expr& MutableCallee() noexcept; + void SetCallee(std::unique_ptr new_callee); + std::unique_ptr ReplaceCallee(std::unique_ptr new_callee); + + const std::vector>& Args() const noexcept; + std::vector>& MutableArgs() noexcept; + void AddArg(std::unique_ptr new_arg); + void ClearArgs(); + +private: + std::unique_ptr callee_; + std::vector> args_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CALL_HPP_ diff --git a/lib/parser/ast/nodes/exprs/CastAs.cpp b/lib/parser/ast/nodes/exprs/CastAs.cpp new file mode 100644 index 0000000..9bf495f --- /dev/null +++ b/lib/parser/ast/nodes/exprs/CastAs.cpp @@ -0,0 +1,43 @@ +#include "lib/parser/ast/nodes/exprs/CastAs.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void CastAs::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& CastAs::Expression() const noexcept { + return *expr_; +} + +Expr& CastAs::MutableExpression() noexcept { + return *expr_; +} + +void CastAs::SetExpression(std::unique_ptr new_expression) { + expr_ = std::move(new_expression); +} + +std::unique_ptr CastAs::ReplaceExpression(std::unique_ptr new_expression) { + auto old_expr = std::move(expr_); + expr_ = std::move(new_expression); + return old_expr; +} + +const TypeReference& CastAs::Type() const noexcept { + return type_; +} + +TypeReference& CastAs::MutableType() noexcept { + return type_; +} + +void CastAs::SetType(TypeReference new_type) { + type_ = std::move(new_type); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/CastAs.hpp b/lib/parser/ast/nodes/exprs/CastAs.hpp new file mode 100644 index 0000000..fc9c88a --- /dev/null +++ b/lib/parser/ast/nodes/exprs/CastAs.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_CASTAS_HPP_ +#define PARSER_CASTAS_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class CastAs : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& Expression() const noexcept; + Expr& MutableExpression() noexcept; + void SetExpression(std::unique_ptr new_expression); + std::unique_ptr ReplaceExpression(std::unique_ptr new_expression); + + const TypeReference& Type() const noexcept; + TypeReference& MutableType() noexcept; + void SetType(TypeReference new_type); + +private: + std::unique_ptr expr_; + TypeReference type_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CASTAS_HPP_ diff --git a/lib/parser/ast/nodes/exprs/Elvis.cpp b/lib/parser/ast/nodes/exprs/Elvis.cpp new file mode 100644 index 0000000..c19b6d3 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Elvis.cpp @@ -0,0 +1,49 @@ +#include "lib/parser/ast/nodes/exprs/Elvis.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void Elvis::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& Elvis::Lhs() const noexcept { + return *lhs_; +} + +Expr& Elvis::MutableLhs() noexcept { + return *lhs_; +} + +void Elvis::SetLhs(std::unique_ptr new_lhs) { + lhs_ = std::move(new_lhs); +} + +std::unique_ptr Elvis::ReplaceLhs(std::unique_ptr new_lhs) { + auto old_lhs = std::move(lhs_); + lhs_ = std::move(new_lhs); + return old_lhs; +} + +const Expr& Elvis::Rhs() const noexcept { + return *rhs_; +} + +Expr& Elvis::MutableRhs() noexcept { + return *rhs_; +} + +void Elvis::SetRhs(std::unique_ptr new_rhs) { + rhs_ = std::move(new_rhs); +} + +std::unique_ptr Elvis::ReplaceRhs(std::unique_ptr new_rhs) { + auto old_rhs = std::move(rhs_); + rhs_ = std::move(new_rhs); + return old_rhs; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/Elvis.hpp b/lib/parser/ast/nodes/exprs/Elvis.hpp new file mode 100644 index 0000000..0511bb8 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Elvis.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_ELVIS_HPP_ +#define PARSER_ELVIS_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class Elvis : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& Lhs() const noexcept; + Expr& MutableLhs() noexcept; + void SetLhs(std::unique_ptr new_lhs); + std::unique_ptr ReplaceLhs(std::unique_ptr new_lhs); + + const Expr& Rhs() const noexcept; + Expr& MutableRhs() noexcept; + void SetRhs(std::unique_ptr new_rhs); + std::unique_ptr ReplaceRhs(std::unique_ptr new_rhs); + +private: + std::unique_ptr lhs_; + std::unique_ptr rhs_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ELVIS_HPP_ diff --git a/lib/parser/ast/nodes/exprs/FieldAccess.cpp b/lib/parser/ast/nodes/exprs/FieldAccess.cpp new file mode 100644 index 0000000..67395ae --- /dev/null +++ b/lib/parser/ast/nodes/exprs/FieldAccess.cpp @@ -0,0 +1,39 @@ +#include "lib/parser/ast/nodes/exprs/FieldAccess.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void FieldAccess::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& FieldAccess::Object() const noexcept { + return *object_; +} + +Expr& FieldAccess::MutableObject() noexcept { + return *object_; +} + +void FieldAccess::SetObject(std::unique_ptr new_object) { + object_ = std::move(new_object); +} + +std::unique_ptr FieldAccess::ReplaceObject(std::unique_ptr new_object) { + auto old_object = std::move(object_); + object_ = std::move(new_object); + return old_object; +} + +const std::string& FieldAccess::Name() const noexcept { + return name_; +} + +void FieldAccess::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/FieldAccess.hpp b/lib/parser/ast/nodes/exprs/FieldAccess.hpp new file mode 100644 index 0000000..96cbed9 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/FieldAccess.hpp @@ -0,0 +1,30 @@ +#ifndef PARSER_FIELDACCESS_HPP_ +#define PARSER_FIELDACCESS_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class FieldAccess : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& Object() const noexcept; + Expr& MutableObject() noexcept; + void SetObject(std::unique_ptr new_object); + std::unique_ptr ReplaceObject(std::unique_ptr new_object); + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + +private: + std::unique_ptr object_; + std::string name_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FIELDACCESS_HPP_ diff --git a/lib/parser/ast/nodes/exprs/IdentRef.cpp b/lib/parser/ast/nodes/exprs/IdentRef.cpp new file mode 100644 index 0000000..37cb13c --- /dev/null +++ b/lib/parser/ast/nodes/exprs/IdentRef.cpp @@ -0,0 +1,21 @@ +#include "lib/parser/ast/nodes/exprs/IdentRef.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void IdentRef::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& IdentRef::Name() const noexcept { + return name_; +} + +void IdentRef::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/IdentRef.hpp b/lib/parser/ast/nodes/exprs/IdentRef.hpp new file mode 100644 index 0000000..288aeb6 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/IdentRef.hpp @@ -0,0 +1,23 @@ +#ifndef PARSER_IDENTREF_HPP_ +#define PARSER_IDENTREF_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class IdentRef : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + +private: + std::string name_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IDENTREF_HPP_ diff --git a/lib/parser/ast/nodes/exprs/IndexAccess.cpp b/lib/parser/ast/nodes/exprs/IndexAccess.cpp new file mode 100644 index 0000000..2f59348 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/IndexAccess.cpp @@ -0,0 +1,49 @@ +#include "lib/parser/ast/nodes/exprs/IndexAccess.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void IndexAccess::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& IndexAccess::Object() const noexcept { + return *object_; +} + +Expr& IndexAccess::MutableObject() noexcept { + return *object_; +} + +void IndexAccess::SetObject(std::unique_ptr new_object) { + object_ = std::move(new_object); +} + +std::unique_ptr IndexAccess::ReplaceObject(std::unique_ptr new_object) { + auto old_object = std::move(object_); + object_ = std::move(new_object); + return old_object; +} + +const Expr& IndexAccess::IndexExpr() const noexcept { + return *index_; +} + +Expr& IndexAccess::MutableIndexExpr() noexcept { + return *index_; +} + +void IndexAccess::SetIndexExpr(std::unique_ptr new_index) { + index_ = std::move(new_index); +} + +std::unique_ptr IndexAccess::ReplaceIndexExpr(std::unique_ptr new_index) { + auto old_index = std::move(index_); + index_ = std::move(new_index); + return old_index; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/IndexAccess.hpp b/lib/parser/ast/nodes/exprs/IndexAccess.hpp new file mode 100644 index 0000000..694c789 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/IndexAccess.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_INDEXACCESS_HPP_ +#define PARSER_INDEXACCESS_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class IndexAccess : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& Object() const noexcept; + Expr& MutableObject() noexcept; + void SetObject(std::unique_ptr new_object); + std::unique_ptr ReplaceObject(std::unique_ptr new_object); + + const Expr& IndexExpr() const noexcept; + Expr& MutableIndexExpr() noexcept; + void SetIndexExpr(std::unique_ptr new_index); + std::unique_ptr ReplaceIndexExpr(std::unique_ptr new_index); + +private: + std::unique_ptr object_; + std::unique_ptr index_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INDEXACCESS_HPP_ diff --git a/lib/parser/ast/nodes/exprs/NamespaceRef.cpp b/lib/parser/ast/nodes/exprs/NamespaceRef.cpp new file mode 100644 index 0000000..7443147 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/NamespaceRef.cpp @@ -0,0 +1,39 @@ +#include "lib/parser/ast/nodes/exprs/NamespaceRef.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void NamespaceRef::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& NamespaceRef::NamespaceExpr() const noexcept { + return *namespace_; +} + +Expr& NamespaceRef::MutableNamespaceExpr() noexcept { + return *namespace_; +} + +void NamespaceRef::SetNamespaceExpr(std::unique_ptr new_namespace_expr) { + namespace_ = std::move(new_namespace_expr); +} + +std::unique_ptr NamespaceRef::ReplaceNamespaceExpr(std::unique_ptr new_namespace_expr) { + auto old_ns = std::move(namespace_); + namespace_ = std::move(new_namespace_expr); + return old_ns; +} + +const std::string& NamespaceRef::Name() const noexcept { + return name_; +} + +void NamespaceRef::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/NamespaceRef.hpp b/lib/parser/ast/nodes/exprs/NamespaceRef.hpp new file mode 100644 index 0000000..0f0eb72 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/NamespaceRef.hpp @@ -0,0 +1,30 @@ +#ifndef PARSER_NAMESPACEREF_HPP_ +#define PARSER_NAMESPACEREF_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class NamespaceRef : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& NamespaceExpr() const noexcept; + Expr& MutableNamespaceExpr() noexcept; + void SetNamespaceExpr(std::unique_ptr new_namespace_expr); + std::unique_ptr ReplaceNamespaceExpr(std::unique_ptr new_namespace_expr); + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + +private: + std::unique_ptr namespace_; + std::string name_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_NAMESPACEREF_HPP_ diff --git a/lib/parser/ast/nodes/exprs/SafeCall.cpp b/lib/parser/ast/nodes/exprs/SafeCall.cpp new file mode 100644 index 0000000..a0a158a --- /dev/null +++ b/lib/parser/ast/nodes/exprs/SafeCall.cpp @@ -0,0 +1,67 @@ +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void SafeCall::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& SafeCall::Object() const noexcept { + return *object_; +} + +Expr& SafeCall::MutableObject() noexcept { + return *object_; +} + +void SafeCall::SetObject(std::unique_ptr object_expr) { + object_ = std::move(object_expr); +} + +std::unique_ptr SafeCall::ReplaceObject(std::unique_ptr new_object) { + auto old_object = std::move(object_); + object_ = std::move(new_object); + return old_object; +} + +const std::string& SafeCall::Method() const noexcept { + return method_; +} + +void SafeCall::SetMethod(std::string method_name) { + method_ = std::move(method_name); +} + +const std::vector>& SafeCall::Args() const noexcept { + return args_; +} + +std::vector>& SafeCall::MutableArgs() noexcept { + return args_; +} + +void SafeCall::AddArg(std::unique_ptr argument_expr) { + args_.emplace_back(std::move(argument_expr)); +} + +void SafeCall::ClearArgs() { + args_.clear(); +} + +bool SafeCall::IsNullPropagating() const noexcept { + return true; +} + +void SafeCall::SetInferredType(TypeReference inferred) { + inferred_type_ = std::move(inferred); +} + +const std::optional& SafeCall::InferredType() const noexcept { + return inferred_type_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/SafeCall.hpp b/lib/parser/ast/nodes/exprs/SafeCall.hpp new file mode 100644 index 0000000..1052a7d --- /dev/null +++ b/lib/parser/ast/nodes/exprs/SafeCall.hpp @@ -0,0 +1,47 @@ +#ifndef PARSER_SAFECALL_HPP_ +#define PARSER_SAFECALL_HPP_ + +#include +#include +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class AstVisitor; + +class SafeCall : public Expr { +public: + void Accept(AstVisitor& v) override; + + const Expr& Object() const noexcept; + Expr& MutableObject() noexcept; + void SetObject(std::unique_ptr object_expr); + std::unique_ptr ReplaceObject(std::unique_ptr new_object); + + const std::string& Method() const noexcept; + void SetMethod(std::string method_name); + + const std::vector>& Args() const noexcept; + std::vector>& MutableArgs() noexcept; + void AddArg(std::unique_ptr argument_expr); + void ClearArgs(); + + bool IsNullPropagating() const noexcept; + + void SetInferredType(TypeReference inferred); + const std::optional& InferredType() const noexcept; + +private: + std::unique_ptr object_; + std::string method_; + std::vector> args_; + std::optional inferred_type_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_SAFECALL_HPP_ diff --git a/lib/parser/ast/nodes/exprs/TypeTestIs.cpp b/lib/parser/ast/nodes/exprs/TypeTestIs.cpp new file mode 100644 index 0000000..9b360d8 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/TypeTestIs.cpp @@ -0,0 +1,43 @@ +#include "lib/parser/ast/nodes/exprs/TypeTestIs.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void TypeTestIs::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr& TypeTestIs::Expression() const noexcept { + return *expr; +} + +Expr& TypeTestIs::MutableExpression() noexcept { + return *expr; +} + +void TypeTestIs::SetExpression(std::unique_ptr new_expression) { + expr = std::move(new_expression); +} + +std::unique_ptr TypeTestIs::ReplaceExpression(std::unique_ptr new_expression) { + auto old_expr = std::move(expr); + expr = std::move(new_expression); + return old_expr; +} + +const TypeReference& TypeTestIs::Type() const noexcept { + return type; +} + +TypeReference& TypeTestIs::MutableType() noexcept { + return type; +} + +void TypeTestIs::SetType(TypeReference new_type) { + type = std::move(new_type); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/TypeTestIs.hpp b/lib/parser/ast/nodes/exprs/TypeTestIs.hpp new file mode 100644 index 0000000..4cff1ce --- /dev/null +++ b/lib/parser/ast/nodes/exprs/TypeTestIs.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_TYPETESTIS_HPP_ +#define PARSER_TYPETESTIS_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class TypeTestIs : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const Expr& Expression() const noexcept; + Expr& MutableExpression() noexcept; + void SetExpression(std::unique_ptr new_expression); + std::unique_ptr ReplaceExpression(std::unique_ptr new_expression); + + const TypeReference& Type() const noexcept; + TypeReference& MutableType() noexcept; + void SetType(TypeReference new_type); + +private: + std::unique_ptr expr; + TypeReference type; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_TYPETESTIS_HPP_ diff --git a/lib/parser/ast/nodes/exprs/Unary.cpp b/lib/parser/ast/nodes/exprs/Unary.cpp new file mode 100644 index 0000000..e7f5edd --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Unary.cpp @@ -0,0 +1,39 @@ +#include "lib/parser/ast/nodes/exprs/Unary.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void Unary::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const IUnaryOpTag& Unary::Op() const noexcept { + return *op_; +} + +void Unary::SetOp(const IUnaryOpTag& new_op) noexcept { + op_ = &new_op; +} + +const Expr& Unary::Operand() const noexcept { + return *operand_; +} + +Expr& Unary::MutableOperand() noexcept { + return *operand_; +} + +void Unary::SetOperand(std::unique_ptr new_operand) { + operand_ = std::move(new_operand); +} + +std::unique_ptr Unary::ReplaceOperand(std::unique_ptr new_operand) { + auto old_operand = std::move(operand_); + operand_ = std::move(new_operand); + return old_operand; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/Unary.hpp b/lib/parser/ast/nodes/exprs/Unary.hpp new file mode 100644 index 0000000..60319cc --- /dev/null +++ b/lib/parser/ast/nodes/exprs/Unary.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_UNARY_HPP_ +#define PARSER_UNARY_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "tags/IUnaryOpTag.hpp" +#include "tags/OpTags.hpp" + +namespace ovum::compiler::parser { + +class Unary : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const IUnaryOpTag& Op() const noexcept; + void SetOp(const IUnaryOpTag& new_op) noexcept; + + const Expr& Operand() const noexcept; + Expr& MutableOperand() noexcept; + void SetOperand(std::unique_ptr new_operand); + std::unique_ptr ReplaceOperand(std::unique_ptr new_operand); + +private: + const IUnaryOpTag* op_ = &OpTags::Neg(); + std::unique_ptr operand_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_UNARY_HPP_ diff --git a/lib/parser/ast/nodes/exprs/literals/BoolLit.cpp b/lib/parser/ast/nodes/exprs/literals/BoolLit.cpp new file mode 100644 index 0000000..51a7488 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/BoolLit.cpp @@ -0,0 +1,19 @@ +#include "lib/parser/ast/nodes/exprs/literals/BoolLit.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void BoolLit::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool BoolLit::Value() const noexcept { + return value; +} + +void BoolLit::SetValue(bool new_value) noexcept { + value = new_value; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/literals/BoolLit.hpp b/lib/parser/ast/nodes/exprs/literals/BoolLit.hpp new file mode 100644 index 0000000..399b701 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/BoolLit.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_BOOLLIT_HPP_ +#define PARSER_BOOLLIT_HPP_ + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class BoolLit : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + bool Value() const noexcept; + void SetValue(bool new_value) noexcept; + +private: + bool value = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BOOLLIT_HPP_ diff --git a/lib/parser/ast/nodes/exprs/literals/CharLit.cpp b/lib/parser/ast/nodes/exprs/literals/CharLit.cpp new file mode 100644 index 0000000..4c45367 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/CharLit.cpp @@ -0,0 +1,19 @@ +#include "lib/parser/ast/nodes/exprs/literals/CharLit.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void CharLit::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +char CharLit::Value() const noexcept { + return value_; +} + +void CharLit::SetValue(char new_value) noexcept { + value_ = new_value; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/literals/CharLit.hpp b/lib/parser/ast/nodes/exprs/literals/CharLit.hpp new file mode 100644 index 0000000..6393dd8 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/CharLit.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_CHARLIT_HPP_ +#define PARSER_CHARLIT_HPP_ + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class CharLit : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + char Value() const noexcept; + void SetValue(char new_value) noexcept; + +private: + char value_ = '\0'; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CHARLIT_HPP_ diff --git a/lib/parser/ast/nodes/exprs/literals/FloatLit.cpp b/lib/parser/ast/nodes/exprs/literals/FloatLit.cpp new file mode 100644 index 0000000..99631d6 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/FloatLit.cpp @@ -0,0 +1,19 @@ +#include "lib/parser/ast/nodes/exprs/literals/FloatLit.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void FloatLit::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +double FloatLit::Value() const noexcept { + return value; +} + +void FloatLit::SetValue(double new_value) noexcept { + value = new_value; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/literals/FloatLit.hpp b/lib/parser/ast/nodes/exprs/literals/FloatLit.hpp new file mode 100644 index 0000000..4dba68a --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/FloatLit.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_FLOATLIT_HPP_ +#define PARSER_FLOATLIT_HPP_ + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class FloatLit : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + double Value() const noexcept; + void SetValue(double new_value) noexcept; + +private: + double value = 0.0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FLOATLIT_HPP_ diff --git a/lib/parser/ast/nodes/exprs/literals/IntLit.cpp b/lib/parser/ast/nodes/exprs/literals/IntLit.cpp new file mode 100644 index 0000000..8c9d681 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/IntLit.cpp @@ -0,0 +1,19 @@ +#include "lib/parser/ast/nodes/exprs/literals/IntLit.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void IntLit::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +int64_t IntLit::Value() const noexcept { + return value; +} + +void IntLit::SetValue(int64_t new_value) noexcept { + value = new_value; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/literals/IntLit.hpp b/lib/parser/ast/nodes/exprs/literals/IntLit.hpp new file mode 100644 index 0000000..3ec55e5 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/IntLit.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_INTLIT_HPP_ +#define PARSER_INTLIT_HPP_ + +#include +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class IntLit : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + int64_t Value() const noexcept; + void SetValue(int64_t new_value) noexcept; + +private: + int64_t value = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INTLIT_HPP_ diff --git a/lib/parser/ast/nodes/exprs/literals/NullLit.cpp b/lib/parser/ast/nodes/exprs/literals/NullLit.cpp new file mode 100644 index 0000000..1af96fd --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/NullLit.cpp @@ -0,0 +1,11 @@ +#include "lib/parser/ast/nodes/exprs/literals/NullLit.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void NullLit::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/literals/NullLit.hpp b/lib/parser/ast/nodes/exprs/literals/NullLit.hpp new file mode 100644 index 0000000..21ac8a4 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/NullLit.hpp @@ -0,0 +1,15 @@ +#ifndef PARSER_NULLLIT_HPP_ +#define PARSER_NULLLIT_HPP_ + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class NullLit : public Expr { +public: + void Accept(AstVisitor& visitor) override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_NULLLIT_HPP_ diff --git a/lib/parser/ast/nodes/exprs/literals/StringLit.cpp b/lib/parser/ast/nodes/exprs/literals/StringLit.cpp new file mode 100644 index 0000000..db667f2 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/StringLit.cpp @@ -0,0 +1,21 @@ +#include "lib/parser/ast/nodes/exprs/literals/StringLit.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void StringLit::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& StringLit::Value() const noexcept { + return value_; +} + +void StringLit::SetValue(std::string new_value) { + value_ = std::move(new_value); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/literals/StringLit.hpp b/lib/parser/ast/nodes/exprs/literals/StringLit.hpp new file mode 100644 index 0000000..e6a1ed5 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/literals/StringLit.hpp @@ -0,0 +1,23 @@ +#ifndef PARSER_STRINGLIT_HPP_ +#define PARSER_STRINGLIT_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class StringLit : public Expr { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& Value() const noexcept; + void SetValue(std::string new_value); + +private: + std::string value_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STRINGLIT_HPP_ diff --git a/lib/parser/ast/nodes/exprs/tags/IAssignOpTag.hpp b/lib/parser/ast/nodes/exprs/tags/IAssignOpTag.hpp new file mode 100644 index 0000000..a7f6116 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/tags/IAssignOpTag.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_IASSIGNOPTAG_HPP_ +#define PARSER_IASSIGNOPTAG_HPP_ + +#include + +namespace ovum::compiler::parser { + +class IAssignOpTag { +public: + virtual ~IAssignOpTag() = default; + + virtual std::string_view Name() const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IASSIGNOPTAG_HPP_ diff --git a/lib/parser/ast/nodes/exprs/tags/IBinaryOpTag.hpp b/lib/parser/ast/nodes/exprs/tags/IBinaryOpTag.hpp new file mode 100644 index 0000000..0032c50 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/tags/IBinaryOpTag.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_IBINARYOPTAG_HPP_ +#define PARSER_IBINARYOPTAG_HPP_ + +#include + +namespace ovum::compiler::parser { + +class IBinaryOpTag { +public: + virtual ~IBinaryOpTag() = default; + + virtual std::string_view Name() const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IBINARYOPTAG_HPP_ diff --git a/lib/parser/ast/nodes/exprs/tags/IUnaryOpTag.hpp b/lib/parser/ast/nodes/exprs/tags/IUnaryOpTag.hpp new file mode 100644 index 0000000..d5d42ee --- /dev/null +++ b/lib/parser/ast/nodes/exprs/tags/IUnaryOpTag.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_IUNARYOPTAG_HPP_ +#define PARSER_IUNARYOPTAG_HPP_ + +#include + +namespace ovum::compiler::parser { + +class IUnaryOpTag { +public: + virtual ~IUnaryOpTag() = default; + + virtual std::string_view Name() const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IUNARYOPTAG_HPP_ diff --git a/lib/parser/ast/nodes/exprs/tags/OpTags.cpp b/lib/parser/ast/nodes/exprs/tags/OpTags.cpp new file mode 100644 index 0000000..53c8c87 --- /dev/null +++ b/lib/parser/ast/nodes/exprs/tags/OpTags.cpp @@ -0,0 +1,224 @@ +#include "OpTags.hpp" + +#include + +namespace ovum::compiler::parser { + +namespace { + +struct BinaryAdd : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "add"; + } +}; + +struct BinarySub : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "sub"; + } +}; + +struct BinaryMul : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "mul"; + } +}; + +struct BinaryDiv : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "div"; + } +}; + +struct BinaryMod : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "mod"; + } +}; + +struct BinaryLt : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "lt"; + } +}; + +struct BinaryLe : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "le"; + } +}; + +struct BinaryGt : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "gt"; + } +}; + +struct BinaryGe : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "ge"; + } +}; + +struct BinaryEq : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "eq"; + } +}; + +struct BinaryNe : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "ne"; + } +}; + +struct BinaryAnd : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "and"; + } +}; + +struct BinaryOr : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "or"; + } +}; + +struct BinaryXor : IBinaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "xor"; + } +}; + +struct UnaryNeg : IUnaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "neg"; + } +}; + +struct UnaryPlus : IUnaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "plus"; + } +}; + +struct UnaryNot : IUnaryOpTag { + [[nodiscard]] std::string_view Name() const override { + return "not"; + } +}; + +struct AssignRef : IAssignOpTag { + [[nodiscard]] std::string_view Name() const override { + return "="; + } +}; + +struct AssignCopy : IAssignOpTag { + [[nodiscard]] std::string_view Name() const override { + return ":="; + } +}; + +} // namespace + +namespace OpTags { + +const IBinaryOpTag& Add() { + static BinaryAdd t; + return t; +} + +const IBinaryOpTag& Sub() { + static BinarySub t; + return t; +} + +const IBinaryOpTag& Mul() { + static BinaryMul t; + return t; +} + +const IBinaryOpTag& Div() { + static BinaryDiv t; + return t; +} + +const IBinaryOpTag& Mod() { + static BinaryMod t; + return t; +} + +const IBinaryOpTag& Lt() { + static BinaryLt t; + return t; +} + +const IBinaryOpTag& Le() { + static BinaryLe t; + return t; +} + +const IBinaryOpTag& Gt() { + static BinaryGt t; + return t; +} + +const IBinaryOpTag& Ge() { + static BinaryGe t; + return t; +} + +const IBinaryOpTag& Eq() { + static BinaryEq t; + return t; +} + +const IBinaryOpTag& Ne() { + static BinaryNe t; + return t; +} + +const IBinaryOpTag& And() { + static BinaryAnd t; + return t; +} + +const IBinaryOpTag& Or() { + static BinaryOr t; + return t; +} + +const IBinaryOpTag& Xor() { + static BinaryXor t; + return t; +} + +const IUnaryOpTag& Neg() { + static UnaryNeg t; + return t; +} + +const IUnaryOpTag& Plus() { + static UnaryPlus t; + return t; +} + +const IUnaryOpTag& Not() { + static UnaryNot t; + return t; +} + +const IAssignOpTag& RefAssign() { + static AssignRef t; + return t; +} + +const IAssignOpTag& CopyAssign() { + static AssignCopy t; + return t; +} + +} // namespace OpTags + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/exprs/tags/OpTags.hpp b/lib/parser/ast/nodes/exprs/tags/OpTags.hpp new file mode 100644 index 0000000..7879e2e --- /dev/null +++ b/lib/parser/ast/nodes/exprs/tags/OpTags.hpp @@ -0,0 +1,39 @@ +#ifndef PARSER_OPTAGS_HPP_ +#define PARSER_OPTAGS_HPP_ + +#include "IAssignOpTag.hpp" +#include "IBinaryOpTag.hpp" +#include "IUnaryOpTag.hpp" + +namespace ovum::compiler::parser { + +namespace OpTags { +// binary +const IBinaryOpTag& Add(); +const IBinaryOpTag& Sub(); +const IBinaryOpTag& Mul(); +const IBinaryOpTag& Div(); +const IBinaryOpTag& Mod(); +const IBinaryOpTag& Lt(); +const IBinaryOpTag& Le(); +const IBinaryOpTag& Gt(); +const IBinaryOpTag& Ge(); +const IBinaryOpTag& Eq(); +const IBinaryOpTag& Ne(); +const IBinaryOpTag& And(); +const IBinaryOpTag& Or(); +const IBinaryOpTag& Xor(); + +// unary +const IUnaryOpTag& Neg(); +const IUnaryOpTag& Plus(); +const IUnaryOpTag& Not(); + +// assign +const IAssignOpTag& RefAssign(); // = +const IAssignOpTag& CopyAssign(); // := +} // namespace OpTags + +} // namespace ovum::compiler::parser + +#endif // PARSER_OPTAGS_HPP_ diff --git a/lib/parser/ast/nodes/stmts/Block.cpp b/lib/parser/ast/nodes/stmts/Block.cpp new file mode 100644 index 0000000..e572b0a --- /dev/null +++ b/lib/parser/ast/nodes/stmts/Block.cpp @@ -0,0 +1,51 @@ +#include "lib/parser/ast/nodes/stmts/Block.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void Block::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +std::vector>& Block::GetStatements() { + return stmts_; +} + +const std::vector>& Block::GetStatements() const { + return stmts_; +} + +void Block::Append(std::unique_ptr statement) { + stmts_.emplace_back(std::move(statement)); +} + +void Block::Insert(std::size_t index, std::unique_ptr statement) { + if (index >= stmts_.size()) { + stmts_.emplace_back(std::move(statement)); + } else { + stmts_.insert(stmts_.begin() + static_cast(index), std::move(statement)); + } +} + +std::unique_ptr Block::ReleaseAt(std::size_t index) { + if (index >= stmts_.size()) { + return nullptr; + } + + auto old_stmt = std::move(stmts_[index]); + stmts_.erase(stmts_.begin() + static_cast(index)); + return old_stmt; +} + +void Block::Clear() noexcept { + stmts_.clear(); +} + +std::size_t Block::Size() const noexcept { + return stmts_.size(); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/Block.hpp b/lib/parser/ast/nodes/stmts/Block.hpp new file mode 100644 index 0000000..046ba3e --- /dev/null +++ b/lib/parser/ast/nodes/stmts/Block.hpp @@ -0,0 +1,32 @@ +#ifndef PARSER_BLOCK_HPP_ +#define PARSER_BLOCK_HPP_ + +#include +#include +#include + +#include "lib/parser/ast/nodes/base/AstNode.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class Block : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + std::vector>& GetStatements(); + const std::vector>& GetStatements() const; + void Append(std::unique_ptr statement); + + void Insert(std::size_t index, std::unique_ptr statement); + std::unique_ptr ReleaseAt(std::size_t index); + void Clear() noexcept; + std::size_t Size() const noexcept; + +private: + std::vector> stmts_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BLOCK_HPP_ diff --git a/lib/parser/ast/nodes/stmts/Branch.cpp b/lib/parser/ast/nodes/stmts/Branch.cpp new file mode 100644 index 0000000..8dbdecf --- /dev/null +++ b/lib/parser/ast/nodes/stmts/Branch.cpp @@ -0,0 +1,43 @@ +#include "lib/parser/ast/nodes/stmts/Branch.hpp" + +#include + +namespace ovum::compiler::parser { + +Branch::Branch(std::unique_ptr condition, std::unique_ptr then_block) : + condition_(std::move(condition)), then_block_(std::move(then_block)) { +} + +const Expr* Branch::Condition() const noexcept { + return condition_.get(); +} + +Expr* Branch::MutableCondition() noexcept { + return condition_.get(); +} + +void Branch::SetCondition(std::unique_ptr expression) { + condition_ = std::move(expression); +} + +std::unique_ptr Branch::ReleaseCondition() { + return std::move(condition_); +} + +const Block* Branch::Then() const noexcept { + return then_block_.get(); +} + +Block* Branch::MutableThen() noexcept { + return then_block_.get(); +} + +void Branch::SetThen(std::unique_ptr then_body) { + then_block_ = std::move(then_body); +} + +std::unique_ptr Branch::ReleaseThen() { + return std::move(then_block_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/Branch.hpp b/lib/parser/ast/nodes/stmts/Branch.hpp new file mode 100644 index 0000000..cc679ff --- /dev/null +++ b/lib/parser/ast/nodes/stmts/Branch.hpp @@ -0,0 +1,37 @@ +#ifndef PARSER_BRANCH_HPP_ +#define PARSER_BRANCH_HPP_ + +#include + +#include "Block.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class Branch { +public: + Branch(std::unique_ptr condition, std::unique_ptr then_block); + Branch(const Branch&) = delete; + Branch& operator=(const Branch&) = delete; + Branch(Branch&&) noexcept = default; + Branch& operator=(Branch&&) noexcept = default; + ~Branch() = default; + + const Expr* Condition() const noexcept; + Expr* MutableCondition() noexcept; + void SetCondition(std::unique_ptr expression); + std::unique_ptr ReleaseCondition(); + + const Block* Then() const noexcept; + Block* MutableThen() noexcept; + void SetThen(std::unique_ptr then_body); + std::unique_ptr ReleaseThen(); + +private: + std::unique_ptr condition_; + std::unique_ptr then_block_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BRANCH_HPP_ diff --git a/lib/parser/ast/nodes/stmts/BreakStmt.cpp b/lib/parser/ast/nodes/stmts/BreakStmt.cpp new file mode 100644 index 0000000..1685231 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/BreakStmt.cpp @@ -0,0 +1,11 @@ +#include "lib/parser/ast/nodes/stmts/BreakStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void BreakStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/BreakStmt.hpp b/lib/parser/ast/nodes/stmts/BreakStmt.hpp new file mode 100644 index 0000000..bf3fbf5 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/BreakStmt.hpp @@ -0,0 +1,15 @@ +#ifndef PARSER_BREAKSTMT_HPP_ +#define PARSER_BREAKSTMT_HPP_ + +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class BreakStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_BREAKSTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/ContinueStmt.cpp b/lib/parser/ast/nodes/stmts/ContinueStmt.cpp new file mode 100644 index 0000000..aa19fc7 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ContinueStmt.cpp @@ -0,0 +1,11 @@ +#include "lib/parser/ast/nodes/stmts/ContinueStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +void ContinueStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/ContinueStmt.hpp b/lib/parser/ast/nodes/stmts/ContinueStmt.hpp new file mode 100644 index 0000000..11ce141 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ContinueStmt.hpp @@ -0,0 +1,15 @@ +#ifndef PARSER_CONTINUESTMT_HPP_ +#define PARSER_CONTINUESTMT_HPP_ + +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class ContinueStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CONTINUESTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/ExprStmt.cpp b/lib/parser/ast/nodes/stmts/ExprStmt.cpp new file mode 100644 index 0000000..80424ef --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ExprStmt.cpp @@ -0,0 +1,29 @@ +#include "lib/parser/ast/nodes/stmts/ExprStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void ExprStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr* ExprStmt::Expression() const noexcept { + return expr_.get(); +} + +Expr* ExprStmt::MutableExpression() noexcept { + return expr_.get(); +} + +void ExprStmt::SetExpression(std::unique_ptr expression) { + expr_ = std::move(expression); +} + +std::unique_ptr ExprStmt::ReleaseExpression() { + return std::move(expr_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/ExprStmt.hpp b/lib/parser/ast/nodes/stmts/ExprStmt.hpp new file mode 100644 index 0000000..420b611 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ExprStmt.hpp @@ -0,0 +1,26 @@ +#ifndef PARSER_EXPRSTMT_HPP_ +#define PARSER_EXPRSTMT_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class ExprStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + const Expr* Expression() const noexcept; + Expr* MutableExpression() noexcept; + void SetExpression(std::unique_ptr expression); + std::unique_ptr ReleaseExpression(); + +private: + std::unique_ptr expr_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_EXPRSTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/ForStmt.cpp b/lib/parser/ast/nodes/stmts/ForStmt.cpp new file mode 100644 index 0000000..3767dbc --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ForStmt.cpp @@ -0,0 +1,53 @@ +#include "lib/parser/ast/nodes/stmts/ForStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void ForStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::string& ForStmt::IteratorName() const noexcept { + return iter_name_; +} + +void ForStmt::SetIteratorName(std::string new_name) { + iter_name_ = std::move(new_name); +} + +const Expr* ForStmt::IteratorExpr() const noexcept { + return iter_expr_.get(); +} + +Expr* ForStmt::MutableIteratorExpr() noexcept { + return iter_expr_.get(); +} + +void ForStmt::SetIteratorExpr(std::unique_ptr expression) { + iter_expr_ = std::move(expression); +} + +std::unique_ptr ForStmt::ReleaseIteratorExpr() { + return std::move(iter_expr_); +} + +const Block* ForStmt::Body() const noexcept { + return body_.get(); +} + +Block* ForStmt::MutableBody() noexcept { + return body_.get(); +} + +void ForStmt::SetBody(std::unique_ptr body_block) { + body_ = std::move(body_block); +} + +std::unique_ptr ForStmt::ReleaseBody() { + return std::move(body_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/ForStmt.hpp b/lib/parser/ast/nodes/stmts/ForStmt.hpp new file mode 100644 index 0000000..954f0e4 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ForStmt.hpp @@ -0,0 +1,37 @@ +#ifndef PARSER_FORSTMT_HPP_ +#define PARSER_FORSTMT_HPP_ + +#include +#include + +#include "Block.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" + +namespace ovum::compiler::parser { + +class ForStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + const std::string& IteratorName() const noexcept; + void SetIteratorName(std::string new_name); + + const Expr* IteratorExpr() const noexcept; + Expr* MutableIteratorExpr() noexcept; + void SetIteratorExpr(std::unique_ptr expression); + std::unique_ptr ReleaseIteratorExpr(); + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr body_block); + std::unique_ptr ReleaseBody(); + +private: + std::string iter_name_; + std::unique_ptr iter_expr_; + std::unique_ptr body_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FORSTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/IfStmt.cpp b/lib/parser/ast/nodes/stmts/IfStmt.cpp new file mode 100644 index 0000000..dd768dd --- /dev/null +++ b/lib/parser/ast/nodes/stmts/IfStmt.cpp @@ -0,0 +1,53 @@ +#include "lib/parser/ast/nodes/stmts/IfStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void IfStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const std::vector& IfStmt::Branches() const noexcept { + return branches_; +} + +std::vector& IfStmt::MutableBranches() noexcept { + return branches_; +} + +void IfStmt::AddBranch(Branch branch_value) { + branches_.emplace_back(std::move(branch_value)); +} + +void IfStmt::EmplaceBranch(std::unique_ptr cond, std::unique_ptr then_blk) { + branches_.emplace_back(std::move(cond), std::move(then_blk)); +} + +const Block* IfStmt::ElseBlock() const noexcept { + return else_block_.get(); +} + +Block* IfStmt::MutableElseBlock() noexcept { + return else_block_.get(); +} + +void IfStmt::SetElseBlock(std::unique_ptr else_body) { + else_block_ = std::move(else_body); +} + +std::unique_ptr IfStmt::ReleaseElseBlock() { + return std::move(else_block_); +} + +bool IfStmt::HasElse() const noexcept { + return static_cast(else_block_); +} + +bool IfStmt::Empty() const noexcept { + return branches_.empty() && !else_block_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/IfStmt.hpp b/lib/parser/ast/nodes/stmts/IfStmt.hpp new file mode 100644 index 0000000..e272bc3 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/IfStmt.hpp @@ -0,0 +1,38 @@ +#ifndef PARSER_IFSTMT_HPP_ +#define PARSER_IFSTMT_HPP_ + +#include +#include + +#include "Block.hpp" +#include "Branch.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class IfStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + const std::vector& Branches() const noexcept; + std::vector& MutableBranches() noexcept; + void AddBranch(Branch branch_value); + void EmplaceBranch(std::unique_ptr cond, std::unique_ptr then_blk); + + const Block* ElseBlock() const noexcept; + Block* MutableElseBlock() noexcept; + void SetElseBlock(std::unique_ptr else_body); + std::unique_ptr ReleaseElseBlock(); + + bool HasElse() const noexcept; + bool Empty() const noexcept; + +private: + std::vector branches_; + std::unique_ptr else_block_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IFSTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/ReturnStmt.cpp b/lib/parser/ast/nodes/stmts/ReturnStmt.cpp new file mode 100644 index 0000000..0ad75a8 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ReturnStmt.cpp @@ -0,0 +1,43 @@ +#include "lib/parser/ast/nodes/stmts/ReturnStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void ReturnStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool ReturnStmt::HasValue() const noexcept { + return value_.has_value() && static_cast(value_.value()); +} + +const Expr* ReturnStmt::Value() const noexcept { + return value_.has_value() ? value_.value().get() : nullptr; +} + +Expr* ReturnStmt::MutableValue() noexcept { + return value_.has_value() ? value_.value().get() : nullptr; +} + +void ReturnStmt::SetValue(std::unique_ptr new_value) { + value_.emplace(std::move(new_value)); +} + +void ReturnStmt::ResetValue() { + value_.reset(); +} + +std::unique_ptr ReturnStmt::ReleaseValue() { + if (!value_.has_value()) { + return nullptr; + } + + auto out = std::move(value_.value()); + value_.reset(); + return out; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/ReturnStmt.hpp b/lib/parser/ast/nodes/stmts/ReturnStmt.hpp new file mode 100644 index 0000000..3437e5a --- /dev/null +++ b/lib/parser/ast/nodes/stmts/ReturnStmt.hpp @@ -0,0 +1,29 @@ +#ifndef PARSER_RETURNSTMT_HPP_ +#define PARSER_RETURNSTMT_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class ReturnStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + bool HasValue() const noexcept; + const Expr* Value() const noexcept; + Expr* MutableValue() noexcept; + void SetValue(std::unique_ptr new_value); + void ResetValue(); + std::unique_ptr ReleaseValue(); + +private: + std::optional> value_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_RETURNSTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/UnsafeBlock.cpp b/lib/parser/ast/nodes/stmts/UnsafeBlock.cpp new file mode 100644 index 0000000..e15365d --- /dev/null +++ b/lib/parser/ast/nodes/stmts/UnsafeBlock.cpp @@ -0,0 +1,29 @@ +#include "lib/parser/ast/nodes/stmts/UnsafeBlock.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void UnsafeBlock::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Block* UnsafeBlock::Body() const noexcept { + return body_.get(); +} + +Block* UnsafeBlock::MutableBody() noexcept { + return body_.get(); +} + +void UnsafeBlock::SetBody(std::unique_ptr body_block) { + body_ = std::move(body_block); +} + +std::unique_ptr UnsafeBlock::ReleaseBody() { + return std::move(body_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/UnsafeBlock.hpp b/lib/parser/ast/nodes/stmts/UnsafeBlock.hpp new file mode 100644 index 0000000..76a8d92 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/UnsafeBlock.hpp @@ -0,0 +1,26 @@ +#ifndef PARSER_UNSAFEBLOCK_HPP_ +#define PARSER_UNSAFEBLOCK_HPP_ + +#include + +#include "Block.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class UnsafeBlock : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr body_block); + std::unique_ptr ReleaseBody(); + +private: + std::unique_ptr body_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_UNSAFEBLOCK_HPP_ diff --git a/lib/parser/ast/nodes/stmts/VarDeclStmt.cpp b/lib/parser/ast/nodes/stmts/VarDeclStmt.cpp new file mode 100644 index 0000000..2d3e9a1 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/VarDeclStmt.cpp @@ -0,0 +1,57 @@ +#include "lib/parser/ast/nodes/stmts/VarDeclStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void VarDeclStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +bool VarDeclStmt::IsVar() const noexcept { + return is_var_; +} + +void VarDeclStmt::SetVar(bool is_var) noexcept { + is_var_ = is_var; +} + +const std::string& VarDeclStmt::Name() const noexcept { + return name_; +} + +void VarDeclStmt::SetName(std::string new_name) { + name_ = std::move(new_name); +} + +const TypeReference& VarDeclStmt::Type() const noexcept { + return type_; +} + +TypeReference& VarDeclStmt::MutableType() noexcept { + return type_; +} + +void VarDeclStmt::SetType(TypeReference new_type) { + type_ = std::move(new_type); +} + +const Expr* VarDeclStmt::Init() const noexcept { + return init_.get(); +} + +Expr* VarDeclStmt::MutableInit() noexcept { + return init_.get(); +} + +void VarDeclStmt::SetInit(std::unique_ptr init_expr) { + init_ = std::move(init_expr); +} + +std::unique_ptr VarDeclStmt::ReleaseInit() { + return std::move(init_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/VarDeclStmt.hpp b/lib/parser/ast/nodes/stmts/VarDeclStmt.hpp new file mode 100644 index 0000000..6c86680 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/VarDeclStmt.hpp @@ -0,0 +1,41 @@ +#ifndef PARSER_VARDECLSTMT_HPP_ +#define PARSER_VARDECLSTMT_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class VarDeclStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + bool IsVar() const noexcept; + void SetVar(bool is_var) noexcept; + + const std::string& Name() const noexcept; + void SetName(std::string new_name); + + const TypeReference& Type() const noexcept; + TypeReference& MutableType() noexcept; + void SetType(TypeReference new_type); + + const Expr* Init() const noexcept; + Expr* MutableInit() noexcept; + void SetInit(std::unique_ptr init_expr); + std::unique_ptr ReleaseInit(); + +private: + bool is_var_ = false; + std::string name_; + TypeReference type_; + std::unique_ptr init_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_VARDECLSTMT_HPP_ diff --git a/lib/parser/ast/nodes/stmts/WhileStmt.cpp b/lib/parser/ast/nodes/stmts/WhileStmt.cpp new file mode 100644 index 0000000..952b0f8 --- /dev/null +++ b/lib/parser/ast/nodes/stmts/WhileStmt.cpp @@ -0,0 +1,45 @@ +#include "lib/parser/ast/nodes/stmts/WhileStmt.hpp" + +#include "lib/parser/ast/AstVisitor.hpp" + +#include + +namespace ovum::compiler::parser { + +void WhileStmt::Accept(AstVisitor& visitor) { + visitor.Visit(*this); +} + +const Expr* WhileStmt::Condition() const noexcept { + return cond_.get(); +} + +Expr* WhileStmt::MutableCondition() noexcept { + return cond_.get(); +} + +void WhileStmt::SetCondition(std::unique_ptr condition_expr) { + cond_ = std::move(condition_expr); +} + +std::unique_ptr WhileStmt::ReleaseCondition() { + return std::move(cond_); +} + +const Block* WhileStmt::Body() const noexcept { + return body_.get(); +} + +Block* WhileStmt::MutableBody() noexcept { + return body_.get(); +} + +void WhileStmt::SetBody(std::unique_ptr body_block) { + body_ = std::move(body_block); +} + +std::unique_ptr WhileStmt::ReleaseBody() { + return std::move(body_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/nodes/stmts/WhileStmt.hpp b/lib/parser/ast/nodes/stmts/WhileStmt.hpp new file mode 100644 index 0000000..8a4c65b --- /dev/null +++ b/lib/parser/ast/nodes/stmts/WhileStmt.hpp @@ -0,0 +1,33 @@ +#ifndef PARSER_WHILESTMT_HPP_ +#define PARSER_WHILESTMT_HPP_ + +#include + +#include "Block.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/ast/nodes/base/Stmt.hpp" + +namespace ovum::compiler::parser { + +class WhileStmt : public Stmt { +public: + void Accept(AstVisitor& visitor) override; + + const Expr* Condition() const noexcept; + Expr* MutableCondition() noexcept; + void SetCondition(std::unique_ptr condition_expr); + std::unique_ptr ReleaseCondition(); + + const Block* Body() const noexcept; + Block* MutableBody() noexcept; + void SetBody(std::unique_ptr body_block); + std::unique_ptr ReleaseBody(); + +private: + std::unique_ptr cond_; + std::unique_ptr body_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_WHILESTMT_HPP_ diff --git a/lib/parser/ast/visitors/ConstWalkVisitor.cpp b/lib/parser/ast/visitors/ConstWalkVisitor.cpp new file mode 100644 index 0000000..37f244e --- /dev/null +++ b/lib/parser/ast/visitors/ConstWalkVisitor.cpp @@ -0,0 +1,274 @@ +#include "ConstWalkVisitor.hpp" + +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/decls/GlobalVarDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" +#include "lib/parser/ast/nodes/decls/TypeAliasDecl.hpp" + +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" + +#include "lib/parser/ast/nodes/exprs/Assign.hpp" +#include "lib/parser/ast/nodes/exprs/Binary.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" +#include "lib/parser/ast/nodes/exprs/CastAs.hpp" +#include "lib/parser/ast/nodes/exprs/Elvis.hpp" +#include "lib/parser/ast/nodes/exprs/FieldAccess.hpp" +#include "lib/parser/ast/nodes/exprs/IdentRef.hpp" +#include "lib/parser/ast/nodes/exprs/IndexAccess.hpp" +#include "lib/parser/ast/nodes/exprs/NamespaceRef.hpp" +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" +#include "lib/parser/ast/nodes/exprs/TypeTestIs.hpp" +#include "lib/parser/ast/nodes/exprs/Unary.hpp" + +#include "lib/parser/ast/nodes/exprs/literals/BoolLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/CharLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/FloatLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/IntLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/NullLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/StringLit.hpp" + +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/ast/nodes/stmts/BreakStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ContinueStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ExprStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ForStmt.hpp" +#include "lib/parser/ast/nodes/stmts/IfStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ReturnStmt.hpp" +#include "lib/parser/ast/nodes/stmts/UnsafeBlock.hpp" +#include "lib/parser/ast/nodes/stmts/VarDeclStmt.hpp" +#include "lib/parser/ast/nodes/stmts/WhileStmt.hpp" + +namespace ovum::compiler::parser { + +void ConstWalkVisitor::Visit(Module& node) { + for (auto& decl_ptr : node.MutableDecls()) { + decl_ptr->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(FunctionDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(ClassDecl& node) { + for (auto& member : node.MutableMembers()) { + member->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(InterfaceMethod& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(InterfaceDecl& node) { + for (auto& m : node.MutableMembers()) { + m->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(TypeAliasDecl& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(GlobalVarDecl& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(FieldDecl& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(StaticFieldDecl& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(MethodDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(CallDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(DestructorDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(Block& node) { + for (auto& stmt : node.GetStatements()) { + stmt->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(VarDeclStmt& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(ExprStmt& node) { + if (auto* e = node.MutableExpression()) { + e->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(ReturnStmt& node) { + if (auto* v = node.MutableValue()) { + v->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(BreakStmt& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(ContinueStmt& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(IfStmt& node) { + for (auto& br : node.MutableBranches()) { + if (auto* c = br.MutableCondition()) { + c->Accept(*this); + } + + if (auto* t = br.MutableThen()) { + t->Accept(*this); + } + } + + if (auto* eb = node.MutableElseBlock()) { + eb->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(WhileStmt& node) { + if (auto* c = node.MutableCondition()) { + c->Accept(*this); + } + + if (auto* b = node.MutableBody()) { + b->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(ForStmt& node) { + if (auto* it = node.MutableIteratorExpr()) { + it->Accept(*this); + } + + if (auto* b = node.MutableBody()) { + b->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(UnsafeBlock& node) { + if (auto* b = node.MutableBody()) { + b->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(Binary& node) { + node.MutableLhs().Accept(*this); + node.MutableRhs().Accept(*this); +} + +void ConstWalkVisitor::Visit(Unary& node) { + node.MutableOperand().Accept(*this); +} + +void ConstWalkVisitor::Visit(Assign& node) { + node.MutableTarget().Accept(*this); + node.MutableValue().Accept(*this); +} + +void ConstWalkVisitor::Visit(Call& node) { + node.MutableCallee().Accept(*this); + for (auto& a : node.MutableArgs()) { + a->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(FieldAccess& node) { + node.MutableObject().Accept(*this); +} + +void ConstWalkVisitor::Visit(IndexAccess& node) { + node.MutableObject().Accept(*this); + node.MutableIndexExpr().Accept(*this); +} + +void ConstWalkVisitor::Visit(NamespaceRef& node) { + node.MutableNamespaceExpr().Accept(*this); +} + +void ConstWalkVisitor::Visit(SafeCall& node) { + node.MutableObject().Accept(*this); + for (auto& a : node.MutableArgs()) { + a->Accept(*this); + } +} + +void ConstWalkVisitor::Visit(Elvis& node) { + node.MutableLhs().Accept(*this); + node.MutableRhs().Accept(*this); +} + +void ConstWalkVisitor::Visit(CastAs& node) { + node.MutableExpression().Accept(*this); +} + +void ConstWalkVisitor::Visit(TypeTestIs& node) { + node.MutableExpression().Accept(*this); +} + +void ConstWalkVisitor::Visit(IdentRef& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(IntLit& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(FloatLit& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(StringLit& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(CharLit& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(BoolLit& node) { + (void) node; +} + +void ConstWalkVisitor::Visit(NullLit& node) { + (void) node; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/visitors/ConstWalkVisitor.hpp b/lib/parser/ast/visitors/ConstWalkVisitor.hpp new file mode 100644 index 0000000..c1b3f6d --- /dev/null +++ b/lib/parser/ast/visitors/ConstWalkVisitor.hpp @@ -0,0 +1,58 @@ +#ifndef PARSER_CONSTWALKVISITOR_HPP_ +#define PARSER_CONSTWALKVISITOR_HPP_ + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +class ConstWalkVisitor : public AstVisitor { +public: + ~ConstWalkVisitor() override = default; + + void Visit(Module& node) override; + void Visit(FunctionDecl& node) override; + void Visit(ClassDecl& node) override; + void Visit(InterfaceMethod& node) override; + void Visit(InterfaceDecl& node) override; + void Visit(TypeAliasDecl& node) override; + void Visit(GlobalVarDecl& node) override; + void Visit(FieldDecl& node) override; + void Visit(StaticFieldDecl& node) override; + void Visit(MethodDecl& node) override; + void Visit(CallDecl& node) override; + void Visit(DestructorDecl& node) override; + + void Visit(Block& node) override; + void Visit(VarDeclStmt& node) override; + void Visit(ExprStmt& node) override; + void Visit(ReturnStmt& node) override; + void Visit(BreakStmt& node) override; + void Visit(ContinueStmt& node) override; + void Visit(IfStmt& node) override; + void Visit(WhileStmt& node) override; + void Visit(ForStmt& node) override; + void Visit(UnsafeBlock& node) override; + + void Visit(Binary& node) override; + void Visit(Unary& node) override; + void Visit(Assign& node) override; + void Visit(Call& node) override; + void Visit(FieldAccess& node) override; + void Visit(IndexAccess& node) override; + void Visit(NamespaceRef& node) override; + void Visit(SafeCall& node) override; + void Visit(Elvis& node) override; + void Visit(CastAs& node) override; + void Visit(TypeTestIs& node) override; + void Visit(IdentRef& node) override; + void Visit(IntLit& node) override; + void Visit(FloatLit& node) override; + void Visit(StringLit& node) override; + void Visit(CharLit& node) override; + void Visit(BoolLit& node) override; + void Visit(NullLit& node) override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CONSTWALKVISITOR_HPP_ diff --git a/lib/parser/ast/visitors/LintVisitor.cpp b/lib/parser/ast/visitors/LintVisitor.cpp new file mode 100644 index 0000000..f7f5d82 --- /dev/null +++ b/lib/parser/ast/visitors/LintVisitor.cpp @@ -0,0 +1,327 @@ +#include "LintVisitor.hpp" + +#include + +#include "lib/parser/diagnostics/severity/Severity.hpp" + +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" + +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/decls/GlobalVarDecl.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" + +#include "lib/parser/ast/nodes/exprs/Assign.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" + +#include "lib/parser/ast/nodes/exprs/literals/BoolLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/StringLit.hpp" + +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/ast/nodes/stmts/BreakStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ContinueStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ExprStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ForStmt.hpp" +#include "lib/parser/ast/nodes/stmts/IfStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ReturnStmt.hpp" +#include "lib/parser/ast/nodes/stmts/UnsafeBlock.hpp" +#include "lib/parser/ast/nodes/stmts/WhileStmt.hpp" + +namespace ovum::compiler::parser { + +void LintVisitor::EnterBody() { + ++nesting_depth_; +} + +void LintVisitor::LeaveBody() { + if (nesting_depth_ > 0) { + --nesting_depth_; + } +} + +void LintVisitor::EnterLoop() { + ++loop_depth_; +} + +void LintVisitor::LeaveLoop() { + if (loop_depth_ > 0) { + --loop_depth_; + } +} + +void LintVisitor::CheckNestingDepth(const SourceSpan&) const { + if (opts_.warn_deep_nesting && nesting_depth_ > opts_.max_nesting) { + sink_.Warn("W0201", "deep nesting"); + } +} + +bool LintVisitor::IsPureExpr(Expr& expression) const { + if (dynamic_cast(&expression)) { + return false; + } + + if (dynamic_cast(&expression)) { + return false; + } + + if (dynamic_cast(&expression)) { + return false; + } + + return true; +} + +void LintVisitor::Visit(Module& node) { + if (opts_.warn_module_without_decls && node.MutableDecls().empty()) { + sink_.Warn("W0001", "module has no declarations"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(ClassDecl& node) { + if (opts_.warn_large_class && node.MutableMembers().size() > opts_.max_class_members) { + sink_.Warn("W0101", "class has too many members"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(FunctionDecl& node) { + if (opts_.warn_empty_bodies) { + if (auto* b = node.MutableBody()) { + if (b->Size() == 0) { + sink_.Warn("W0102", "function body is empty"); + } + } + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(MethodDecl& node) { + if (opts_.warn_empty_bodies) { + if (!node.IsPure()) { + if (auto* b = node.MutableBody()) { + if (b->Size() == 0) { + sink_.Warn("W0103", "method body is empty"); + } + } + } + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(CallDecl& node) { + if (opts_.warn_empty_bodies) { + if (auto* b = node.MutableBody()) { + if (b->Size() == 0) { + sink_.Warn("W0104", "call body is empty"); + } + } + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(DestructorDecl& node) { + if (opts_.warn_empty_bodies) { + if (auto* b = node.MutableBody()) { + if (b->Size() == 0) { + sink_.Warn("W0105", "destructor body is empty"); + } + } + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(Block& node) { + EnterBody(); + + if (opts_.warn_empty_blocks && node.GetStatements().empty()) { + sink_.Warn("W0202", "empty block"); + } + + CheckNestingDepth(); + + bool terminated = false; + if (opts_.warn_unreachable) { + for (const auto& stmt : node.GetStatements()) { + if (terminated) { + sink_.Warn("W0301", "unreachable statement"); + continue; + } + + if (dynamic_cast(stmt.get()) || dynamic_cast(stmt.get()) || + dynamic_cast(stmt.get())) { + terminated = true; + } + } + } + + if (opts_.max_block_len > 0 && node.GetStatements().size() > opts_.max_block_len) { + sink_.Warn("W0203", "block is too long"); + } + + for (auto& stmt : node.GetStatements()) { + stmt->Accept(*this); + } + + LeaveBody(); +} + +void LintVisitor::Visit(ExprStmt& node) { + if (opts_.warn_pure_expr_stmt) { + if (auto* e = node.MutableExpression()) { + if (IsPureExpr(*e)) { + sink_.Warn("W0401", "expression statement has no effect"); + } + } + } + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(ReturnStmt& node) { + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(BreakStmt& node) { + if (opts_.warn_break_continue_outside_loop && loop_depth_ == 0) { + sink_.Error("E0301", "break outside of loop"); + } + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(ContinueStmt& node) { + if (opts_.warn_break_continue_outside_loop && loop_depth_ == 0) { + sink_.Error("E0302", "continue outside of loop"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(IfStmt& node) { + EnterBody(); + + if (opts_.warn_if_without_branches && node.MutableBranches().empty() && !node.HasElse()) { + sink_.Warn("W0501", "if statement has no branches"); + } + + for (auto& br : node.MutableBranches()) { + if (auto* then_blk = br.MutableThen()) { + if (opts_.warn_empty_blocks && then_blk->GetStatements().empty()) { + sink_.Warn("W0502", "then-branch is empty"); + } + } + } + + if (opts_.warn_empty_else && node.HasElse()) { + if (auto* eb = node.MutableElseBlock()) { + if (eb->GetStatements().empty()) { + sink_.Warn("W0503", "else-branch is empty"); + } + } + } + + WalkVisitor::Visit(node); + + LeaveBody(); +} + +void LintVisitor::Visit(WhileStmt& node) { + EnterBody(); + + if (opts_.warn_missing_loop_cond_or_iterable && node.MutableCondition() == nullptr) { + sink_.Error("E0401", "while loop without condition"); + } + + if (opts_.warn_while_true) { + if (auto* cond = node.MutableCondition()) { + if (auto* bl = dynamic_cast(cond)) { + if (bl->Value()) { + sink_.Warn("W0601", "while(true) loop"); + } + } + } + } + + EnterLoop(); + WalkVisitor::Visit(node); + LeaveLoop(); + + LeaveBody(); +} + +void LintVisitor::Visit(ForStmt& node) { + EnterBody(); + + if (opts_.warn_missing_loop_cond_or_iterable && node.MutableIteratorExpr() == nullptr) { + sink_.Error("E0402", "for loop without iterable expression"); + } + + EnterLoop(); + WalkVisitor::Visit(node); + LeaveLoop(); + + LeaveBody(); +} + +void LintVisitor::Visit(UnsafeBlock& node) { + EnterBody(); + if (opts_.warn_empty_blocks) { + if (auto* b = node.MutableBody()) { + if (b->GetStatements().empty()) { + sink_.Warn("W0701", "empty unsafe block"); + } + } + } + + WalkVisitor::Visit(node); + LeaveBody(); +} + +void LintVisitor::Visit(GlobalVarDecl& node) { + if (opts_.warn_mutable_globals && node.IsVar()) { + sink_.Warn("W0801", "mutable global variable"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(FieldDecl& node) { + if (opts_.warn_public_fields && node.IsPublic()) { + sink_.Warn("W0802", "public field"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(StaticFieldDecl& node) { + if (opts_.warn_static_mutable_fields && node.IsVar()) { + sink_.Warn("W0803", "static mutable field"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(StringLit& node) { + if (opts_.warn_empty_string_literal && node.Value().empty()) { + sink_.Warn("W0901", "empty string literal"); + } + + WalkVisitor::Visit(node); +} + +void LintVisitor::Visit(BoolLit& node) { + (void) node; + WalkVisitor::Visit(node); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/visitors/LintVisitor.hpp b/lib/parser/ast/visitors/LintVisitor.hpp new file mode 100644 index 0000000..22cd71c --- /dev/null +++ b/lib/parser/ast/visitors/LintVisitor.hpp @@ -0,0 +1,80 @@ +#ifndef PARSER_LINTVISITOR_HPP_ +#define PARSER_LINTVISITOR_HPP_ + +#include +#include + +#include "WalkVisitor.hpp" + +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" + +namespace ovum::compiler::parser { + +struct LintOptions { + std::size_t max_block_len = 200; + std::size_t max_nesting = 4; + std::size_t max_class_members = 64; + bool warn_empty_blocks = true; + bool warn_public_fields = true; + bool warn_mutable_globals = true; + bool warn_static_mutable_fields = true; + bool warn_unreachable = true; + bool warn_pure_expr_stmt = true; + bool warn_break_continue_outside_loop = true; + bool warn_empty_bodies = true; + bool warn_empty_else = true; + bool warn_missing_loop_cond_or_iterable = true; + bool warn_module_without_decls = true; + bool warn_empty_string_literal = true; + bool warn_deep_nesting = true; + bool warn_large_class = true; + bool warn_if_without_branches = true; + bool warn_while_true = true; +}; + +class LintVisitor : public WalkVisitor { +public: + explicit LintVisitor(IDiagnosticSink& sink, LintOptions options = {}) : sink_(sink), opts_(options) { + } + + void Visit(Module& node) override; + void Visit(ClassDecl& node) override; + void Visit(FunctionDecl& node) override; + void Visit(MethodDecl& node) override; + void Visit(CallDecl& node) override; + void Visit(DestructorDecl& node) override; + + void Visit(Block& node) override; + void Visit(ExprStmt& node) override; + void Visit(ReturnStmt& node) override; + void Visit(BreakStmt& node) override; + void Visit(ContinueStmt& node) override; + void Visit(IfStmt& node) override; + void Visit(WhileStmt& node) override; + void Visit(ForStmt& node) override; + void Visit(UnsafeBlock& node) override; + + void Visit(GlobalVarDecl& node) override; + void Visit(FieldDecl& node) override; + void Visit(StaticFieldDecl& node) override; + + void Visit(StringLit& node) override; + void Visit(BoolLit& node) override; + +private: + bool IsPureExpr(Expr& expression) const; + void EnterBody(); + void LeaveBody(); + void EnterLoop(); + void LeaveLoop(); + void CheckNestingDepth(const SourceSpan& where_hint = {}) const; + + IDiagnosticSink& sink_; + LintOptions opts_; + std::size_t loop_depth_ = 0; + std::size_t nesting_depth_ = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_LINTVISITOR_HPP_ diff --git a/lib/parser/ast/visitors/PrintVisitor.cpp b/lib/parser/ast/visitors/PrintVisitor.cpp new file mode 100644 index 0000000..9f47964 --- /dev/null +++ b/lib/parser/ast/visitors/PrintVisitor.cpp @@ -0,0 +1,421 @@ +#include "PrintVisitor.hpp" + +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" + +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/decls/GlobalVarDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" +#include "lib/parser/ast/nodes/decls/TypeAliasDecl.hpp" + +#include "lib/parser/ast/nodes/stmts/Block.hpp" + +namespace ovum::compiler::parser { + +PrintVisitor::PrintVisitor(std::ostream& output) : out_(&output) { +} + +PrintVisitor::PrintVisitor() : out_(&buffer_), use_buffer_(true) { +} + +std::string PrintVisitor::Str() const { + return buffer_.str(); +} + +void PrintVisitor::WriteIndent() { + for (int i = 0; i < indent_; ++i) { + *out_ << " "; + } +} + +void PrintVisitor::WriteLine(const std::string& text) { + WriteIndent(); + *out_ << text << '\n'; +} + +void PrintVisitor::Open(const std::string& header) { + WriteLine(header + " {"); + ++indent_; +} + +void PrintVisitor::Close() { + --indent_; + WriteLine("}"); +} + +void PrintVisitor::Visit(Module& node) { + Open("Module name=\"" + node.Name() + "\""); + for (auto& declaration : node.MutableDecls()) { + declaration->Accept(*this); + } + Close(); +} + +void PrintVisitor::Visit(FunctionDecl& node) { + Open(std::string("FunctionDecl name=\"") + node.Name() + "\"" + (node.IsPure() ? " pure" : "")); + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } + Close(); +} + +void PrintVisitor::Visit(ClassDecl& node) { + Open(std::string("ClassDecl name=\"") + node.Name() + "\""); + for (auto& member : node.MutableMembers()) { + member->Accept(*this); + } + Close(); +} + +void PrintVisitor::Visit(InterfaceMethod& node) { + WriteLine(std::string("InterfaceMethod name=\"") + node.Name() + "\""); +} + +void PrintVisitor::Visit(InterfaceDecl& node) { + Open(std::string("InterfaceDecl name=\"") + node.Name() + "\""); + for (auto& method_ptr : node.MutableMembers()) { + method_ptr->Accept(*this); + } + Close(); +} + +void PrintVisitor::Visit(TypeAliasDecl& node) { + WriteLine(std::string("TypeAliasDecl name=\"") + node.Name() + "\""); +} + +void PrintVisitor::Visit(GlobalVarDecl& node) { + Open(std::string("GlobalVarDecl ") + (node.IsVar() ? "var" : "val") + " name=\"" + node.Name() + "\""); + if (auto* init_expr = node.MutableInit()) { + init_expr->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(FieldDecl& node) { + Open(std::string("FieldDecl ") + (node.IsVar() ? "var" : "val") + " name=\"" + node.Name() + "\"" + + (node.IsPublic() ? " public" : "")); + if (auto* init_expr = node.MutableInit()) { + init_expr->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(StaticFieldDecl& node) { + Open(std::string("StaticFieldDecl ") + (node.IsVar() ? "var" : "val") + " name=\"" + node.Name() + "\"" + + (node.IsPublic() ? " public" : "")); + if (auto* init_expr = node.MutableInit()) { + init_expr->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(MethodDecl& node) { + std::string flags; + if (node.IsPublic()) { + flags += " public"; + } + + if (node.IsStatic()) { + flags += " static"; + } + + if (node.IsOverride()) { + flags += " override"; + } + + if (node.IsPure()) { + flags += " pure"; + } + + Open("MethodDecl name=\"" + node.Name() + "\"" + flags); + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(CallDecl& node) { + Open(std::string("CallDecl") + (node.IsPublic() ? " public" : "")); + + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(DestructorDecl& node) { + Open(std::string("DestructorDecl") + (node.IsPublic() ? " public" : "")); + + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(Block& node) { + Open("Block"); + + for (auto& statement : node.GetStatements()) { + statement->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(VarDeclStmt& node) { + Open(std::string("VarDeclStmt ") + (node.IsVar() ? "var" : "val") + " name=\"" + node.Name() + "\""); + + if (auto* init_expr = node.MutableInit()) { + init_expr->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(ExprStmt& node) { + Open("ExprStmt"); + + if (auto* expression = node.MutableExpression()) { + expression->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(ReturnStmt& node) { + if (!node.HasValue()) { + WriteLine("ReturnStmt"); + return; + } + + Open("ReturnStmt"); + if (auto* value_expr = node.MutableValue()) { + value_expr->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(BreakStmt& node) { + WriteLine("BreakStmt"); + (void) node; +} + +void PrintVisitor::Visit(ContinueStmt& node) { + WriteLine("ContinueStmt"); + (void) node; +} + +void PrintVisitor::Visit(IfStmt& node) { + Open("IfStmt"); + for (auto& branch_value : node.MutableBranches()) { + Open("Branch"); + + if (auto* cond_expr = branch_value.MutableCondition()) { + Open("Condition"); + cond_expr->Accept(*this); + Close(); + } + + if (auto* then_block = branch_value.MutableThen()) { + Open("Then"); + then_block->Accept(*this); + Close(); + } + + Close(); + } + + if (auto* else_block = node.MutableElseBlock()) { + Open("Else"); + else_block->Accept(*this); + Close(); + } + + Close(); +} + +void PrintVisitor::Visit(WhileStmt& node) { + Open("WhileStmt"); + + if (auto* cond_expr = node.MutableCondition()) { + Open("Condition"); + cond_expr->Accept(*this); + Close(); + } + + if (auto* body_block = node.MutableBody()) { + Open("Body"); + body_block->Accept(*this); + Close(); + } + + Close(); +} + +void PrintVisitor::Visit(ForStmt& node) { + Open(std::string("ForStmt iterator=\"") + node.IteratorName() + "\""); + + if (auto* iter_expr = node.MutableIteratorExpr()) { + Open("Iterable"); + iter_expr->Accept(*this); + Close(); + } + + if (auto* body_block = node.MutableBody()) { + Open("Body"); + body_block->Accept(*this); + Close(); + } + + Close(); +} + +void PrintVisitor::Visit(UnsafeBlock& node) { + Open("UnsafeBlock"); + + if (auto* body_block = node.MutableBody()) { + body_block->Accept(*this); + } + + Close(); +} + +void PrintVisitor::Visit(Binary& node) { + Open(std::string("Binary op=\"") + std::string(node.Op().Name()) + "\""); + node.MutableLhs().Accept(*this); + node.MutableRhs().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(Unary& node) { + Open(std::string("Unary op=\"") + std::string(node.Op().Name()) + "\""); + node.MutableOperand().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(Assign& node) { + Open(std::string("Assign kind=\"") + std::string(node.Kind().Name()) + "\""); + Open("Target"); + node.MutableTarget().Accept(*this); + Close(); + Open("Value"); + node.MutableValue().Accept(*this); + Close(); + Close(); +} + +void PrintVisitor::Visit(Call& node) { + Open("Call"); + Open("Callee"); + node.MutableCallee().Accept(*this); + Close(); + Open("Args"); + + for (auto& argument : node.MutableArgs()) { + argument->Accept(*this); + } + + Close(); + Close(); +} + +void PrintVisitor::Visit(FieldAccess& node) { + Open(std::string("FieldAccess name=\"") + node.Name() + "\""); + node.MutableObject().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(IndexAccess& node) { + Open("IndexAccess"); + Open("Object"); + node.MutableObject().Accept(*this); + Close(); + Open("Index"); + node.MutableIndexExpr().Accept(*this); + Close(); + Close(); +} + +void PrintVisitor::Visit(NamespaceRef& node) { + Open(std::string("NamespaceRef name=\"") + node.Name() + "\""); + node.MutableNamespaceExpr().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(SafeCall& node) { + Open(std::string("SafeCall method=\"") + node.Method() + "\""); + Open("Object"); + node.MutableObject().Accept(*this); + Close(); + Open("Args"); + + for (auto& argument : node.MutableArgs()) { + argument->Accept(*this); + } + + Close(); + Close(); +} + +void PrintVisitor::Visit(Elvis& node) { + Open("Elvis"); + node.MutableLhs().Accept(*this); + node.MutableRhs().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(CastAs& node) { + Open("CastAs"); + node.MutableExpression().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(TypeTestIs& node) { + Open("TypeTestIs"); + node.MutableExpression().Accept(*this); + Close(); +} + +void PrintVisitor::Visit(IdentRef& node) { + WriteLine(std::string("IdentRef name=\"") + node.Name() + "\""); +} + +void PrintVisitor::Visit(IntLit& node) { + WriteLine("IntLit value=" + std::to_string(node.Value())); +} + +void PrintVisitor::Visit(FloatLit& node) { + WriteLine("FloatLit value=" + std::to_string(node.Value())); +} + +void PrintVisitor::Visit(StringLit& node) { + WriteLine(std::string("StringLit value=\"") + node.Value() + "\""); +} + +void PrintVisitor::Visit(CharLit& node) { + std::string printable(1, node.Value()); + WriteLine(std::string("CharLit value='") + printable + "'"); +} + +void PrintVisitor::Visit(BoolLit& node) { + WriteLine(std::string("BoolLit value=") + (node.Value() ? "true" : "false")); +} + +void PrintVisitor::Visit(NullLit& node) { + WriteLine("NullLit"); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/visitors/PrintVisitor.hpp b/lib/parser/ast/visitors/PrintVisitor.hpp new file mode 100644 index 0000000..fef2fce --- /dev/null +++ b/lib/parser/ast/visitors/PrintVisitor.hpp @@ -0,0 +1,78 @@ +#ifndef PARSER_PRINTVISITOR_HPP_ +#define PARSER_PRINTVISITOR_HPP_ + +#include +#include +#include + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +class PrintVisitor : public AstVisitor { +public: + explicit PrintVisitor(std::ostream& output); + PrintVisitor(); + + ~PrintVisitor() override = default; + + std::string Str() const; + + void Visit(Module& node) override; + void Visit(FunctionDecl& node) override; + void Visit(ClassDecl& node) override; + void Visit(InterfaceMethod& node) override; + void Visit(InterfaceDecl& node) override; + void Visit(TypeAliasDecl& node) override; + void Visit(GlobalVarDecl& node) override; + void Visit(FieldDecl& node) override; + void Visit(StaticFieldDecl& node) override; + void Visit(MethodDecl& node) override; + void Visit(CallDecl& node) override; + void Visit(DestructorDecl& node) override; + + void Visit(Block& node) override; + void Visit(VarDeclStmt& node) override; + void Visit(ExprStmt& node) override; + void Visit(ReturnStmt& node) override; + void Visit(BreakStmt& node) override; + void Visit(ContinueStmt& node) override; + void Visit(IfStmt& node) override; + void Visit(WhileStmt& node) override; + void Visit(ForStmt& node) override; + void Visit(UnsafeBlock& node) override; + + void Visit(Binary& node) override; + void Visit(Unary& node) override; + void Visit(Assign& node) override; + void Visit(Call& node) override; + void Visit(FieldAccess& node) override; + void Visit(IndexAccess& node) override; + void Visit(NamespaceRef& node) override; + void Visit(SafeCall& node) override; + void Visit(Elvis& node) override; + void Visit(CastAs& node) override; + void Visit(TypeTestIs& node) override; + void Visit(IdentRef& node) override; + void Visit(IntLit& node) override; + void Visit(FloatLit& node) override; + void Visit(StringLit& node) override; + void Visit(CharLit& node) override; + void Visit(BoolLit& node) override; + void Visit(NullLit& node) override; + +private: + void WriteIndent(); + void WriteLine(const std::string& text); + void Open(const std::string& header); + void Close(); + + std::ostream* out_ = nullptr; + std::ostringstream buffer_; + int indent_ = 0; + bool use_buffer_ = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_PRINTVISITOR_HPP_ diff --git a/lib/parser/ast/visitors/StructuralValidator.cpp b/lib/parser/ast/visitors/StructuralValidator.cpp new file mode 100644 index 0000000..0a9b5b4 --- /dev/null +++ b/lib/parser/ast/visitors/StructuralValidator.cpp @@ -0,0 +1,118 @@ +#include "StructuralValidator.hpp" + +#include "lib/parser/diagnostics/severity/Severity.hpp" + +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" + +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" + +#include "lib/parser/ast/nodes/exprs/Binary.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" +#include "lib/parser/ast/nodes/exprs/FieldAccess.hpp" +#include "lib/parser/ast/nodes/exprs/IndexAccess.hpp" +#include "lib/parser/ast/nodes/exprs/NamespaceRef.hpp" +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" +#include "lib/parser/ast/nodes/exprs/Unary.hpp" + +namespace ovum::compiler::parser { + +void StructuralValidator::Visit(Module& node) { + if (node.Name().empty()) { + sink_.Error("E0001", "module name must not be empty"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(FunctionDecl& node) { + if (!node.IsPure() && node.MutableBody() == nullptr) { + sink_.Error("E1001", "function must have a body"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(ClassDecl& node) { + if (node.Name().empty()) { + sink_.Error("E1002", "class name must not be empty"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(CallDecl& node) { + if (node.MutableBody() == nullptr) { + sink_.Error("E1101", "call declaration must have a body"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(MethodDecl& node) { + if (!node.IsPure() && node.MutableBody() == nullptr) { + sink_.Error("E1201", "method must have a body"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(DestructorDecl& node) { + if (node.MutableBody() == nullptr) { + sink_.Error("E1301", "destructor must have a body"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(Call& node) { + if (&node.MutableCallee() == nullptr) { + sink_.Error("E2001", "call must have callee"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(Binary& node) { + (void) node.MutableLhs(); + (void) node.MutableRhs(); + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(Unary& node) { + (void) node.MutableOperand(); + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(FieldAccess& node) { + (void) node.MutableObject(); + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(IndexAccess& node) { + (void) node.MutableObject(); + (void) node.MutableIndexExpr(); + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(NamespaceRef& node) { + if (node.Name().empty()) { + sink_.Error("E2101", "namespace reference must have name"); + } + + WalkVisitor::Visit(node); +} + +void StructuralValidator::Visit(SafeCall& node) { + if (node.Method().empty()) { + sink_.Error("E2201", "safecall must have method name"); + } + + (void) node.MutableObject(); + WalkVisitor::Visit(node); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/visitors/StructuralValidator.hpp b/lib/parser/ast/visitors/StructuralValidator.hpp new file mode 100644 index 0000000..7079927 --- /dev/null +++ b/lib/parser/ast/visitors/StructuralValidator.hpp @@ -0,0 +1,35 @@ +#ifndef PARSER_STRUCTURALVALIDATOR_HPP_ +#define PARSER_STRUCTURALVALIDATOR_HPP_ + +#include "WalkVisitor.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" + +namespace ovum::compiler::parser { + +class StructuralValidator : public WalkVisitor { +public: + explicit StructuralValidator(IDiagnosticSink& sink) : sink_(sink) { + } + + void Visit(Module& node) override; + void Visit(FunctionDecl& node) override; + void Visit(ClassDecl& node) override; + void Visit(CallDecl& node) override; + void Visit(MethodDecl& node) override; + void Visit(DestructorDecl& node) override; + + void Visit(Call& node) override; + void Visit(Binary& node) override; + void Visit(Unary& node) override; + void Visit(FieldAccess& node) override; + void Visit(IndexAccess& node) override; + void Visit(NamespaceRef& node) override; + void Visit(SafeCall& node) override; + +private: + IDiagnosticSink& sink_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STRUCTURALVALIDATOR_HPP_ diff --git a/lib/parser/ast/visitors/WalkVisitor.cpp b/lib/parser/ast/visitors/WalkVisitor.cpp new file mode 100644 index 0000000..f9d4216 --- /dev/null +++ b/lib/parser/ast/visitors/WalkVisitor.cpp @@ -0,0 +1,274 @@ +#include "WalkVisitor.hpp" + +#include "lib/parser/ast/nodes/decls/ClassDecl.hpp" +#include "lib/parser/ast/nodes/decls/FunctionDecl.hpp" +#include "lib/parser/ast/nodes/decls/GlobalVarDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceDecl.hpp" +#include "lib/parser/ast/nodes/decls/InterfaceMethod.hpp" +#include "lib/parser/ast/nodes/decls/Module.hpp" +#include "lib/parser/ast/nodes/decls/TypeAliasDecl.hpp" + +#include "lib/parser/ast/nodes/class_members/CallDecl.hpp" +#include "lib/parser/ast/nodes/class_members/DestructorDecl.hpp" +#include "lib/parser/ast/nodes/class_members/FieldDecl.hpp" +#include "lib/parser/ast/nodes/class_members/MethodDecl.hpp" +#include "lib/parser/ast/nodes/class_members/StaticFieldDecl.hpp" + +#include "lib/parser/ast/nodes/exprs/Assign.hpp" +#include "lib/parser/ast/nodes/exprs/Binary.hpp" +#include "lib/parser/ast/nodes/exprs/Call.hpp" +#include "lib/parser/ast/nodes/exprs/CastAs.hpp" +#include "lib/parser/ast/nodes/exprs/Elvis.hpp" +#include "lib/parser/ast/nodes/exprs/FieldAccess.hpp" +#include "lib/parser/ast/nodes/exprs/IdentRef.hpp" +#include "lib/parser/ast/nodes/exprs/IndexAccess.hpp" +#include "lib/parser/ast/nodes/exprs/NamespaceRef.hpp" +#include "lib/parser/ast/nodes/exprs/SafeCall.hpp" +#include "lib/parser/ast/nodes/exprs/TypeTestIs.hpp" +#include "lib/parser/ast/nodes/exprs/Unary.hpp" + +#include "lib/parser/ast/nodes/exprs/literals/BoolLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/CharLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/FloatLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/IntLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/NullLit.hpp" +#include "lib/parser/ast/nodes/exprs/literals/StringLit.hpp" + +#include "lib/parser/ast/nodes/stmts/Block.hpp" +#include "lib/parser/ast/nodes/stmts/BreakStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ContinueStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ExprStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ForStmt.hpp" +#include "lib/parser/ast/nodes/stmts/IfStmt.hpp" +#include "lib/parser/ast/nodes/stmts/ReturnStmt.hpp" +#include "lib/parser/ast/nodes/stmts/UnsafeBlock.hpp" +#include "lib/parser/ast/nodes/stmts/VarDeclStmt.hpp" +#include "lib/parser/ast/nodes/stmts/WhileStmt.hpp" + +namespace ovum::compiler::parser { + +void WalkVisitor::Visit(Module& node) { + for (auto& decl_ptr : node.MutableDecls()) { + decl_ptr->Accept(*this); + } +} + +void WalkVisitor::Visit(FunctionDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void WalkVisitor::Visit(ClassDecl& node) { + for (auto& member : node.MutableMembers()) { + member->Accept(*this); + } +} + +void WalkVisitor::Visit(InterfaceMethod& node) { + (void) node; +} + +void WalkVisitor::Visit(InterfaceDecl& node) { + for (auto& m : node.MutableMembers()) { + m->Accept(*this); + } +} + +void WalkVisitor::Visit(TypeAliasDecl& node) { + (void) node; +} + +void WalkVisitor::Visit(GlobalVarDecl& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void WalkVisitor::Visit(FieldDecl& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void WalkVisitor::Visit(StaticFieldDecl& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void WalkVisitor::Visit(MethodDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void WalkVisitor::Visit(CallDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void WalkVisitor::Visit(DestructorDecl& node) { + if (auto* body = node.MutableBody()) { + body->Accept(*this); + } +} + +void WalkVisitor::Visit(Block& node) { + for (auto& stmt : node.GetStatements()) { + stmt->Accept(*this); + } +} + +void WalkVisitor::Visit(VarDeclStmt& node) { + if (auto* init = node.MutableInit()) { + init->Accept(*this); + } +} + +void WalkVisitor::Visit(ExprStmt& node) { + if (auto* e = node.MutableExpression()) { + e->Accept(*this); + } +} + +void WalkVisitor::Visit(ReturnStmt& node) { + if (auto* v = node.MutableValue()) { + v->Accept(*this); + } +} + +void WalkVisitor::Visit(BreakStmt& node) { + (void) node; +} + +void WalkVisitor::Visit(ContinueStmt& node) { + (void) node; +} + +void WalkVisitor::Visit(IfStmt& node) { + for (auto& br : node.MutableBranches()) { + if (auto* c = br.MutableCondition()) { + c->Accept(*this); + } + + if (auto* t = br.MutableThen()) { + t->Accept(*this); + } + } + + if (auto* eb = node.MutableElseBlock()) { + eb->Accept(*this); + } +} + +void WalkVisitor::Visit(WhileStmt& node) { + if (auto* c = node.MutableCondition()) { + c->Accept(*this); + } + + if (auto* b = node.MutableBody()) { + b->Accept(*this); + } +} + +void WalkVisitor::Visit(ForStmt& node) { + if (auto* it = node.MutableIteratorExpr()) { + it->Accept(*this); + } + + if (auto* b = node.MutableBody()) { + b->Accept(*this); + } +} + +void WalkVisitor::Visit(UnsafeBlock& node) { + if (auto* b = node.MutableBody()) { + b->Accept(*this); + } +} + +void WalkVisitor::Visit(Binary& node) { + node.MutableLhs().Accept(*this); + node.MutableRhs().Accept(*this); +} + +void WalkVisitor::Visit(Unary& node) { + node.MutableOperand().Accept(*this); +} + +void WalkVisitor::Visit(Assign& node) { + node.MutableTarget().Accept(*this); + node.MutableValue().Accept(*this); +} + +void WalkVisitor::Visit(Call& node) { + node.MutableCallee().Accept(*this); + for (auto& a : node.MutableArgs()) { + a->Accept(*this); + } +} + +void WalkVisitor::Visit(FieldAccess& node) { + node.MutableObject().Accept(*this); +} + +void WalkVisitor::Visit(IndexAccess& node) { + node.MutableObject().Accept(*this); + node.MutableIndexExpr().Accept(*this); +} + +void WalkVisitor::Visit(NamespaceRef& node) { + node.MutableNamespaceExpr().Accept(*this); +} + +void WalkVisitor::Visit(SafeCall& node) { + node.MutableObject().Accept(*this); + for (auto& a : node.MutableArgs()) { + a->Accept(*this); + } +} + +void WalkVisitor::Visit(Elvis& node) { + node.MutableLhs().Accept(*this); + node.MutableRhs().Accept(*this); +} + +void WalkVisitor::Visit(CastAs& node) { + node.MutableExpression().Accept(*this); +} + +void WalkVisitor::Visit(TypeTestIs& node) { + node.MutableExpression().Accept(*this); +} + +void WalkVisitor::Visit(IdentRef& node) { + (void) node; +} + +void WalkVisitor::Visit(IntLit& node) { + (void) node; +} + +void WalkVisitor::Visit(FloatLit& node) { + (void) node; +} + +void WalkVisitor::Visit(StringLit& node) { + (void) node; +} + +void WalkVisitor::Visit(CharLit& node) { + (void) node; +} + +void WalkVisitor::Visit(BoolLit& node) { + (void) node; +} + +void WalkVisitor::Visit(NullLit& node) { + (void) node; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/ast/visitors/WalkVisitor.hpp b/lib/parser/ast/visitors/WalkVisitor.hpp new file mode 100644 index 0000000..448217a --- /dev/null +++ b/lib/parser/ast/visitors/WalkVisitor.hpp @@ -0,0 +1,58 @@ +#ifndef PARSER_WALKVISITOR_HPP_ +#define PARSER_WALKVISITOR_HPP_ + +#include "lib/parser/ast/AstVisitor.hpp" + +namespace ovum::compiler::parser { + +class WalkVisitor : public AstVisitor { +public: + ~WalkVisitor() override = default; + + void Visit(Module& node) override; + void Visit(FunctionDecl& node) override; + void Visit(ClassDecl& node) override; + void Visit(InterfaceMethod& node) override; + void Visit(InterfaceDecl& node) override; + void Visit(TypeAliasDecl& node) override; + void Visit(GlobalVarDecl& node) override; + void Visit(FieldDecl& node) override; + void Visit(StaticFieldDecl& node) override; + void Visit(MethodDecl& node) override; + void Visit(CallDecl& node) override; + void Visit(DestructorDecl& node) override; + + void Visit(Block& node) override; + void Visit(VarDeclStmt& node) override; + void Visit(ExprStmt& node) override; + void Visit(ReturnStmt& node) override; + void Visit(BreakStmt& node) override; + void Visit(ContinueStmt& node) override; + void Visit(IfStmt& node) override; + void Visit(WhileStmt& node) override; + void Visit(ForStmt& node) override; + void Visit(UnsafeBlock& node) override; + + void Visit(Binary& node) override; + void Visit(Unary& node) override; + void Visit(Assign& node) override; + void Visit(Call& node) override; + void Visit(FieldAccess& node) override; + void Visit(IndexAccess& node) override; + void Visit(NamespaceRef& node) override; + void Visit(SafeCall& node) override; + void Visit(Elvis& node) override; + void Visit(CastAs& node) override; + void Visit(TypeTestIs& node) override; + void Visit(IdentRef& node) override; + void Visit(IntLit& node) override; + void Visit(FloatLit& node) override; + void Visit(StringLit& node) override; + void Visit(CharLit& node) override; + void Visit(BoolLit& node) override; + void Visit(NullLit& node) override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_WALKVISITOR_HPP_ diff --git a/lib/parser/context/ContextParser.cpp b/lib/parser/context/ContextParser.cpp new file mode 100644 index 0000000..c205a19 --- /dev/null +++ b/lib/parser/context/ContextParser.cpp @@ -0,0 +1,90 @@ +#include "ContextParser.hpp" + +#include + +namespace ovum::compiler::parser { + +std::vector& ContextParser::StateStack() { + return state_stack_; +} + +std::vector& ContextParser::NodeStack() { + return node_stack_; +} + +void ContextParser::SetDiagnostics(IDiagnosticSink* diagnostics) { + diags_ = diagnostics; +} + +IDiagnosticSink* ContextParser::Diags() const { + return diags_; +} + +void ContextParser::SetExpr(IExpressionParser* parser) { + expr_ = parser; +} + +IExpressionParser* ContextParser::Expr() const { + return expr_; +} + +void ContextParser::SetTypeParser(ITypeParser* parser) { + typep_ = parser; +} + +ITypeParser* ContextParser::TypeParser() const { + return typep_; +} + +void ContextParser::PushState(const IState& state) { + state_stack_.push_back(&state); +} + +void ContextParser::PopState() { + if (!state_stack_.empty()) { + state_stack_.pop_back(); + } +} + +const IState* ContextParser::CurrentState() const { + if (state_stack_.empty()) { + return nullptr; + } + return state_stack_.back(); +} + +void ContextParser::PushNode(std::unique_ptr node) { + node_stack_.emplace_back(std::move(node)); +} + +std::unique_ptr ContextParser::PopNode() { + if (node_stack_.empty()) { + return nullptr; + } + auto node = node_stack_.back().ReleaseNode(); + node_stack_.pop_back(); + return node; +} + +bool ContextParser::HasStates() const noexcept { + return !state_stack_.empty(); +} + +bool ContextParser::HasNodes() const noexcept { + return !node_stack_.empty(); +} + +void ContextParser::Clear() { + state_stack_.clear(); + node_stack_.clear(); +} + +void ContextParser::SetFactory(IAstFactory* factory) { + factory_ = factory; +} + +IAstFactory* ContextParser::Factory() const { + return factory_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/context/ContextParser.hpp b/lib/parser/context/ContextParser.hpp new file mode 100644 index 0000000..095ce9d --- /dev/null +++ b/lib/parser/context/ContextParser.hpp @@ -0,0 +1,70 @@ +#ifndef PARSER_CONTEXTPARSER_HPP_ +#define PARSER_CONTEXTPARSER_HPP_ + +#include +#include +#include + +#include "NodeEntry.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/states/base/IState.hpp" + +namespace ovum::compiler::parser { + +class AstNode; +class IExpressionParser; +class ITypeParser; +class IAstFactory; // forward + +template +concept AstNodeDerived = std::is_base_of_v; + +class ContextParser { +public: + std::vector& StateStack(); + std::vector& NodeStack(); + + void SetDiagnostics(IDiagnosticSink* diagnostics); + IDiagnosticSink* Diags() const; + + void SetExpr(IExpressionParser* parser); + IExpressionParser* Expr() const; + + void SetTypeParser(ITypeParser* parser); + ITypeParser* TypeParser() const; + + void SetFactory(IAstFactory* factory); + IAstFactory* Factory() const; + + void PushState(const IState& state); + void PopState(); + const IState* CurrentState() const; + + template + T* TopNodeAs() { + if (node_stack_.empty()) { + return nullptr; + } + + return dynamic_cast(node_stack_.back().MutableNode()); + } + + void PushNode(std::unique_ptr node); + std::unique_ptr PopNode(); + + bool HasStates() const noexcept; + bool HasNodes() const noexcept; + void Clear(); + +private: + std::vector state_stack_; + std::vector node_stack_; + IDiagnosticSink* diags_ = nullptr; + IExpressionParser* expr_ = nullptr; + ITypeParser* typep_ = nullptr; + IAstFactory* factory_ = nullptr; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_CONTEXTPARSER_HPP_ diff --git a/lib/parser/context/NodeEntry.cpp b/lib/parser/context/NodeEntry.cpp new file mode 100644 index 0000000..659e4d7 --- /dev/null +++ b/lib/parser/context/NodeEntry.cpp @@ -0,0 +1,26 @@ +#include "NodeEntry.hpp" + +#include + +namespace ovum::compiler::parser { + +NodeEntry::NodeEntry(std::unique_ptr node) : node_(std::move(node)) { +} + +const AstNode* NodeEntry::GetNode() const noexcept { + return node_.get(); +} + +AstNode* NodeEntry::MutableNode() noexcept { + return node_.get(); +} + +void NodeEntry::SetNode(std::unique_ptr node) { + node_ = std::move(node); +} + +std::unique_ptr NodeEntry::ReleaseNode() { + return std::move(node_); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/context/NodeEntry.hpp b/lib/parser/context/NodeEntry.hpp new file mode 100644 index 0000000..0261c30 --- /dev/null +++ b/lib/parser/context/NodeEntry.hpp @@ -0,0 +1,26 @@ +#ifndef PARSER_NODEENTRY_HPP_ +#define PARSER_NODEENTRY_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/AstNode.hpp" + +namespace ovum::compiler::parser { + +class NodeEntry { +public: + NodeEntry() = default; + explicit NodeEntry(std::unique_ptr node); + + const AstNode* GetNode() const noexcept; + AstNode* MutableNode() noexcept; + void SetNode(std::unique_ptr node); + std::unique_ptr ReleaseNode(); + +private: + std::unique_ptr node_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_NODEENTRY_HPP_ diff --git a/lib/parser/diagnostics/Diagnostic.cpp b/lib/parser/diagnostics/Diagnostic.cpp new file mode 100644 index 0000000..21bdf3f --- /dev/null +++ b/lib/parser/diagnostics/Diagnostic.cpp @@ -0,0 +1,129 @@ +#include "Diagnostic.hpp" + +#include + +namespace ovum::compiler::parser { + +Diagnostic::Diagnostic() = default; + +Diagnostic::Diagnostic(std::shared_ptr sev, std::string code, std::string message) : + severity_(std::move(sev)), code_(std::move(code)), message_(std::move(message)) { +} + +Diagnostic::Diagnostic(const Diagnostic& other) = default; + +Diagnostic::Diagnostic(Diagnostic&& other) noexcept : + severity_(std::move(other.severity_)), code_(std::move(other.code_)), message_(std::move(other.message_)), + category_(std::move(other.category_)), where_(std::move(other.where_)), notes_(std::move(other.notes_)), + fixes_(std::move(other.fixes_)), is_fatal_(other.is_fatal_), is_suppressed_(other.is_suppressed_) { +} + +Diagnostic& Diagnostic::operator=(const Diagnostic& other) { + if (this == &other) { + return *this; + } + + severity_ = other.severity_; + code_ = other.code_; + message_ = other.message_; + category_ = other.category_; + where_ = other.where_; + notes_ = other.notes_; + fixes_ = other.fixes_; + is_fatal_ = other.is_fatal_; + is_suppressed_ = other.is_suppressed_; + return *this; +} + +Diagnostic& Diagnostic::operator=(Diagnostic&& other) noexcept { + if (this == &other) { + return *this; + } + + severity_ = std::move(other.severity_); + code_ = std::move(other.code_); + message_ = std::move(other.message_); + category_ = std::move(other.category_); + where_ = std::move(other.where_); + notes_ = std::move(other.notes_); + fixes_ = std::move(other.fixes_); + is_fatal_ = other.is_fatal_; + is_suppressed_ = other.is_suppressed_; + return *this; +} + +Diagnostic::~Diagnostic() = default; + +void Diagnostic::SetSeverity(std::shared_ptr sev) { + severity_ = std::move(sev); +} +const std::shared_ptr& Diagnostic::GetSeverity() const noexcept { + return severity_; +} + +void Diagnostic::SetCode(std::string c) { + code_ = std::move(c); +} +const std::string& Diagnostic::GetCode() const noexcept { + return code_; +} + +void Diagnostic::SetMessage(std::string m) { + message_ = std::move(m); +} +const std::string& Diagnostic::GetMessage() const noexcept { + return message_; +} + +void Diagnostic::SetCategory(std::string cat) { + category_ = std::move(cat); +} +const std::string& Diagnostic::GetCategory() const noexcept { + return category_; +} + +void Diagnostic::SetWhere(SourceSpan sp) { + where_ = std::move(sp); +} +void Diagnostic::ResetWhere() { + where_.reset(); +} +const std::optional& Diagnostic::GetWhere() const noexcept { + return where_; +} + +void Diagnostic::AddNote(RelatedInfo note) { + notes_.emplace_back(std::move(note)); +} +void Diagnostic::ClearNotes() { + notes_.clear(); +} +const std::vector& Diagnostic::GetNotes() const noexcept { + return notes_; +} + +void Diagnostic::AddFix(FixIt fix) { + fixes_.emplace_back(std::move(fix)); +} +void Diagnostic::ClearFixes() { + fixes_.clear(); +} +const std::vector& Diagnostic::GetFixes() const noexcept { + return fixes_; +} + +void Diagnostic::SetFatal(bool on) { + is_fatal_ = on; +} +bool Diagnostic::IsFatal() const noexcept { + return is_fatal_; +} + +void Diagnostic::SetSuppressed(bool on) { + is_suppressed_ = on; +} +bool Diagnostic::IsSuppressed() const noexcept { + return is_suppressed_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/diagnostics/Diagnostic.hpp b/lib/parser/diagnostics/Diagnostic.hpp new file mode 100644 index 0000000..d4b766d --- /dev/null +++ b/lib/parser/diagnostics/Diagnostic.hpp @@ -0,0 +1,70 @@ +#ifndef PARSER_DIAGNOSTIC_HPP_ +#define PARSER_DIAGNOSTIC_HPP_ + +#include +#include +#include +#include + +#include "FixIt.hpp" +#include "RelatedInfo.hpp" +#include "lib/parser/tokens/SourceSpan.hpp" +#include "severity/ISeverity.hpp" + +namespace ovum::compiler::parser { + +class Diagnostic { +public: + Diagnostic(); + Diagnostic(std::shared_ptr sev, std::string code, std::string message); + Diagnostic(const Diagnostic& other); + Diagnostic(Diagnostic&& other) noexcept; + Diagnostic& operator=(const Diagnostic& other); + Diagnostic& operator=(Diagnostic&& other) noexcept; + ~Diagnostic(); + + void SetSeverity(std::shared_ptr sev); + [[nodiscard]] const std::shared_ptr& GetSeverity() const noexcept; + + void SetCode(std::string c); + [[nodiscard]] const std::string& GetCode() const noexcept; + + void SetMessage(std::string m); + [[nodiscard]] const std::string& GetMessage() const noexcept; + + void SetCategory(std::string cat); + [[nodiscard]] const std::string& GetCategory() const noexcept; + + void SetWhere(SourceSpan sp); + void ResetWhere(); + [[nodiscard]] const std::optional& GetWhere() const noexcept; + + void AddNote(RelatedInfo note); + void ClearNotes(); + [[nodiscard]] const std::vector& GetNotes() const noexcept; + + void AddFix(FixIt fix); + void ClearFixes(); + [[nodiscard]] const std::vector& GetFixes() const noexcept; + + void SetFatal(bool on); + [[nodiscard]] bool IsFatal() const noexcept; + + void SetSuppressed(bool on); + [[nodiscard]] bool IsSuppressed() const noexcept; + +private: + std::shared_ptr severity_; + std::string code_; + std::string message_; + std::string category_; + std::optional where_; + std::vector notes_; + std::vector fixes_; + bool is_fatal_ = false; + bool is_suppressed_ = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_DIAGNOSTIC_HPP_ diff --git a/lib/parser/diagnostics/DiagnosticCollector.cpp b/lib/parser/diagnostics/DiagnosticCollector.cpp new file mode 100644 index 0000000..43991ff --- /dev/null +++ b/lib/parser/diagnostics/DiagnosticCollector.cpp @@ -0,0 +1,158 @@ +#include "lib/parser/diagnostics/DiagnosticCollector.hpp" + +#include + +#include "lib/parser/diagnostics/severity/Severity.hpp" + +namespace ovum::compiler::parser { + +void DiagnosticCollector::Report(Diagnostic d) { + bool suppressed = !ShouldKeep(d); + d.SetSuppressed(suppressed); + if (suppressed) { + return; + } + + if (dedup_ && IsDuplicate(d)) { + return; + } + + if (capacity_ && diags_.size() >= *capacity_) { + return; + } + + int err_level = Severity::Error()->Level(); + int warn_level = Severity::Warning()->Level(); + int level = d.GetSeverity() ? d.GetSeverity()->Level() : 0; + + if (level >= err_level) { + if (error_limit_ && errors_ >= *error_limit_) { + return; + } + + ++errors_; + } else if (level >= warn_level) { + if (warning_limit_ && warnings_ >= *warning_limit_) { + return; + } + + ++warnings_; + } + + diags_.emplace_back(std::move(d)); +} + +bool DiagnosticCollector::HasErrors() const { + return errors_ > 0; +} +std::size_t DiagnosticCollector::Count() const { + return diags_.size(); +} +std::size_t DiagnosticCollector::ErrorCount() const { + return errors_; +} +std::size_t DiagnosticCollector::WarningCount() const { + return warnings_; +} + +void DiagnosticCollector::Note(std::string_view code, std::string_view msg, std::optional where) { + Diagnostic d{Severity::Note(), std::string{code}, std::string{msg}}; + if (where) { + d.SetWhere(*where); + } + + Report(std::move(d)); +} + +void DiagnosticCollector::Warn(std::string_view code, std::string_view msg, std::optional where) { + Diagnostic d{Severity::Warning(), std::string{code}, std::string{msg}}; + if (where) { + d.SetWhere(*where); + } + + Report(std::move(d)); +} + +void DiagnosticCollector::Error(std::string_view code, std::string_view msg, std::optional where) { + Diagnostic d{Severity::Error(), std::string{code}, std::string{msg}}; + if (where) { + d.SetWhere(*where); + } + + Report(std::move(d)); +} + +const std::vector& DiagnosticCollector::All() const { + return diags_; +} + +void DiagnosticCollector::Clear() { + diags_.clear(); + errors_ = 0; + warnings_ = 0; +} + +void DiagnosticCollector::SuppressCode(std::string code) { + suppressed_codes_.insert(std::move(code)); +} + +void DiagnosticCollector::SuppressCategory(std::string category) { + suppressed_categories_.insert(std::move(category)); +} + +void DiagnosticCollector::SetGlobalFilter(Predicate p) { + global_filter_ = std::move(p); +} + +void DiagnosticCollector::ResetGlobalFilter() { + global_filter_.reset(); +} + +void DiagnosticCollector::EnableDeduplication(bool on) { + dedup_ = on; +} + +void DiagnosticCollector::SetCapacity(std::optional max_total) { + capacity_ = max_total; +} + +void DiagnosticCollector::SetErrorLimit(std::optional max_errors) { + error_limit_ = max_errors; +} + +void DiagnosticCollector::SetWarningLimit(std::optional max_warnings) { + warning_limit_ = max_warnings; +} + +bool DiagnosticCollector::IsSuppressed(const Diagnostic& d) const { + if (!d.GetCode().empty() && suppressed_codes_.count(d.GetCode()) > 0) { + return true; + } + + if (!d.GetCategory().empty() && suppressed_categories_.count(d.GetCategory()) > 0) { + return true; + } + + if (global_filter_ && !(*global_filter_)(d)) { + return true; + } + + return false; +} + +bool DiagnosticCollector::ShouldKeep(const Diagnostic& d) const { + return !IsSuppressed(d); +} + +bool DiagnosticCollector::IsDuplicate(const Diagnostic& d) const { + for (const auto& prev : diags_) { + if (prev.GetCode() == d.GetCode() && prev.GetMessage() == d.GetMessage() && + ((prev.GetSeverity() && d.GetSeverity()) ? prev.GetSeverity()->Level() == d.GetSeverity()->Level() + : prev.GetSeverity() == d.GetSeverity())) { + return true; + } + } + return false; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/diagnostics/DiagnosticCollector.hpp b/lib/parser/diagnostics/DiagnosticCollector.hpp new file mode 100644 index 0000000..9ed4f7c --- /dev/null +++ b/lib/parser/diagnostics/DiagnosticCollector.hpp @@ -0,0 +1,67 @@ +#ifndef PARSER_DIAGNOSTICCOLLECTOR_HPP_ +#define PARSER_DIAGNOSTICCOLLECTOR_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "IDiagnosticSink.hpp" + +namespace ovum::compiler::parser { + +class DiagnosticCollector : public IDiagnosticSink { +public: + using Predicate = std::function; + + ~DiagnosticCollector() override = default; + + void Report(Diagnostic d) override; + bool HasErrors() const override; + std::size_t Count() const override; + std::size_t ErrorCount() const override; + std::size_t WarningCount() const override; + + void Note(std::string_view code, std::string_view msg, std::optional where = std::nullopt) override; + void Warn(std::string_view code, std::string_view msg, std::optional where = std::nullopt) override; + void Error(std::string_view code, std::string_view msg, std::optional where = std::nullopt) override; + + const std::vector& All() const; + void Clear(); + + void SuppressCode(std::string code); + void SuppressCategory(std::string category); + void SetGlobalFilter(Predicate p); + void ResetGlobalFilter(); + void EnableDeduplication(bool on); + + void SetCapacity(std::optional max_total); + void SetErrorLimit(std::optional max_errors); + void SetWarningLimit(std::optional max_warnings); + + bool IsSuppressed(const Diagnostic& d) const; + +private: + bool ShouldKeep(const Diagnostic& d) const; + bool IsDuplicate(const Diagnostic& d) const; + + std::vector diags_; + std::unordered_set suppressed_codes_; + std::unordered_set suppressed_categories_; + std::optional global_filter_; + + bool dedup_ = true; + std::optional capacity_; + std::optional error_limit_; + std::optional warning_limit_; + + std::size_t errors_ = 0; + std::size_t warnings_ = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_DIAGNOSTICCOLLECTOR_HPP_ diff --git a/lib/parser/diagnostics/FixIt.cpp b/lib/parser/diagnostics/FixIt.cpp new file mode 100644 index 0000000..f110531 --- /dev/null +++ b/lib/parser/diagnostics/FixIt.cpp @@ -0,0 +1,11 @@ +#include "lib/parser/diagnostics/FixIt.hpp" + +#include + +namespace ovum::compiler::parser { + +FixIt::FixIt(SourceSpan source_span, std::string replacement) : + where_(std::move(source_span)), replacement_(std::move(replacement)) { +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/diagnostics/FixIt.hpp b/lib/parser/diagnostics/FixIt.hpp new file mode 100644 index 0000000..fcd23f2 --- /dev/null +++ b/lib/parser/diagnostics/FixIt.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_FIXIT_HPP_ +#define PARSER_FIXIT_HPP_ + +#include + +#include "lib/parser/tokens/SourceSpan.hpp" + +namespace ovum::compiler::parser { + +class FixIt { +public: + FixIt(SourceSpan source_span, std::string replacement); + +private: + SourceSpan where_; + std::string replacement_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_FIXIT_HPP_ diff --git a/lib/parser/diagnostics/IDiagnosticSink.hpp b/lib/parser/diagnostics/IDiagnosticSink.hpp new file mode 100644 index 0000000..a9bfe62 --- /dev/null +++ b/lib/parser/diagnostics/IDiagnosticSink.hpp @@ -0,0 +1,31 @@ +#ifndef PARSER_IDIAGNOSTICSINK_HPP_ +#define PARSER_IDIAGNOSTICSINK_HPP_ + +#include +#include +#include + +#include "Diagnostic.hpp" +#include "lib/parser/tokens/SourceSpan.hpp" + +namespace ovum::compiler::parser { + +class IDiagnosticSink { +public: + virtual ~IDiagnosticSink() = default; + + virtual void Report(Diagnostic d) = 0; + + virtual bool HasErrors() const = 0; + virtual std::size_t Count() const = 0; + virtual std::size_t ErrorCount() const = 0; + virtual std::size_t WarningCount() const = 0; + + virtual void Note(std::string_view code, std::string_view msg, std::optional where = std::nullopt) = 0; + virtual void Warn(std::string_view code, std::string_view msg, std::optional where = std::nullopt) = 0; + virtual void Error(std::string_view code, std::string_view msg, std::optional where = std::nullopt) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IDIAGNOSTICSINK_HPP_ diff --git a/lib/parser/diagnostics/RelatedInfo.cpp b/lib/parser/diagnostics/RelatedInfo.cpp new file mode 100644 index 0000000..6878cad --- /dev/null +++ b/lib/parser/diagnostics/RelatedInfo.cpp @@ -0,0 +1,11 @@ +#include "lib/parser/diagnostics/RelatedInfo.hpp" + +#include + +namespace ovum::compiler::parser { + +RelatedInfo::RelatedInfo(std::string&& message, SourceSpan&& span) : + message_(std::move(message)), where_(std::move(span)) { +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/diagnostics/RelatedInfo.hpp b/lib/parser/diagnostics/RelatedInfo.hpp new file mode 100644 index 0000000..7ec6707 --- /dev/null +++ b/lib/parser/diagnostics/RelatedInfo.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_RELATEDINFO_HPP_ +#define PARSER_RELATEDINFO_HPP_ + +#include +#include + +#include "lib/parser/tokens/SourceSpan.hpp" + +namespace ovum::compiler::parser { + +class RelatedInfo { +public: + RelatedInfo(std::string&& message, SourceSpan&& span); + +private: + std::string message_; + std::optional where_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_RELATEDINFO_HPP_ diff --git a/lib/parser/diagnostics/severity/ISeverity.hpp b/lib/parser/diagnostics/severity/ISeverity.hpp new file mode 100644 index 0000000..1738dcf --- /dev/null +++ b/lib/parser/diagnostics/severity/ISeverity.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_ISEVERITY_HPP_ +#define PARSER_ISEVERITY_HPP_ + +#include + +namespace ovum::compiler::parser { + +class ISeverity { +public: + virtual ~ISeverity() = default; + virtual std::string_view Name() const = 0; + virtual int Level() const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ISEVERITY_HPP_ diff --git a/lib/parser/diagnostics/severity/Severity.cpp b/lib/parser/diagnostics/severity/Severity.cpp new file mode 100644 index 0000000..860ef58 --- /dev/null +++ b/lib/parser/diagnostics/severity/Severity.cpp @@ -0,0 +1,49 @@ +#include "lib/parser/diagnostics/severity/Severity.hpp" + +#include +#include +#include +#include + +namespace ovum::compiler::parser { + +namespace { +class SimpleSeverity : public ISeverity { +public: + SimpleSeverity(std::string name, int level) : name_(std::move(name)), level_(level) { + } + + [[nodiscard]] std::string_view Name() const override { + return name_; + } + + [[nodiscard]] int Level() const override { + return level_; + } + +private: + std::string name_; + int level_; +}; +} // namespace + +const std::shared_ptr& Severity::Note() { + static const auto kInst = std::make_shared("note", 10); + return kInst; +} + +const std::shared_ptr& Severity::Warning() { + static const auto kInst = std::make_shared("warning", 20); + return kInst; +} + +const std::shared_ptr& Severity::Error() { + static const auto kInst = std::make_shared("error", 30); + return kInst; +} + +std::shared_ptr Severity::Custom(std::string_view name, int level) { + return std::make_shared(std::string{name}, level); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/diagnostics/severity/Severity.hpp b/lib/parser/diagnostics/severity/Severity.hpp new file mode 100644 index 0000000..c7bfa8b --- /dev/null +++ b/lib/parser/diagnostics/severity/Severity.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_SEVERITY_HPP_ +#define PARSER_SEVERITY_HPP_ + +#include +#include + +#include "ISeverity.hpp" + +namespace ovum::compiler::parser { + +class Severity { +public: + static const std::shared_ptr& Note(); + static const std::shared_ptr& Warning(); + static const std::shared_ptr& Error(); + + static std::shared_ptr Custom(std::string_view name, int level); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_SEVERITY_HPP_ diff --git a/lib/parser/pratt/DefaultOperatorResolver.cpp b/lib/parser/pratt/DefaultOperatorResolver.cpp new file mode 100644 index 0000000..d5ccde1 --- /dev/null +++ b/lib/parser/pratt/DefaultOperatorResolver.cpp @@ -0,0 +1,145 @@ +#include "lib/parser/pratt/DefaultOperatorResolver.hpp" + +#include +#include + +#include "lib/parser/ast/nodes/exprs/tags/OpTags.hpp" + +namespace ovum::compiler::parser { + +namespace { +bool LexIs(const Token& t, std::string_view s) { + return t.GetLexeme() == s; +} + +constexpr int kBP_Assign = 10; +constexpr int kBP_Elvis = 20; // right-assoc +constexpr int kBP_Or = 30; +constexpr int kBP_And = 40; +constexpr int kBP_Xor = 50; +constexpr int kBP_Eq = 60; +constexpr int kBP_Rel = 70; +constexpr int kBP_Add = 80; +constexpr int kBP_Mul = 90; +constexpr int kBP_Post = 100; + +std::vector& InfixTable() { + static std::vector specs; + if (!specs.empty()) { + return specs; + } + + auto add = [&](std::string_view lex, int bp, const IBinaryOpTag& tag) { + InfixSpec s(bp, bp, false, const_cast(&tag), false); + s.SetMatcher([lex](const Token& t) { return LexIs(t, lex); }); + specs.push_back(std::move(s)); + }; + + add("+", kBP_Add, OpTags::Add()); + add("-", kBP_Add, OpTags::Sub()); + add("*", kBP_Mul, OpTags::Mul()); + add("/", kBP_Mul, OpTags::Div()); + add("%", kBP_Mul, OpTags::Mod()); + + add("==", kBP_Eq, OpTags::Eq()); + add("!=", kBP_Eq, OpTags::Ne()); + + add("<", kBP_Rel, OpTags::Lt()); + add("<=", kBP_Rel, OpTags::Le()); + add(">", kBP_Rel, OpTags::Gt()); + add(">=", kBP_Rel, OpTags::Ge()); + + add("&&", kBP_And, OpTags::And()); + add("||", kBP_Or, OpTags::Or()); + add("^", kBP_Xor, OpTags::Xor()); + + { + InfixSpec elvis(kBP_Elvis, kBP_Elvis - 1, true, nullptr, true); + elvis.SetMatcher([](const Token& t) { return LexIs(t, "?:"); }); + specs.push_back(std::move(elvis)); + } + + return specs; +} + +std::vector& PostfixTable() { + static std::vector specs; + if (!specs.empty()) { + return specs; + } + + specs.emplace_back([](const Token& t) { return LexIs(t, "("); }, kBP_Post, false); + specs.emplace_back([](const Token& t) { return LexIs(t, "."); }, kBP_Post, false); + specs.emplace_back([](const Token& t) { return LexIs(t, "?."); }, kBP_Post, false); + specs.emplace_back([](const Token& t) { return LexIs(t, "as"); }, kBP_Post, true); + specs.emplace_back([](const Token& t) { return LexIs(t, "is"); }, kBP_Post, true); + specs.emplace_back([](const Token& t) { return LexIs(t, "::"); }, kBP_Post, false); + + return specs; +} + +const IUnaryOpTag* MatchPrefix(const Token& t) { + if (LexIs(t, "-")) { + return &OpTags::Neg(); + } + + if (LexIs(t, "+")) { + return &OpTags::Plus(); + } + + if (LexIs(t, "!")) { + return &OpTags::Not(); + } + + return nullptr; +} + +} // namespace + +std::optional> DefaultOperatorResolver::FindInfix(const Token& t) const { + auto& tbl = InfixTable(); + for (const auto& s : tbl) { + if (s.TryMatch(t)) { + return std::cref(s); + } + } + + return std::nullopt; +} + +std::optional> DefaultOperatorResolver::FindPostfix(const Token& t) const { + auto& tbl = PostfixTable(); + for (const auto& s : tbl) { + if (s.TryMatch(t)) { + return std::cref(s); + } + } + + return std::nullopt; +} + +std::optional> DefaultOperatorResolver::FindPrefix(const Token& t) const { + if (auto* tag = MatchPrefix(t)) { + return std::cref(*tag); + } + + return std::nullopt; +} + +bool DefaultOperatorResolver::IsContinuation(const Token& t) const { + if (FindInfix(t).has_value()) { + return true; + } + + if (FindPostfix(t).has_value()) { + return true; + } + + const auto& lx = t.GetLexeme(); + if (lx == "(" || lx == "[") { + return true; + } + return false; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/pratt/DefaultOperatorResolver.hpp b/lib/parser/pratt/DefaultOperatorResolver.hpp new file mode 100644 index 0000000..30aa0ec --- /dev/null +++ b/lib/parser/pratt/DefaultOperatorResolver.hpp @@ -0,0 +1,32 @@ +#ifndef PARSER_DEFAULTOPERATORRESOLVER_HPP_ +#define PARSER_DEFAULTOPERATORRESOLVER_HPP_ + +#include +#include +#include + +#include "IOperatorResolver.hpp" +#include "lib/parser/ast/nodes/exprs/tags/IUnaryOpTag.hpp" +#include "specifications/InfixSpec.hpp" +#include "specifications/PostfixSpec.hpp" +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class DefaultOperatorResolver : public IOperatorResolver { +public: + ~DefaultOperatorResolver() override = default; + + std::optional> FindInfix(const Token& t) const override; + std::optional> FindPostfix(const Token& t) const override; + std::optional> FindPrefix(const Token& t) const override; + bool IsContinuation(const Token& t) const override; + +private: + std::vector infix_; + std::vector postfix_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_DEFAULTOPERATORRESOLVER_HPP_ diff --git a/lib/parser/pratt/IExpressionParser.hpp b/lib/parser/pratt/IExpressionParser.hpp new file mode 100644 index 0000000..4cdc336 --- /dev/null +++ b/lib/parser/pratt/IExpressionParser.hpp @@ -0,0 +1,21 @@ +#ifndef PARSER_IEXPRESSIONPARSER_HPP_ +#define PARSER_IEXPRESSIONPARSER_HPP_ + +#include + +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class IExpressionParser { +public: + virtual ~IExpressionParser() = default; + + virtual std::unique_ptr Parse(ITokenStream& ts, IDiagnosticSink& diags) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IEXPRESSIONPARSER_HPP_ diff --git a/lib/parser/pratt/IOperatorResolver.hpp b/lib/parser/pratt/IOperatorResolver.hpp new file mode 100644 index 0000000..35346b9 --- /dev/null +++ b/lib/parser/pratt/IOperatorResolver.hpp @@ -0,0 +1,25 @@ +#ifndef PARSER_IOPERATORRESOLVER_HPP_ +#define PARSER_IOPERATORRESOLVER_HPP_ + +#include +#include + +#include "lib/parser/ast/nodes/exprs/tags/IUnaryOpTag.hpp" +#include "specifications/InfixSpec.hpp" +#include "specifications/PostfixSpec.hpp" + +namespace ovum::compiler::parser { + +class IOperatorResolver { +public: + virtual ~IOperatorResolver() = default; + + virtual std::optional> FindInfix(const Token& t) const = 0; + virtual std::optional> FindPostfix(const Token& t) const = 0; + virtual std::optional> FindPrefix(const Token& t) const = 0; + virtual bool IsContinuation(const Token& t) const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IOPERATORRESOLVER_HPP_ diff --git a/lib/parser/pratt/PrattExpressionParser.cpp b/lib/parser/pratt/PrattExpressionParser.cpp new file mode 100644 index 0000000..a655b5b --- /dev/null +++ b/lib/parser/pratt/PrattExpressionParser.cpp @@ -0,0 +1,353 @@ +#include "PrattExpressionParser.hpp" + +#include +#include +#include + +#include +#include "lib/parser/ast/nodes/exprs/tags/OpTags.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/pratt/specifications/InfixSpec.hpp" +#include "lib/parser/pratt/specifications/PostfixSpec.hpp" + +namespace ovum::compiler::parser { + +namespace { + +constexpr int kBP_Assign = 5; // right-assoc +constexpr int kBP_Elvis = 20; // right-assoc +constexpr int kBP_Post = 100; // postfix + +bool Lex(const Token& t, std::string_view s) { + return t.GetLexeme() == s; +} + +bool IsIdentifier(const Token& t) { + return t.GetStringType() == "IDENT"; +} + +bool IsLiteral(const Token& t) { + const std::string ty = t.GetStringType(); + return ty.rfind("LITERAL", 0) == 0; // "LITERAL:*" +} + +} // namespace + +PrattExpressionParser::PrattExpressionParser(std::unique_ptr resolver, + std::shared_ptr factory) : + resolver_(std::move(resolver)), factory_(std::move(factory)) { +} + +std::unique_ptr PrattExpressionParser::Parse(ITokenStream& ts, IDiagnosticSink& diags) { + return ParseExpr(ts, diags, 0); +} + +std::unique_ptr PrattExpressionParser::ParseExpr(ITokenStream& ts, IDiagnosticSink& diags, int min_bp) { + std::unique_ptr left = ParsePrefix(ts, diags); + if (!left) { + return nullptr; + } + + while (!ts.IsEof()) { + const Token& look = ts.Peek(); + const auto post = resolver_->FindPostfix(look); + if (!post.has_value()) { + break; + } + + const int bp = post->get().BindingPower(); + if (bp < min_bp) { + break; + } + + left = ParsePostfix(ts, diags, std::move(left)); + if (!left) { + return nullptr; + } + } + + while (!ts.IsEof()) { + const Token& look = ts.Peek(); + + const bool is_ref_assign = Lex(look, "="); + const bool is_copy_assign = Lex(look, ":="); + if (is_ref_assign || is_copy_assign) { + if (kBP_Assign < min_bp) { + break; + } + + ts.Consume(); + + std::unique_ptr rhs = ParseExpr(ts, diags, kBP_Assign - 1); // right-assoc + if (!rhs) { + return nullptr; + } + + left = factory_->MakeAssign( + is_ref_assign ? OpTags::RefAssign() : OpTags::CopyAssign(), std::move(left), std::move(rhs)); + + while (!ts.IsEof()) { + const Token& next = ts.Peek(); + const auto post2 = resolver_->FindPostfix(next); + if (!post2.has_value() || post2->get().BindingPower() < min_bp) { + break; + } + + left = ParsePostfix(ts, diags, std::move(left)); + if (!left) { + return nullptr; + } + } + continue; + } + + const auto inf = resolver_->FindInfix(look); + if (!inf.has_value()) { + break; + } + + const int lbp = inf->get().Lbp(); + if (lbp < min_bp) { + break; + } + + if (inf->get().IsElvis()) { + ts.Consume(); // ?: + std::unique_ptr rhs = ParseExpr(ts, diags, inf->get().Rbp()); + if (!rhs) { + return nullptr; + } + + left = factory_->MakeElvis(std::move(left), std::move(rhs)); + } else { + const IBinaryOpTag* tag = inf->get().Tag(); + if (tag == nullptr) { + diags.Error("E_EXPR_OP", "internal: infix without tag"); + return nullptr; + } + + ts.Consume(); + + const int next_min = inf->get().IsRightAssociative() ? inf->get().Rbp() : inf->get().Rbp() + 1; + + std::unique_ptr rhs = ParseExpr(ts, diags, next_min); + if (!rhs) { + return nullptr; + } + + left = factory_->MakeBinary(*tag, std::move(left), std::move(rhs)); + } + + while (!ts.IsEof()) { + const Token& next2 = ts.Peek(); + const auto post3 = resolver_->FindPostfix(next2); + if (!post3.has_value() || post3->get().BindingPower() < min_bp) { + break; + } + + left = ParsePostfix(ts, diags, std::move(left)); + if (!left) { + return nullptr; + } + } + } + + return left; +} + +std::unique_ptr PrattExpressionParser::ParsePrefix(ITokenStream& ts, IDiagnosticSink& diags) { + if (ts.IsEof()) { + diags.Error("E_EXPR_EOF", "unexpected end of input"); + return nullptr; + } + + const Token& look = ts.Peek(); + + if (auto pre = resolver_->FindPrefix(look)) { + ts.Consume(); + std::unique_ptr operand = ParseExpr(ts, diags, kBP_Post - 1); + if (!operand) { + return nullptr; + } + + return factory_->MakeUnary(pre->get(), std::move(operand)); + } + + if (Lex(look, "(")) { + ts.Consume(); + std::unique_ptr inner = ParseExpr(ts, diags, 0); + if (!inner) { + return nullptr; + } + + if (ts.IsEof() || !Lex(ts.Peek(), ")")) { + diags.Error("E_EXPR_GROUP", "expected ')'"); + return nullptr; + } + + ts.Consume(); + return inner; + } + + if (IsIdentifier(look)) { + std::string name = look.GetLexeme(); + ts.Consume(); + return factory_->MakeIdentRef(std::move(name)); + } + + if (IsLiteral(look)) { + std::unique_ptr lit = factory_->MakeLiteralFromToken(look); + ts.Consume(); + return lit; + } + + diags.Error("E_EXPR_PRIMARY", "expected primary expression"); + return nullptr; +} + +std::unique_ptr PrattExpressionParser::ParsePostfix(ITokenStream& ts, + IDiagnosticSink& diags, + std::unique_ptr base) { + if (!base) { + return nullptr; + } + + if (ts.IsEof()) { + return base; + } + + const Token& look = ts.Peek(); + + if (Lex(look, "(")) { + ts.Consume(); + auto args = ParseArgList(ts, diags, ')'); + if (args.empty() && (ts.IsEof() || !Lex(ts.Peek(), ")"))) { + diags.Error("E_CALL_CLOSE", "expected ')'"); + return nullptr; + } + + if (!ts.IsEof() && Lex(ts.Peek(), ")")) { + ts.Consume(); + } + + return factory_->MakeCall(std::move(base), std::move(args)); + } + + if (Lex(look, ".")) { + ts.Consume(); + + if (ts.IsEof() || !IsIdentifier(ts.Peek())) { + diags.Error("E_DOT_IDENT", "expected identifier after '.'"); + return nullptr; + } + + std::string member = ts.Peek().GetLexeme(); + ts.Consume(); + + if (!ts.IsEof() && Lex(ts.Peek(), "(")) { + ts.Consume(); + auto args = ParseArgList(ts, diags, ')'); + if (args.empty() && (ts.IsEof() || !Lex(ts.Peek(), ")"))) { + diags.Error("E_CALL_CLOSE", "expected ')'"); + return nullptr; + } + + if (!ts.IsEof() && Lex(ts.Peek(), ")")) { + ts.Consume(); + } + + auto callee = factory_->MakeFieldAccess(std::move(base), std::move(member)); + return factory_->MakeCall(std::move(callee), std::move(args)); + } + + return factory_->MakeFieldAccess(std::move(base), std::move(member)); + } + + if (Lex(look, "?.")) { + ts.Consume(); + + if (ts.IsEof() || !IsIdentifier(ts.Peek())) { + diags.Error("E_SAFECALL_IDENT", "expected identifier after '?.'"); + return nullptr; + } + + std::string method = ts.Peek().GetLexeme(); + ts.Consume(); + + std::vector> args; + if (!ts.IsEof() && Lex(ts.Peek(), "(")) { + ts.Consume(); + args = ParseArgList(ts, diags, ')'); + + if (args.empty() && (ts.IsEof() || !Lex(ts.Peek(), ")"))) { + diags.Error("E_CALL_CLOSE", "expected ')'"); + return nullptr; + } + + if (!ts.IsEof() && Lex(ts.Peek(), ")")) { + ts.Consume(); + } + } + + return factory_->MakeSafeCall(std::move(base), std::move(method), std::move(args)); + } + + if (Lex(look, "::")) { + ts.Consume(); + if (ts.IsEof() || !IsIdentifier(ts.Peek())) { + diags.Error("E_NS_IDENT", "expected identifier after '::'"); + return nullptr; + } + + std::string ident = ts.Peek().GetLexeme(); + ts.Consume(); + return factory_->MakeNamespaceRef(std::move(base), std::move(ident)); + } + + if (Lex(look, "as") || Lex(look, "is")) { + diags.Error("E_TYPE_POSTFIX", "type postfix ('as'/'is') requires type parser"); + return nullptr; + } + + return base; +} + +std::vector> PrattExpressionParser::ParseArgList(ITokenStream& ts, + IDiagnosticSink& diags, + char closing) { + std::vector> result; + + if (!ts.IsEof() && ts.Peek().GetLexeme().size() == 1 && ts.Peek().GetLexeme()[0] == closing) { + return result; + } + + if (auto arg = ParseExpr(ts, diags, 0)) { + result.push_back(std::move(arg)); + } else { + return {}; + } + + while (!ts.IsEof() && ts.Peek().GetLexeme() == ",") { + ts.Consume(); + auto arg = ParseExpr(ts, diags, 0); + + if (!arg) { + return {}; + } + + result.push_back(std::move(arg)); + } + + return result; +} + +std::unique_ptr PrattExpressionParser::MakeInfix(const InfixSpec& spec, + std::unique_ptr lhs, + std::unique_ptr rhs) { + if (spec.IsElvis()) { + return factory_->MakeElvis(std::move(lhs), std::move(rhs)); + } + return factory_->MakeBinary(*spec.Tag(), std::move(lhs), std::move(rhs)); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/pratt/PrattExpressionParser.hpp b/lib/parser/pratt/PrattExpressionParser.hpp new file mode 100644 index 0000000..daadd0b --- /dev/null +++ b/lib/parser/pratt/PrattExpressionParser.hpp @@ -0,0 +1,38 @@ +#ifndef PARSER_PRATTEXPRESSIONPARSER_HPP_ +#define PARSER_PRATTEXPRESSIONPARSER_HPP_ + +#include +#include + +#include "IExpressionParser.hpp" +#include "IOperatorResolver.hpp" +#include "lib/parser/ast/IAstFactory.hpp" +#include "lib/parser/ast/nodes/base/Expr.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class PrattExpressionParser : public IExpressionParser { +public: + explicit PrattExpressionParser(std::unique_ptr resolver, std::shared_ptr factory); + ~PrattExpressionParser() override = default; + + std::unique_ptr Parse(ITokenStream& ts, IDiagnosticSink& diags) override; + + std::unique_ptr ParseExpr(ITokenStream& ts, IDiagnosticSink& diags, int min_bp); + std::unique_ptr ParsePrefix(ITokenStream& ts, IDiagnosticSink& diags); + std::unique_ptr ParsePostfix(ITokenStream& ts, IDiagnosticSink& diags, std::unique_ptr base); + + std::vector> ParseArgList(ITokenStream& ts, IDiagnosticSink& diags, char closing); + +private: + std::unique_ptr MakeInfix(const InfixSpec& spec, std::unique_ptr lhs, std::unique_ptr rhs); + + std::unique_ptr resolver_; + std::shared_ptr factory_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_PRATTEXPRESSIONPARSER_HPP_ diff --git a/lib/parser/pratt/specifications/InfixSpec.cpp b/lib/parser/pratt/specifications/InfixSpec.cpp new file mode 100644 index 0000000..e13c1f4 --- /dev/null +++ b/lib/parser/pratt/specifications/InfixSpec.cpp @@ -0,0 +1,49 @@ +#include "InfixSpec.hpp" + +namespace ovum::compiler::parser { + +InfixSpec::InfixSpec(int left_bp, int right_bp, bool right_associative, IBinaryOpTag* tag, bool is_elvis) : + lbp_(left_bp), rbp_(right_bp), right_associative_(right_associative), tag_(tag), is_elvis_(is_elvis) { +} + +void InfixSpec::SetMatcher(std::function matcher) { + match_ = std::move(matcher); +} + +bool InfixSpec::TryMatch(const Token& token) const { + return match_ ? match_(token) : false; +} + +int InfixSpec::Lbp() const noexcept { + return lbp_; +} +int InfixSpec::Rbp() const noexcept { + return rbp_; +} +bool InfixSpec::IsRightAssociative() const noexcept { + return right_associative_; +} +const IBinaryOpTag* InfixSpec::Tag() const noexcept { + return tag_; +} +bool InfixSpec::IsElvis() const noexcept { + return is_elvis_; +} + +void InfixSpec::SetLbp(int v) noexcept { + lbp_ = v; +} +void InfixSpec::SetRbp(int v) noexcept { + rbp_ = v; +} +void InfixSpec::SetRightAssociative(bool v) noexcept { + right_associative_ = v; +} +void InfixSpec::SetTag(const IBinaryOpTag* t) noexcept { + tag_ = t; +} +void InfixSpec::SetElvis(bool v) noexcept { + is_elvis_ = v; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/pratt/specifications/InfixSpec.hpp b/lib/parser/pratt/specifications/InfixSpec.hpp new file mode 100644 index 0000000..cdad620 --- /dev/null +++ b/lib/parser/pratt/specifications/InfixSpec.hpp @@ -0,0 +1,41 @@ +#ifndef PARSER_INFIXSPEC_HPP_ +#define PARSER_INFIXSPEC_HPP_ + +#include + +#include "lib/parser/ast/nodes/exprs/tags/IBinaryOpTag.hpp" +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class InfixSpec { +public: + InfixSpec(int left_bp, int right_bp, bool right_associative, IBinaryOpTag* tag, bool is_elvis); + + void SetMatcher(std::function matcher); + bool TryMatch(const Token& token) const; + + int Lbp() const noexcept; + int Rbp() const noexcept; + bool IsRightAssociative() const noexcept; + const IBinaryOpTag* Tag() const noexcept; + bool IsElvis() const noexcept; + + void SetLbp(int v) noexcept; + void SetRbp(int v) noexcept; + void SetRightAssociative(bool v) noexcept; + void SetTag(const IBinaryOpTag* t) noexcept; + void SetElvis(bool v) noexcept; + +private: + std::function match_; + int lbp_ = 0; + int rbp_ = 0; + bool right_associative_ = false; + const IBinaryOpTag* tag_ = nullptr; + bool is_elvis_ = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_INFIXSPEC_HPP_ diff --git a/lib/parser/pratt/specifications/PostfixSpec.cpp b/lib/parser/pratt/specifications/PostfixSpec.cpp new file mode 100644 index 0000000..b506eb6 --- /dev/null +++ b/lib/parser/pratt/specifications/PostfixSpec.cpp @@ -0,0 +1,27 @@ +#include "PostfixSpec.hpp" + +namespace ovum::compiler::parser { + +PostfixSpec::PostfixSpec(std::function match, int bp, bool keyword) : + match_(std::move(match)), bp_(bp), keyword_(keyword) { +} + +bool PostfixSpec::TryMatch(const Token& token) const { + return match_ ? match_(token) : false; +} + +int PostfixSpec::BindingPower() const noexcept { + return bp_; +} +bool PostfixSpec::IsKeyword() const noexcept { + return keyword_; +} + +void PostfixSpec::SetBindingPower(int v) noexcept { + bp_ = v; +} +void PostfixSpec::SetKeyword(bool v) noexcept { + keyword_ = v; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/pratt/specifications/PostfixSpec.hpp b/lib/parser/pratt/specifications/PostfixSpec.hpp new file mode 100644 index 0000000..806bbc6 --- /dev/null +++ b/lib/parser/pratt/specifications/PostfixSpec.hpp @@ -0,0 +1,30 @@ +#ifndef PARSER_POSTFIXSPEC_HPP_ +#define PARSER_POSTFIXSPEC_HPP_ + +#include + +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class PostfixSpec { +public: + PostfixSpec(std::function match, int bp, bool keyword); + + bool TryMatch(const Token& token) const; + + int BindingPower() const noexcept; + bool IsKeyword() const noexcept; + + void SetBindingPower(int v) noexcept; + void SetKeyword(bool v) noexcept; + +private: + std::function match_; + int bp_ = 0; + bool keyword_ = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_POSTFIXSPEC_HPP_ diff --git a/lib/parser/recovery/IRecoveryStrategy.hpp b/lib/parser/recovery/IRecoveryStrategy.hpp new file mode 100644 index 0000000..8df9f3e --- /dev/null +++ b/lib/parser/recovery/IRecoveryStrategy.hpp @@ -0,0 +1,18 @@ +#ifndef PARSER_IRECOVERYSTRATEGY_HPP_ +#define PARSER_IRECOVERYSTRATEGY_HPP_ + +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class IRecoveryStrategy { +public: + virtual ~IRecoveryStrategy() { + } + virtual void SyncToStmtEnd(ITokenStream& ts) = 0; + virtual void SyncToBlockEnd(ITokenStream& ts) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_IRECOVERYSTRATEGY_HPP_ diff --git a/lib/parser/recovery/SimpleRecovery.cpp b/lib/parser/recovery/SimpleRecovery.cpp new file mode 100644 index 0000000..9d07422 --- /dev/null +++ b/lib/parser/recovery/SimpleRecovery.cpp @@ -0,0 +1,58 @@ +#include "lib/parser/recovery/SimpleRecovery.hpp" + +#include +#include + +namespace ovum::compiler::parser { +namespace { +bool IsLex(const Token& tok, std::string_view lex) { + return tok.GetLexeme() == lex; +} +} // namespace + +void SimpleRecovery::SyncToStmtEnd(ITokenStream& ts) { + while (!ts.IsEof()) { + const auto* look = ts.TryPeek(); + if (look == nullptr) { + break; + } + if (IsLex(*look, "\n")) { + ts.Consume(); + break; + } + if (IsLex(*look, ";")) { + ts.Consume(); + break; + } + if (IsLex(*look, "}")) { + break; + } + ts.Consume(); + } +} + +void SimpleRecovery::SyncToBlockEnd(ITokenStream& ts) { + int depth = 0; + while (!ts.IsEof()) { + const auto* look = ts.TryPeek(); + if (look == nullptr) { + break; + } + if (IsLex(*look, "{")) { + ++depth; + ts.Consume(); + continue; + } + if (IsLex(*look, "}")) { + ts.Consume(); + if (depth == 0) { + break; + } + --depth; + continue; + } + ts.Consume(); + } +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/recovery/SimpleRecovery.hpp b/lib/parser/recovery/SimpleRecovery.hpp new file mode 100644 index 0000000..737662a --- /dev/null +++ b/lib/parser/recovery/SimpleRecovery.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_SIMPLERECOVERY_HPP_ +#define PARSER_SIMPLERECOVERY_HPP_ + +#include "IRecoveryStrategy.hpp" + +namespace ovum::compiler::parser { + +class SimpleRecovery : public IRecoveryStrategy { +public: + ~SimpleRecovery() override = default; + + void SyncToStmtEnd(ITokenStream& ts) override; + void SyncToBlockEnd(ITokenStream& ts) override; + + void SyncToStatementEnd(ITokenStream& ts) { + SyncToStmtEnd(ts); + } // alias +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_SIMPLERECOVERY_HPP_ diff --git a/lib/parser/states/StateBlock.cpp b/lib/parser/states/StateBlock.cpp new file mode 100644 index 0000000..39f5929 --- /dev/null +++ b/lib/parser/states/StateBlock.cpp @@ -0,0 +1,3 @@ +#include "StateBlock.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateBlock.hpp b/lib/parser/states/StateBlock.hpp new file mode 100644 index 0000000..861dff6 --- /dev/null +++ b/lib/parser/states/StateBlock.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEBLOCK_HPP_ +#define PARSER_STATEBLOCK_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateBlock : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEBLOCK_HPP_ diff --git a/lib/parser/states/StateCallDeclHdr.cpp b/lib/parser/states/StateCallDeclHdr.cpp new file mode 100644 index 0000000..bef8fc0 --- /dev/null +++ b/lib/parser/states/StateCallDeclHdr.cpp @@ -0,0 +1,3 @@ +#include "StateCallDeclHdr.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateCallDeclHdr.hpp b/lib/parser/states/StateCallDeclHdr.hpp new file mode 100644 index 0000000..57d1ad9 --- /dev/null +++ b/lib/parser/states/StateCallDeclHdr.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATECALLDECLHDR_HPP_ +#define PARSER_STATECALLDECLHDR_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateCallDeclHdr : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATECALLDECLHDR_HPP_ diff --git a/lib/parser/states/StateDestructorDecl.cpp b/lib/parser/states/StateDestructorDecl.cpp new file mode 100644 index 0000000..d054df6 --- /dev/null +++ b/lib/parser/states/StateDestructorDecl.cpp @@ -0,0 +1,3 @@ +#include "StateDestructorDecl.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateDestructorDecl.hpp b/lib/parser/states/StateDestructorDecl.hpp new file mode 100644 index 0000000..acac97d --- /dev/null +++ b/lib/parser/states/StateDestructorDecl.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEDESTRUCTORDECL_HPP_ +#define PARSER_STATEDESTRUCTORDECL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateDestructorDecl : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEDESTRUCTORDECL_HPP_ diff --git a/lib/parser/states/StateExpr.cpp b/lib/parser/states/StateExpr.cpp new file mode 100644 index 0000000..732bb7e --- /dev/null +++ b/lib/parser/states/StateExpr.cpp @@ -0,0 +1,3 @@ +#include "StateExpr.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateExpr.hpp b/lib/parser/states/StateExpr.hpp new file mode 100644 index 0000000..44a3647 --- /dev/null +++ b/lib/parser/states/StateExpr.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEEXPR_HPP_ +#define PARSER_STATEEXPR_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateExpr : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEEXPR_HPP_ diff --git a/lib/parser/states/StateFieldDecl.cpp b/lib/parser/states/StateFieldDecl.cpp new file mode 100644 index 0000000..ad88b6e --- /dev/null +++ b/lib/parser/states/StateFieldDecl.cpp @@ -0,0 +1,3 @@ +#include "StateFieldDecl.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateFieldDecl.hpp b/lib/parser/states/StateFieldDecl.hpp new file mode 100644 index 0000000..aab6a9a --- /dev/null +++ b/lib/parser/states/StateFieldDecl.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEFIELDDECL_HPP_ +#define PARSER_STATEFIELDDECL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateFieldDecl : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEFIELDDECL_HPP_ diff --git a/lib/parser/states/StateForHead.cpp b/lib/parser/states/StateForHead.cpp new file mode 100644 index 0000000..cae61dc --- /dev/null +++ b/lib/parser/states/StateForHead.cpp @@ -0,0 +1,3 @@ +#include "StateForHead.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateForHead.hpp b/lib/parser/states/StateForHead.hpp new file mode 100644 index 0000000..c536be3 --- /dev/null +++ b/lib/parser/states/StateForHead.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEFORHEAD_HPP_ +#define PARSER_STATEFORHEAD_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateForHead : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEFORHEAD_HPP_ diff --git a/lib/parser/states/StateGlobalVarDecl.cpp b/lib/parser/states/StateGlobalVarDecl.cpp new file mode 100644 index 0000000..767bacd --- /dev/null +++ b/lib/parser/states/StateGlobalVarDecl.cpp @@ -0,0 +1,3 @@ +#include "StateGlobalVarDecl.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateGlobalVarDecl.hpp b/lib/parser/states/StateGlobalVarDecl.hpp new file mode 100644 index 0000000..a79b2cc --- /dev/null +++ b/lib/parser/states/StateGlobalVarDecl.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEGLOBALVARDECL_HPP_ +#define PARSER_STATEGLOBALVARDECL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateGlobalVarDecl : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEGLOBALVARDECL_HPP_ diff --git a/lib/parser/states/StateIfHead.cpp b/lib/parser/states/StateIfHead.cpp new file mode 100644 index 0000000..250ddad --- /dev/null +++ b/lib/parser/states/StateIfHead.cpp @@ -0,0 +1,3 @@ +#include "StateIfHead.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateIfHead.hpp b/lib/parser/states/StateIfHead.hpp new file mode 100644 index 0000000..2f629db --- /dev/null +++ b/lib/parser/states/StateIfHead.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEIFHEAD_HPP_ +#define PARSER_STATEIFHEAD_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateIfHead : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEIFHEAD_HPP_ diff --git a/lib/parser/states/StateIfTail.cpp b/lib/parser/states/StateIfTail.cpp new file mode 100644 index 0000000..0025258 --- /dev/null +++ b/lib/parser/states/StateIfTail.cpp @@ -0,0 +1,3 @@ +#include "StateIfTail.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateIfTail.hpp b/lib/parser/states/StateIfTail.hpp new file mode 100644 index 0000000..ed502bd --- /dev/null +++ b/lib/parser/states/StateIfTail.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEIFTAIL_HPP_ +#define PARSER_STATEIFTAIL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateIfTail : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEIFTAIL_HPP_ diff --git a/lib/parser/states/StateMethodHdr.cpp b/lib/parser/states/StateMethodHdr.cpp new file mode 100644 index 0000000..a896051 --- /dev/null +++ b/lib/parser/states/StateMethodHdr.cpp @@ -0,0 +1,3 @@ +#include "StateMethodHdr.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateMethodHdr.hpp b/lib/parser/states/StateMethodHdr.hpp new file mode 100644 index 0000000..e53ca24 --- /dev/null +++ b/lib/parser/states/StateMethodHdr.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEMETHODHDR_HPP_ +#define PARSER_STATEMETHODHDR_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateMethodHdr : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEMETHODHDR_HPP_ diff --git a/lib/parser/states/StateModule.cpp b/lib/parser/states/StateModule.cpp new file mode 100644 index 0000000..6789999 --- /dev/null +++ b/lib/parser/states/StateModule.cpp @@ -0,0 +1,30 @@ +#include "lib/parser/states/StateModule.hpp" + +#include + +#include "lib/parser/ast/nodes/decls/Module.hpp" +#include "lib/parser/context/ContextParser.hpp" +#include "lib/parser/states/base/StateRegistry.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +std::string_view StateModule::Name() const { + return "Module"; +} + +IState::StepResult StateModule::TryStep(ContextParser& context, ITokenStream& token_stream) const { + if (context.NodeStack().empty()) { + auto module = std::make_unique(); + context.PushNode(std::move(module)); + } + + if (token_stream.IsEof()) { + return false; + } + + context.PushState(StateRegistry::TopDecl()); + return true; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateModule.hpp b/lib/parser/states/StateModule.hpp new file mode 100644 index 0000000..ec15748 --- /dev/null +++ b/lib/parser/states/StateModule.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_STATEMODULE_HPP_ +#define PARSER_STATEMODULE_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" + +namespace ovum::compiler::parser { + +class StateModule : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& context, ITokenStream& token_stream) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEMODULE_HPP_ diff --git a/lib/parser/states/StateParseType.cpp b/lib/parser/states/StateParseType.cpp new file mode 100644 index 0000000..0cb32e0 --- /dev/null +++ b/lib/parser/states/StateParseType.cpp @@ -0,0 +1,3 @@ +#include "StateParseType.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateParseType.hpp b/lib/parser/states/StateParseType.hpp new file mode 100644 index 0000000..eaf7814 --- /dev/null +++ b/lib/parser/states/StateParseType.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEPARSETYPE_HPP_ +#define PARSER_STATEPARSETYPE_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateParseType : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEPARSETYPE_HPP_ diff --git a/lib/parser/states/StateReturnTail.cpp b/lib/parser/states/StateReturnTail.cpp new file mode 100644 index 0000000..b74db84 --- /dev/null +++ b/lib/parser/states/StateReturnTail.cpp @@ -0,0 +1,3 @@ +#include "StateReturnTail.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateReturnTail.hpp b/lib/parser/states/StateReturnTail.hpp new file mode 100644 index 0000000..968bb8a --- /dev/null +++ b/lib/parser/states/StateReturnTail.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATERETURNTAIL_HPP_ +#define PARSER_STATERETURNTAIL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateReturnTail : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATERETURNTAIL_HPP_ diff --git a/lib/parser/states/StateStmt.cpp b/lib/parser/states/StateStmt.cpp new file mode 100644 index 0000000..5be5521 --- /dev/null +++ b/lib/parser/states/StateStmt.cpp @@ -0,0 +1,3 @@ +#include "StateStmt.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateStmt.hpp b/lib/parser/states/StateStmt.hpp new file mode 100644 index 0000000..c30a9ff --- /dev/null +++ b/lib/parser/states/StateStmt.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATESTMT_HPP_ +#define PARSER_STATESTMT_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateStmt : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATESTMT_HPP_ diff --git a/lib/parser/states/StateSyncToBlockEnd.cpp b/lib/parser/states/StateSyncToBlockEnd.cpp new file mode 100644 index 0000000..c68ba42 --- /dev/null +++ b/lib/parser/states/StateSyncToBlockEnd.cpp @@ -0,0 +1,3 @@ +#include "StateSyncToBlockEnd.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateSyncToBlockEnd.hpp b/lib/parser/states/StateSyncToBlockEnd.hpp new file mode 100644 index 0000000..75f95f2 --- /dev/null +++ b/lib/parser/states/StateSyncToBlockEnd.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATESYNCTOBLOCKEND_HPP_ +#define PARSER_STATESYNCTOBLOCKEND_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateSyncToBlockEnd : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATESYNCTOBLOCKEND_HPP_ diff --git a/lib/parser/states/StateSyncToStmtEnd.cpp b/lib/parser/states/StateSyncToStmtEnd.cpp new file mode 100644 index 0000000..edbb355 --- /dev/null +++ b/lib/parser/states/StateSyncToStmtEnd.cpp @@ -0,0 +1,3 @@ +#include "StateSyncToStmtEnd.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateSyncToStmtEnd.hpp b/lib/parser/states/StateSyncToStmtEnd.hpp new file mode 100644 index 0000000..900a00f --- /dev/null +++ b/lib/parser/states/StateSyncToStmtEnd.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATESYNCTOSTMTEND_HPP_ +#define PARSER_STATESYNCTOSTMTEND_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateSyncToStmtEnd : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATESYNCTOSTMTEND_HPP_ diff --git a/lib/parser/states/StateTopDecl.cpp b/lib/parser/states/StateTopDecl.cpp new file mode 100644 index 0000000..a977e77 --- /dev/null +++ b/lib/parser/states/StateTopDecl.cpp @@ -0,0 +1,3 @@ +#include "StateTopDecl.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateTopDecl.hpp b/lib/parser/states/StateTopDecl.hpp new file mode 100644 index 0000000..937fa0d --- /dev/null +++ b/lib/parser/states/StateTopDecl.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATETOPDECL_HPP_ +#define PARSER_STATETOPDECL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateTopDecl : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATETOPDECL_HPP_ diff --git a/lib/parser/states/StateTypeAliasDecl.cpp b/lib/parser/states/StateTypeAliasDecl.cpp new file mode 100644 index 0000000..8030979 --- /dev/null +++ b/lib/parser/states/StateTypeAliasDecl.cpp @@ -0,0 +1,3 @@ +#include "StateTypeAliasDecl.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateTypeAliasDecl.hpp b/lib/parser/states/StateTypeAliasDecl.hpp new file mode 100644 index 0000000..818386d --- /dev/null +++ b/lib/parser/states/StateTypeAliasDecl.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATETYPEALIASDECL_HPP_ +#define PARSER_STATETYPEALIASDECL_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateTypeAliasDecl : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATETYPEALIASDECL_HPP_ diff --git a/lib/parser/states/StateUnsafeBlock.cpp b/lib/parser/states/StateUnsafeBlock.cpp new file mode 100644 index 0000000..9ca09da --- /dev/null +++ b/lib/parser/states/StateUnsafeBlock.cpp @@ -0,0 +1,3 @@ +#include "StateUnsafeBlock.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateUnsafeBlock.hpp b/lib/parser/states/StateUnsafeBlock.hpp new file mode 100644 index 0000000..4913b0b --- /dev/null +++ b/lib/parser/states/StateUnsafeBlock.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEUNSAFEBLOCK_HPP_ +#define PARSER_STATEUNSAFEBLOCK_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateUnsafeBlock : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEUNSAFEBLOCK_HPP_ diff --git a/lib/parser/states/StateVarDeclTail.cpp b/lib/parser/states/StateVarDeclTail.cpp new file mode 100644 index 0000000..41f64d5 --- /dev/null +++ b/lib/parser/states/StateVarDeclTail.cpp @@ -0,0 +1,3 @@ +#include "StateVarDeclTail.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateVarDeclTail.hpp b/lib/parser/states/StateVarDeclTail.hpp new file mode 100644 index 0000000..b7fe7fe --- /dev/null +++ b/lib/parser/states/StateVarDeclTail.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEVARDECLTAIL_HPP_ +#define PARSER_STATEVARDECLTAIL_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateVarDeclTail : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEVARDECLTAIL_HPP_ diff --git a/lib/parser/states/StateWhileHead.cpp b/lib/parser/states/StateWhileHead.cpp new file mode 100644 index 0000000..ff319f1 --- /dev/null +++ b/lib/parser/states/StateWhileHead.cpp @@ -0,0 +1,3 @@ +#include "StateWhileHead.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/StateWhileHead.hpp b/lib/parser/states/StateWhileHead.hpp new file mode 100644 index 0000000..2298047 --- /dev/null +++ b/lib/parser/states/StateWhileHead.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEWHILEHEAD_HPP_ +#define PARSER_STATEWHILEHEAD_HPP_ + +#include "base/StateBase.hpp" +#include "lib/parser/context/ContextParser.hpp" + +namespace ovum::compiler::parser { + +class StateWhileHead : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEWHILEHEAD_HPP_ diff --git a/lib/parser/states/base/IState.hpp b/lib/parser/states/base/IState.hpp new file mode 100644 index 0000000..85e06cd --- /dev/null +++ b/lib/parser/states/base/IState.hpp @@ -0,0 +1,24 @@ +#ifndef PARSER_ISTATE_HPP_ +#define PARSER_ISTATE_HPP_ + +#include + +#include "StateError.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class ContextParser; // forward + +class IState { +public: + using StepResult = std::expected; + + virtual ~IState() = default; + virtual std::string_view Name() const = 0; + virtual StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ISTATE_HPP_ diff --git a/lib/parser/states/base/StateBase.cpp b/lib/parser/states/base/StateBase.cpp new file mode 100644 index 0000000..f00ebbe --- /dev/null +++ b/lib/parser/states/base/StateBase.cpp @@ -0,0 +1,15 @@ +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/SourceId.hpp" + +namespace ovum::compiler::parser { + +SourceSpan StateBase::SpanFrom(const Token& token) { + const auto& pos = token.GetPosition(); + return SourceSpan(SourceId{}, pos, pos); +} + +SourceSpan StateBase::Union(const SourceSpan& left, const SourceSpan& right) { + return SourceSpan::Union(left, right); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/states/base/StateBase.hpp b/lib/parser/states/base/StateBase.hpp new file mode 100644 index 0000000..c249839 --- /dev/null +++ b/lib/parser/states/base/StateBase.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_STATEBASE_HPP_ +#define PARSER_STATEBASE_HPP_ + +#include "IState.hpp" +#include "lib/parser/tokens/SourceSpan.hpp" + +namespace ovum::compiler::parser { + +class StateBase : public IState { +public: + using StepResult = IState::StepResult; + ~StateBase() override = default; + + static SourceSpan SpanFrom(const Token& token); + static SourceSpan Union(const SourceSpan& lhs, const SourceSpan& rhs); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEBASE_HPP_ diff --git a/lib/parser/states/base/StateError.cpp b/lib/parser/states/base/StateError.cpp new file mode 100644 index 0000000..16d3b7f --- /dev/null +++ b/lib/parser/states/base/StateError.cpp @@ -0,0 +1,17 @@ +#include "StateError.hpp" + +namespace ovum::compiler::parser { + +StateError::StateError() = default; + +StateError::StateError(std::string message) : message_(std::move(message)) { +} + +StateError::StateError(std::string_view message) : message_(message) { +} + +const std::string& StateError::Message() const noexcept { + return message_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/states/base/StateError.hpp b/lib/parser/states/base/StateError.hpp new file mode 100644 index 0000000..c53e6ea --- /dev/null +++ b/lib/parser/states/base/StateError.hpp @@ -0,0 +1,23 @@ +#ifndef PARSER_STATEERROR_HPP_ +#define PARSER_STATEERROR_HPP_ + +#include +#include + +namespace ovum::compiler::parser { + +class StateError { +public: + StateError(); + explicit StateError(std::string message); + explicit StateError(std::string_view message); + + const std::string& Message() const noexcept; + +private: + std::string message_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEERROR_HPP_ diff --git a/lib/parser/states/base/StateRegistry.cpp b/lib/parser/states/base/StateRegistry.cpp new file mode 100644 index 0000000..1e35214 --- /dev/null +++ b/lib/parser/states/base/StateRegistry.cpp @@ -0,0 +1,157 @@ +#include "StateRegistry.hpp" + +#include "lib/parser/states/StateBlock.hpp" +#include "lib/parser/states/StateCallDeclHdr.hpp" +#include "lib/parser/states/StateDestructorDecl.hpp" +#include "lib/parser/states/StateExpr.hpp" +#include "lib/parser/states/StateFieldDecl.hpp" +#include "lib/parser/states/StateForHead.hpp" +#include "lib/parser/states/StateGlobalVarDecl.hpp" +#include "lib/parser/states/StateIfHead.hpp" +#include "lib/parser/states/StateIfTail.hpp" +#include "lib/parser/states/StateMethodHdr.hpp" +#include "lib/parser/states/StateModule.hpp" +#include "lib/parser/states/StateParseType.hpp" +#include "lib/parser/states/StateReturnTail.hpp" +#include "lib/parser/states/StateStmt.hpp" +#include "lib/parser/states/StateSyncToBlockEnd.hpp" +#include "lib/parser/states/StateSyncToStmtEnd.hpp" +#include "lib/parser/states/StateTopDecl.hpp" +#include "lib/parser/states/StateTypeAliasDecl.hpp" +#include "lib/parser/states/StateUnsafeBlock.hpp" +#include "lib/parser/states/StateVarDeclTail.hpp" +#include "lib/parser/states/StateWhileHead.hpp" +#include "lib/parser/states/class/StateClassBody.hpp" +#include "lib/parser/states/class/StateClassHdr.hpp" +#include "lib/parser/states/class/StateClassMember.hpp" +#include "lib/parser/states/func/StateFuncBody.hpp" +#include "lib/parser/states/func/StateFuncHdr.hpp" +#include "lib/parser/states/func/StateFuncParams.hpp" +#include "lib/parser/states/interface/StateInterfaceBody.hpp" +#include "lib/parser/states/interface/StateInterfaceDecl.hpp" +#include "lib/parser/states/interface/StateInterfaceHdr.hpp" + +namespace ovum::compiler::parser { + +const IState& StateRegistry::Module() { + static StateModule s; + return s; +} +const IState& StateRegistry::TopDecl() { + static StateTopDecl s; + return s; +} +const IState& StateRegistry::FuncHdr() { + static StateFuncHdr s; + return s; +} +const IState& StateRegistry::FuncParams() { + static StateFuncParams s; + return s; +} +const IState& StateRegistry::FuncBody() { + static StateFuncBody s; + return s; +} +const IState& StateRegistry::ClassHdr() { + static StateClassHdr s; + return s; +} +const IState& StateRegistry::ClassBody() { + static StateClassBody s; + return s; +} +const IState& StateRegistry::ClassMember() { + static StateClassMember s; + return s; +} +const IState& StateRegistry::InterfaceHdr() { + static StateInterfaceHdr s; + return s; +} +const IState& StateRegistry::InterfaceBody() { + static StateInterfaceBody s; + return s; +} +const IState& StateRegistry::SignatureDecl() { + static StateInterfaceDecl s; + return s; +} +const IState& StateRegistry::TypeAliasDecl() { + static StateTypeAliasDecl s; + return s; +} +const IState& StateRegistry::GlobalVarDecl() { + static StateGlobalVarDecl s; + return s; +} +const IState& StateRegistry::DestructorDecl() { + static StateDestructorDecl s; + return s; +} +const IState& StateRegistry::CallDeclHdr() { + static StateCallDeclHdr s; + return s; +} +const IState& StateRegistry::MethodHdr() { + static StateMethodHdr s; + return s; +} +const IState& StateRegistry::FieldDecl() { + static StateFieldDecl s; + return s; +} +const IState& StateRegistry::Block() { + static StateBlock s; + return s; +} +const IState& StateRegistry::Stmt() { + static StateStmt s; + return s; +} +const IState& StateRegistry::IfHead() { + static StateIfHead s; + return s; +} +const IState& StateRegistry::IfTail() { + static StateIfTail s; + return s; +} +const IState& StateRegistry::WhileHead() { + static StateWhileHead s; + return s; +} +const IState& StateRegistry::ForHead() { + static StateForHead s; + return s; +} +const IState& StateRegistry::ReturnTail() { + static StateReturnTail s; + return s; +} +const IState& StateRegistry::VarDeclTail() { + static StateVarDeclTail s; + return s; +} +const IState& StateRegistry::UnsafeBlock() { + static StateUnsafeBlock s; + return s; +} +const IState& StateRegistry::ParseType() { + static StateParseType s; + return s; +} +const IState& StateRegistry::Expr() { + static StateExpr s; + return s; +} +const IState& StateRegistry::SyncToStmtEnd() { + static StateSyncToStmtEnd s; + return s; +} +const IState& StateRegistry::SyncToBlockEnd() { + static StateSyncToBlockEnd s; + return s; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/states/base/StateRegistry.hpp b/lib/parser/states/base/StateRegistry.hpp new file mode 100644 index 0000000..6233b66 --- /dev/null +++ b/lib/parser/states/base/StateRegistry.hpp @@ -0,0 +1,51 @@ +#ifndef PARSER_STATEREGISTRY_HPP_ +#define PARSER_STATEREGISTRY_HPP_ + +#include "IState.hpp" + +namespace ovum::compiler::parser { + +class StateRegistry { +public: + static const IState& Module(); + static const IState& TopDecl(); + + static const IState& FuncHdr(); + static const IState& FuncParams(); + static const IState& FuncBody(); + + static const IState& ClassHdr(); + static const IState& ClassBody(); + static const IState& ClassMember(); + + static const IState& InterfaceHdr(); + static const IState& InterfaceBody(); + static const IState& SignatureDecl(); + + static const IState& TypeAliasDecl(); + static const IState& GlobalVarDecl(); + + static const IState& DestructorDecl(); + static const IState& CallDeclHdr(); + static const IState& MethodHdr(); + static const IState& FieldDecl(); + + static const IState& Block(); + static const IState& Stmt(); + static const IState& IfHead(); + static const IState& IfTail(); + static const IState& WhileHead(); + static const IState& ForHead(); + static const IState& ReturnTail(); + static const IState& VarDeclTail(); + static const IState& UnsafeBlock(); + + static const IState& ParseType(); + static const IState& Expr(); + static const IState& SyncToStmtEnd(); + static const IState& SyncToBlockEnd(); +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEREGISTRY_HPP_ diff --git a/lib/parser/states/class/StateClassBody.cpp b/lib/parser/states/class/StateClassBody.cpp new file mode 100644 index 0000000..32f31bf --- /dev/null +++ b/lib/parser/states/class/StateClassBody.cpp @@ -0,0 +1,3 @@ +#include "StateClassBody.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/class/StateClassBody.hpp b/lib/parser/states/class/StateClassBody.hpp new file mode 100644 index 0000000..8b1adb9 --- /dev/null +++ b/lib/parser/states/class/StateClassBody.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATECLASSBODY_HPP_ +#define PARSER_STATECLASSBODY_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateClassBody : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATECLASSBODY_HPP_ diff --git a/lib/parser/states/class/StateClassHdr.cpp b/lib/parser/states/class/StateClassHdr.cpp new file mode 100644 index 0000000..8926460 --- /dev/null +++ b/lib/parser/states/class/StateClassHdr.cpp @@ -0,0 +1,3 @@ +#include "StateClassHdr.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/class/StateClassHdr.hpp b/lib/parser/states/class/StateClassHdr.hpp new file mode 100644 index 0000000..29f17aa --- /dev/null +++ b/lib/parser/states/class/StateClassHdr.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATECLASSHDR_HPP_ +#define PARSER_STATECLASSHDR_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateClassHdr : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATECLASSHDR_HPP_ diff --git a/lib/parser/states/class/StateClassMember.cpp b/lib/parser/states/class/StateClassMember.cpp new file mode 100644 index 0000000..bb4b51d --- /dev/null +++ b/lib/parser/states/class/StateClassMember.cpp @@ -0,0 +1,3 @@ +#include "StateClassMember.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/class/StateClassMember.hpp b/lib/parser/states/class/StateClassMember.hpp new file mode 100644 index 0000000..b069929 --- /dev/null +++ b/lib/parser/states/class/StateClassMember.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATECLASSMEMBER_HPP_ +#define PARSER_STATECLASSMEMBER_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateClassMember : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATECLASSMEMBER_HPP_ diff --git a/lib/parser/states/func/StateFuncBody.cpp b/lib/parser/states/func/StateFuncBody.cpp new file mode 100644 index 0000000..3c5f696 --- /dev/null +++ b/lib/parser/states/func/StateFuncBody.cpp @@ -0,0 +1,3 @@ +#include "StateFuncBody.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/func/StateFuncBody.hpp b/lib/parser/states/func/StateFuncBody.hpp new file mode 100644 index 0000000..0369d14 --- /dev/null +++ b/lib/parser/states/func/StateFuncBody.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEFUNCBODY_HPP_ +#define PARSER_STATEFUNCBODY_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateFuncBody : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEFUNCBODY_HPP_ diff --git a/lib/parser/states/func/StateFuncHdr.cpp b/lib/parser/states/func/StateFuncHdr.cpp new file mode 100644 index 0000000..807ce70 --- /dev/null +++ b/lib/parser/states/func/StateFuncHdr.cpp @@ -0,0 +1,3 @@ +#include "StateFuncHdr.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/func/StateFuncHdr.hpp b/lib/parser/states/func/StateFuncHdr.hpp new file mode 100644 index 0000000..c4997cc --- /dev/null +++ b/lib/parser/states/func/StateFuncHdr.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEFUNCHDR_HPP_ +#define PARSER_STATEFUNCHDR_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateFuncHdr : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEFUNCHDR_HPP_ diff --git a/lib/parser/states/func/StateFuncParams.cpp b/lib/parser/states/func/StateFuncParams.cpp new file mode 100644 index 0000000..9fdf6b8 --- /dev/null +++ b/lib/parser/states/func/StateFuncParams.cpp @@ -0,0 +1,3 @@ +#include "StateFuncParams.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/func/StateFuncParams.hpp b/lib/parser/states/func/StateFuncParams.hpp new file mode 100644 index 0000000..fbd7145 --- /dev/null +++ b/lib/parser/states/func/StateFuncParams.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEFUNCPARAMS_HPP_ +#define PARSER_STATEFUNCPARAMS_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateFuncParams : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEFUNCPARAMS_HPP_ diff --git a/lib/parser/states/interface/StateInterfaceBody.cpp b/lib/parser/states/interface/StateInterfaceBody.cpp new file mode 100644 index 0000000..08cfa87 --- /dev/null +++ b/lib/parser/states/interface/StateInterfaceBody.cpp @@ -0,0 +1,3 @@ +#include "StateInterfaceBody.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/interface/StateInterfaceBody.hpp b/lib/parser/states/interface/StateInterfaceBody.hpp new file mode 100644 index 0000000..ac7d041 --- /dev/null +++ b/lib/parser/states/interface/StateInterfaceBody.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEINTERFACEBODY_HPP_ +#define PARSER_STATEINTERFACEBODY_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateInterfaceBody : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEINTERFACEBODY_HPP_ diff --git a/lib/parser/states/interface/StateInterfaceDecl.cpp b/lib/parser/states/interface/StateInterfaceDecl.cpp new file mode 100644 index 0000000..85c9bf3 --- /dev/null +++ b/lib/parser/states/interface/StateInterfaceDecl.cpp @@ -0,0 +1,3 @@ +#include "StateInterfaceDecl.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/interface/StateInterfaceDecl.hpp b/lib/parser/states/interface/StateInterfaceDecl.hpp new file mode 100644 index 0000000..626e095 --- /dev/null +++ b/lib/parser/states/interface/StateInterfaceDecl.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEINTERFACEDECL_HPP_ +#define PARSER_STATEINTERFACEDECL_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateInterfaceDecl : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEINTERFACEDECL_HPP_ diff --git a/lib/parser/states/interface/StateInterfaceHdr.cpp b/lib/parser/states/interface/StateInterfaceHdr.cpp new file mode 100644 index 0000000..cebb5fb --- /dev/null +++ b/lib/parser/states/interface/StateInterfaceHdr.cpp @@ -0,0 +1,3 @@ +#include "StateInterfaceHdr.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/states/interface/StateInterfaceHdr.hpp b/lib/parser/states/interface/StateInterfaceHdr.hpp new file mode 100644 index 0000000..9a6e634 --- /dev/null +++ b/lib/parser/states/interface/StateInterfaceHdr.hpp @@ -0,0 +1,17 @@ +#ifndef PARSER_STATEINTERFACEHDR_HPP_ +#define PARSER_STATEINTERFACEHDR_HPP_ + +#include "lib/parser/states/base/StateBase.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class StateInterfaceHdr : public StateBase { +public: + std::string_view Name() const override; + StepResult TryStep(ContextParser& ctx, ITokenStream& ts) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_STATEINTERFACEHDR_HPP_ diff --git a/lib/parser/tokens/SourceId.cpp b/lib/parser/tokens/SourceId.cpp new file mode 100644 index 0000000..5d6d911 --- /dev/null +++ b/lib/parser/tokens/SourceId.cpp @@ -0,0 +1,3 @@ +#include "SourceId.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/SourceId.hpp b/lib/parser/tokens/SourceId.hpp new file mode 100644 index 0000000..4d2dea3 --- /dev/null +++ b/lib/parser/tokens/SourceId.hpp @@ -0,0 +1,30 @@ +#ifndef PARSER_SOURCEID_HPP_ +#define PARSER_SOURCEID_HPP_ + +#include +#include +#include + +namespace ovum::compiler::parser { + +class SourceId { +public: + SourceId() = default; + explicit SourceId(std::string path) : path_(std::move(path)) { + } + + [[nodiscard]] std::string_view Path() const noexcept; + + [[nodiscard]] std::string Basename() const; + + [[nodiscard]] bool IsValid() const noexcept; + [[nodiscard]] bool operator==(const SourceId& other) const noexcept; + [[nodiscard]] bool operator!=(const SourceId& other) const noexcept; + +private: + std::string path_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_SOURCEID_HPP_ diff --git a/lib/parser/tokens/SourceSpan.cpp b/lib/parser/tokens/SourceSpan.cpp new file mode 100644 index 0000000..68df9e7 --- /dev/null +++ b/lib/parser/tokens/SourceSpan.cpp @@ -0,0 +1,53 @@ +#include "SourceSpan.hpp" + +#include + +namespace ovum::compiler::parser { + +SourceSpan::SourceSpan(SourceId id, TokenPosition start, TokenPosition end) : + id_(std::move(id)), begin_(start), end_(end) { + Normalize(); +} + +const SourceId& SourceSpan::GetSourceId() const noexcept { + return id_; +} +TokenPosition SourceSpan::GetStart() const noexcept { + return begin_; +} +TokenPosition SourceSpan::GetEnd() const noexcept { + return end_; +} + +bool SourceSpan::IsValid() const noexcept { + return id_.IsValid(); +} + +void SourceSpan::Normalize() noexcept { + if (end_ < begin_) { + std::swap(begin_, end_); + } +} + +SourceSpan SourceSpan::SinglePoint(SourceId id, TokenPosition point) { + return SourceSpan(std::move(id), point, point); +} + +SourceSpan SourceSpan::Union(const SourceSpan& a, const SourceSpan& b) { + if (!a.IsValid()) { + return b; + } + + if (!b.IsValid()) { + return a; + } + + if (a.id_ != b.id_) { + return a; + } + TokenPosition start = a.begin_ < b.begin_ ? a.begin_ : b.begin_; + TokenPosition end = a.end_ < b.end_ ? b.end_ : a.end_; + return SourceSpan(a.id_, start, end); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/SourceSpan.hpp b/lib/parser/tokens/SourceSpan.hpp new file mode 100644 index 0000000..3441b46 --- /dev/null +++ b/lib/parser/tokens/SourceSpan.hpp @@ -0,0 +1,32 @@ +#ifndef PARSER_SOURCESPAN_HPP_ +#define PARSER_SOURCESPAN_HPP_ + +#include "SourceId.hpp" +#include "tokens/TokenPosition.hpp" + +namespace ovum::compiler::parser { + +class SourceSpan { +public: + SourceSpan() = default; + SourceSpan(SourceId id, TokenPosition start, TokenPosition end); + + [[nodiscard]] const SourceId& GetSourceId() const noexcept; + [[nodiscard]] TokenPosition GetStart() const noexcept; + [[nodiscard]] TokenPosition GetEnd() const noexcept; + + [[nodiscard]] bool IsValid() const noexcept; + void Normalize() noexcept; + + [[nodiscard]] static SourceSpan SinglePoint(SourceId id, TokenPosition point); + [[nodiscard]] static SourceSpan Union(const SourceSpan& a, const SourceSpan& b); + +private: + SourceId id_; + TokenPosition begin_; + TokenPosition end_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_SOURCESPAN_HPP_ diff --git a/lib/parser/tokens/token_streams/ITokenStream.hpp b/lib/parser/tokens/token_streams/ITokenStream.hpp new file mode 100644 index 0000000..37eaeba --- /dev/null +++ b/lib/parser/tokens/token_streams/ITokenStream.hpp @@ -0,0 +1,27 @@ +#ifndef PARSER_ITOKENSTREAM_HPP_ +#define PARSER_ITOKENSTREAM_HPP_ + +#include + +#include + +namespace ovum::compiler::parser { + +class ITokenStream { +public: + virtual ~ITokenStream() = default; + + virtual const Token& Peek(size_t k = 0) = 0; + virtual TokenPtr Consume() = 0; + + virtual size_t Position() const = 0; + virtual void Rewind(size_t n) = 0; + virtual bool IsEof() const = 0; + + virtual const Token* LastConsumed() const = 0; + virtual const Token* TryPeek(size_t k = 0) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ITOKENSTREAM_HPP_ diff --git a/lib/parser/tokens/token_streams/VectorTokenStream.cpp b/lib/parser/tokens/token_streams/VectorTokenStream.cpp new file mode 100644 index 0000000..6fafb4f --- /dev/null +++ b/lib/parser/tokens/token_streams/VectorTokenStream.cpp @@ -0,0 +1,74 @@ +#include "lib/parser/tokens/token_streams/VectorTokenStream.hpp" + +#include +#include + +namespace ovum::compiler::parser { + +VectorTokenStream::VectorTokenStream(std::vector tokens) : tokens_(std::move(tokens)) { +} + +const Token& VectorTokenStream::Peek(size_t k) { + const Token* token = TryPeek(k); + + if (token != nullptr) { + return *token; + } + + if (last_ != nullptr) { + return *last_; + } + + if (!tokens_.empty()) { + return *tokens_.back(); + } + + throw std::out_of_range("VectorTokenStream::Peek out of range"); +} + +TokenPtr VectorTokenStream::Consume() { + if (index_ < tokens_.size()) { + last_ = tokens_[index_].get(); + return std::move(tokens_[index_++]); + } + + last_ = nullptr; + return nullptr; +} + +size_t VectorTokenStream::Position() const { + return index_; +} + +void VectorTokenStream::Rewind(size_t n) { + if (n > index_) { + index_ = 0; + } else { + index_ -= n; + } + + last_ = nullptr; +} + +bool VectorTokenStream::IsEof() const { + return index_ >= tokens_.size(); +} + +const Token* VectorTokenStream::LastConsumed() const { + return last_; +} + +const Token* VectorTokenStream::TryPeek(size_t k) { + const size_t pos = index_ + k; + if (pos < tokens_.size()) { + return tokens_[pos].get(); + } + + return nullptr; +} + +size_t VectorTokenStream::Size() const { + return tokens_.size(); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/token_streams/VectorTokenStream.hpp b/lib/parser/tokens/token_streams/VectorTokenStream.hpp new file mode 100644 index 0000000..a5caae6 --- /dev/null +++ b/lib/parser/tokens/token_streams/VectorTokenStream.hpp @@ -0,0 +1,42 @@ +#ifndef PARSER_VECTORTOKENSTREAM_HPP_ +#define PARSER_VECTORTOKENSTREAM_HPP_ + +#include +#include +#include + +#include + +#include "ITokenStream.hpp" + +namespace ovum::compiler::parser { + +class VectorTokenStream : public ITokenStream { +public: + explicit VectorTokenStream(std::vector tokens); + + const Token& Peek(size_t k = 0) override; + + TokenPtr Consume() override; + + size_t Position() const override; + + void Rewind(size_t n) override; + + bool IsEof() const override; + + const Token* LastConsumed() const override; + + const Token* TryPeek(size_t k = 0) override; + + size_t Size() const; + +private: + std::vector tokens_; + size_t index_ = 0; + const Token* last_ = nullptr; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_VECTORTOKENSTREAM_HPP_ diff --git a/lib/parser/tokens/token_traits/ITokenMatcher.hpp b/lib/parser/tokens/token_traits/ITokenMatcher.hpp new file mode 100644 index 0000000..57febee --- /dev/null +++ b/lib/parser/tokens/token_traits/ITokenMatcher.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_ITOKENMATCHER_HPP_ +#define PARSER_ITOKENMATCHER_HPP_ + +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class ITokenMatcher { +public: + virtual ~ITokenMatcher() = default; + virtual bool TryMatch(const Token& token) const = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ITOKENMATCHER_HPP_ diff --git a/lib/parser/tokens/token_traits/MatchIdentifier.cpp b/lib/parser/tokens/token_traits/MatchIdentifier.cpp new file mode 100644 index 0000000..a6a25fb --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchIdentifier.cpp @@ -0,0 +1,10 @@ +#include "MatchIdentifier.hpp" + +namespace ovum::compiler::parser { + +bool MatchIdentifier::TryMatch(const Token& token) const { + const std::string type = token.GetStringType(); + return type == "IDENT"; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/token_traits/MatchIdentifier.hpp b/lib/parser/tokens/token_traits/MatchIdentifier.hpp new file mode 100644 index 0000000..52899d8 --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchIdentifier.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_MATCHIDENTIFIER_HPP_ +#define PARSER_MATCHIDENTIFIER_HPP_ + +#include "tokens/Token.hpp" +#include "ITokenMatcher.hpp" + +namespace ovum::compiler::parser { + +class MatchIdentifier : public ITokenMatcher { +public: + bool TryMatch(const Token& token) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MATCHIDENTIFIER_HPP_ diff --git a/lib/parser/tokens/token_traits/MatchLexeme.cpp b/lib/parser/tokens/token_traits/MatchLexeme.cpp new file mode 100644 index 0000000..5cb7280 --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchLexeme.cpp @@ -0,0 +1,12 @@ +#include "MatchLexeme.hpp" + +namespace ovum::compiler::parser { + +MatchLexeme::MatchLexeme(std::string_view lexeme) : lexeme_(lexeme) { +} + +bool MatchLexeme::TryMatch(const Token& token) const { + return token.GetLexeme() == lexeme_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/token_traits/MatchLexeme.hpp b/lib/parser/tokens/token_traits/MatchLexeme.hpp new file mode 100644 index 0000000..d1133ee --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchLexeme.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_MATCHLEXEME_HPP_ +#define PARSER_MATCHLEXEME_HPP_ + +#include + +#include "ITokenMatcher.hpp" +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class MatchLexeme : public ITokenMatcher { +public: + explicit MatchLexeme(std::string_view lexeme); + bool TryMatch(const Token& token) const override; + +private: + std::string_view lexeme_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MATCHLEXEME_HPP_ diff --git a/lib/parser/tokens/token_traits/MatchLiteral.cpp b/lib/parser/tokens/token_traits/MatchLiteral.cpp new file mode 100644 index 0000000..134966e --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchLiteral.cpp @@ -0,0 +1,13 @@ +#include "MatchLiteral.hpp" + +#include + +namespace ovum::compiler::parser { + +bool MatchLiteral::TryMatch(const Token& token) const { + const std::string type = token.GetStringType(); + // LiteralToken::GetStringType() -> "LITERAL:" + return type.rfind("LITERAL:", 0) == 0; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/token_traits/MatchLiteral.hpp b/lib/parser/tokens/token_traits/MatchLiteral.hpp new file mode 100644 index 0000000..79d889b --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchLiteral.hpp @@ -0,0 +1,16 @@ +#ifndef PARSER_MATCHLITERAL_HPP_ +#define PARSER_MATCHLITERAL_HPP_ + +#include "tokens/Token.hpp" +#include "ITokenMatcher.hpp" + +namespace ovum::compiler::parser { + +class MatchLiteral : public ITokenMatcher { +public: + bool TryMatch(const Token& token) const override; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MATCHLITERAL_HPP_ diff --git a/lib/parser/tokens/token_traits/MatchManyOf.cpp b/lib/parser/tokens/token_traits/MatchManyOf.cpp new file mode 100644 index 0000000..31e560c --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchManyOf.cpp @@ -0,0 +1,17 @@ +#include "MatchManyOf.hpp" + +namespace ovum::compiler::parser { + +MatchAnyOf::MatchAnyOf(std::vector> matchers) : matchers_(std::move(matchers)) { +} + +bool MatchAnyOf::TryMatch(const Token& token) const { + for (const auto& m : matchers_) { + if (m && m->TryMatch(token)) { + return true; + } + } + return false; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/token_traits/MatchManyOf.hpp b/lib/parser/tokens/token_traits/MatchManyOf.hpp new file mode 100644 index 0000000..dbaf30a --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchManyOf.hpp @@ -0,0 +1,23 @@ +#ifndef PARSER_MATCHMANYOF_HPP_ +#define PARSER_MATCHMANYOF_HPP_ + +#include +#include + +#include "ITokenMatcher.hpp" +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class MatchAnyOf : public ITokenMatcher { +public: + explicit MatchAnyOf(std::vector> matchers); + bool TryMatch(const Token& token) const override; + +private: + std::vector> matchers_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MATCHMANYOF_HPP_ diff --git a/lib/parser/tokens/token_traits/MatchType.cpp b/lib/parser/tokens/token_traits/MatchType.cpp new file mode 100644 index 0000000..c35dc94 --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchType.cpp @@ -0,0 +1,12 @@ +#include "MatchType.hpp" + +namespace ovum::compiler::parser { + +MatchType::MatchType(std::string_view type_name) : type_(type_name) { +} + +bool MatchType::TryMatch(const Token& token) const { + return token.GetStringType() == type_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/tokens/token_traits/MatchType.hpp b/lib/parser/tokens/token_traits/MatchType.hpp new file mode 100644 index 0000000..c480d6e --- /dev/null +++ b/lib/parser/tokens/token_traits/MatchType.hpp @@ -0,0 +1,22 @@ +#ifndef PARSER_MATCHTYPE_HPP_ +#define PARSER_MATCHTYPE_HPP_ + +#include + +#include "ITokenMatcher.hpp" +#include "tokens/Token.hpp" + +namespace ovum::compiler::parser { + +class MatchType : public ITokenMatcher { +public: + explicit MatchType(std::string_view type_name); + bool TryMatch(const Token& token) const override; + +private: + std::string_view type_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_MATCHTYPE_HPP_ diff --git a/lib/parser/type_parser/ITypeParser.hpp b/lib/parser/type_parser/ITypeParser.hpp new file mode 100644 index 0000000..fabbbd9 --- /dev/null +++ b/lib/parser/type_parser/ITypeParser.hpp @@ -0,0 +1,20 @@ +#ifndef PARSER_ITYPEPARSER_HPP_ +#define PARSER_ITYPEPARSER_HPP_ + +#include + +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class ITypeParser { +public: + virtual ~ITypeParser() = default; + virtual std::unique_ptr ParseType(ITokenStream& ts, IDiagnosticSink& diags) = 0; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_ITYPEPARSER_HPP_ diff --git a/lib/parser/type_parser/QNameTypeParser.cpp b/lib/parser/type_parser/QNameTypeParser.cpp new file mode 100644 index 0000000..dbcb469 --- /dev/null +++ b/lib/parser/type_parser/QNameTypeParser.cpp @@ -0,0 +1,3 @@ +#include "QNameTypeParser.hpp" + +namespace ovum::compiler::parser {} // namespace ovum::compiler::parser diff --git a/lib/parser/type_parser/QNameTypeParser.hpp b/lib/parser/type_parser/QNameTypeParser.hpp new file mode 100644 index 0000000..f54cbed --- /dev/null +++ b/lib/parser/type_parser/QNameTypeParser.hpp @@ -0,0 +1,33 @@ +#ifndef PARSER_QNAMETYPEPARSER_HPP_ +#define PARSER_QNAMETYPEPARSER_HPP_ + +#include + +#include "ITypeParser.hpp" +#include "lib/parser/ast/IAstFactory.hpp" +#include "lib/parser/diagnostics/IDiagnosticSink.hpp" +#include "lib/parser/tokens/token_streams/ITokenStream.hpp" +#include "lib/parser/types/TypeReference.hpp" + +namespace ovum::compiler::parser { + +class QNameTypeParser final : public ITypeParser { +public: + explicit QNameTypeParser(IAstFactory& factory) noexcept; + ~QNameTypeParser() override = default; + + [[nodiscard]] std::unique_ptr ParseType(ITokenStream& ts, IDiagnosticSink& diags) override; + + QNameTypeParser(const QNameTypeParser&) = delete; + QNameTypeParser& operator=(const QNameTypeParser&) = delete; + + QNameTypeParser(QNameTypeParser&&) noexcept = default; + QNameTypeParser& operator=(QNameTypeParser&&) noexcept = delete; + +private: + std::shared_ptr factory_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_QNAMETYPEPARSER_HPP_ diff --git a/lib/parser/types/Nullable.cpp b/lib/parser/types/Nullable.cpp new file mode 100644 index 0000000..b231e1b --- /dev/null +++ b/lib/parser/types/Nullable.cpp @@ -0,0 +1,24 @@ +#include "Nullable.hpp" + +namespace ovum::compiler::parser { + +Nullable::Nullable(bool on) noexcept : on_(on) { +} + +bool Nullable::IsOn() const noexcept { + return on_; +} + +void Nullable::Set(bool on) noexcept { + on_ = on; +} + +void Nullable::Enable() noexcept { + on_ = true; +} + +void Nullable::Disable() noexcept { + on_ = false; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/types/Nullable.hpp b/lib/parser/types/Nullable.hpp new file mode 100644 index 0000000..ffc8c3e --- /dev/null +++ b/lib/parser/types/Nullable.hpp @@ -0,0 +1,26 @@ +#ifndef PARSER_NULLABLE_HPP_ +#define PARSER_NULLABLE_HPP_ + +namespace ovum::compiler::parser { + +class Nullable { +public: + Nullable() noexcept = default; + + explicit Nullable(bool on) noexcept; + + bool IsOn() const noexcept; + + void Set(bool on) noexcept; + + void Enable() noexcept; + + void Disable() noexcept; + +private: + bool on_ = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_NULLABLE_HPP_ diff --git a/lib/parser/types/Param.cpp b/lib/parser/types/Param.cpp new file mode 100644 index 0000000..9e4d022 --- /dev/null +++ b/lib/parser/types/Param.cpp @@ -0,0 +1,17 @@ +#include "lib/parser/types/Param.hpp" + +namespace ovum::compiler::parser { + +Param::Param(std::string name, TypeReference typeReference) : + name_(std::move(name)), reference_(std::move(typeReference)) { +} + +const std::string& Param::GetName() { + return name_; +} + +const TypeReference& Param::GetType() { + return reference_; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/types/Param.hpp b/lib/parser/types/Param.hpp new file mode 100644 index 0000000..ceb3f68 --- /dev/null +++ b/lib/parser/types/Param.hpp @@ -0,0 +1,25 @@ +#ifndef PARSER_PARAM_HPP_ +#define PARSER_PARAM_HPP_ + +#include + +#include "TypeReference.hpp" + +namespace ovum::compiler::parser { + +class Param { +public: + Param(std::string name, TypeReference typeReference); + + [[nodiscard]] const std::string& GetName(); + + [[nodiscard]] const TypeReference& GetType(); + +private: + std::string name_; + TypeReference reference_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_PARAM_HPP_ diff --git a/lib/parser/types/ResolvedTypeHandle.cpp b/lib/parser/types/ResolvedTypeHandle.cpp new file mode 100644 index 0000000..b228d66 --- /dev/null +++ b/lib/parser/types/ResolvedTypeHandle.cpp @@ -0,0 +1,27 @@ +#include "lib/parser/types/ResolvedTypeHandle.hpp" + +#include + +namespace ovum::compiler::parser { + +ResolvedTypeHandle::ResolvedTypeHandle(const void* decl, std::string mangled, bool is_interface) : + decl_(decl), mangled_(std::move(mangled)), is_interface_(is_interface) { +} + +const void* ResolvedTypeHandle::Decl() const noexcept { + return decl_; +} + +std::string_view ResolvedTypeHandle::Mangled() const noexcept { + return mangled_; +} + +bool ResolvedTypeHandle::IsInterface() const noexcept { + return is_interface_; +} + +bool ResolvedTypeHandle::IsValid() const noexcept { + return decl_ != nullptr; +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/types/ResolvedTypeHandle.hpp b/lib/parser/types/ResolvedTypeHandle.hpp new file mode 100644 index 0000000..74b9f57 --- /dev/null +++ b/lib/parser/types/ResolvedTypeHandle.hpp @@ -0,0 +1,33 @@ +#ifndef PARSER_RESOLVEDTYPEHANDLE_HPP_ +#define PARSER_RESOLVEDTYPEHANDLE_HPP_ + +#include + +namespace ovum::compiler::parser { + +class ResolvedTypeHandle { +public: + ResolvedTypeHandle() = default; + ResolvedTypeHandle(const void* decl, std::string mangled, bool is_interface); + + ResolvedTypeHandle(const ResolvedTypeHandle& other) = default; + ResolvedTypeHandle(ResolvedTypeHandle&& other) noexcept = default; + ~ResolvedTypeHandle() = default; + + ResolvedTypeHandle& operator=(const ResolvedTypeHandle& other) = default; + ResolvedTypeHandle& operator=(ResolvedTypeHandle&& other) noexcept = default; + + const void* Decl() const noexcept; + std::string_view Mangled() const noexcept; + bool IsInterface() const noexcept; + bool IsValid() const noexcept; + +private: + const void* decl_ = nullptr; + std::string mangled_; + bool is_interface_ = false; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_RESOLVEDTYPEHANDLE_HPP_ diff --git a/lib/parser/types/TypeReference.cpp b/lib/parser/types/TypeReference.cpp new file mode 100644 index 0000000..9e5bfc2 --- /dev/null +++ b/lib/parser/types/TypeReference.cpp @@ -0,0 +1,258 @@ +#include "lib/parser/types/TypeReference.hpp" + +#include +#include +#include +#include + +namespace ovum::compiler::parser { + +TypeReference::TypeReference() = default; + +TypeReference::TypeReference(std::string name) { + qname_.clear(); + qname_.push_back(std::move(name)); +} + +TypeReference::TypeReference(std::vector qname) : qname_(std::move(qname)) { +} + +TypeReference::TypeReference(const TypeReference& ref) : + qname_(ref.qname_), type_args_(ref.type_args_), nullable_(ref.nullable_) { + if (ref.resolved_) { + resolved_ = std::make_unique(*ref.resolved_); + } +} + +TypeReference::TypeReference(TypeReference&& ref) noexcept : + qname_(std::move(ref.qname_)), type_args_(std::move(ref.type_args_)), nullable_(ref.nullable_), + resolved_(std::move(ref.resolved_)) { +} + +TypeReference::~TypeReference() = default; + +TypeReference& TypeReference::operator=(const TypeReference& ref) { + if (this == &ref) { + return *this; + } + + qname_ = ref.qname_; + type_args_ = ref.type_args_; + nullable_ = ref.nullable_; + + if (ref.resolved_) { + resolved_ = std::make_unique(*ref.resolved_); + } else { + resolved_.reset(); + } + + return *this; +} + +TypeReference& TypeReference::operator=(TypeReference&& ref) noexcept { + if (this == &ref) { + return *this; + } + + qname_ = std::move(ref.qname_); + type_args_ = std::move(ref.type_args_); + nullable_ = ref.nullable_; + resolved_ = std::move(ref.resolved_); + return *this; +} + +TypeReference& TypeReference::operator=(std::string name) { + qname_.clear(); + qname_.push_back(std::move(name)); + InvalidateResolution(); + return *this; +} + +bool TypeReference::StructurallyEquals(const TypeReference& other) const noexcept { + if (nullable_.IsOn() != other.nullable_.IsOn()) { + return false; + } + + if (qname_ != other.qname_) { + return false; + } + + if (type_args_.size() != other.type_args_.size()) { + return false; + } + + for (std::size_t i = 0; i < type_args_.size(); ++i) { + if (!type_args_[i].StructurallyEquals(other.type_args_[i])) { + return false; + } + } + return true; +} + +std::string TypeReference::StableKey() const { + std::ostringstream out; + out << JoinQualified(qname_); + if (!type_args_.empty()) { + out << '<' << ArgsToString(type_args_) << '>'; + } + + if (nullable_.IsOn()) { + out << '?'; + } + + return out.str(); +} + +std::string TypeReference::ToStringHuman() const { + return StableKey(); +} + +const std::vector& TypeReference::QualifiedName() const noexcept { + return qname_; +} + +std::string_view TypeReference::SimpleName() const noexcept { + if (qname_.empty()) { + return {}; + } + + return qname_.back(); +} + +void TypeReference::SetQualifiedName(std::vector qname) { + qname_ = std::move(qname); + InvalidateResolution(); +} + +void TypeReference::SetSimpleName(std::string name) { + if (qname_.empty()) { + qname_.push_back(std::move(name)); + } else { + qname_.back() = std::move(name); + } + + InvalidateResolution(); +} + +void TypeReference::PushQualifier(std::string qualifier) { + qname_.push_back(std::move(qualifier)); + InvalidateResolution(); +} + +bool TypeReference::PopFrontQualifier() { + if (qname_.empty()) { + return false; + } + + qname_.erase(qname_.begin()); + InvalidateResolution(); + return true; +} + +bool TypeReference::PopBackQualifier() { + if (qname_.empty()) { + return false; + } + + qname_.pop_back(); + InvalidateResolution(); + return true; +} + +const std::vector& TypeReference::TypeArguments() const noexcept { + return type_args_; +} + +std::vector& TypeReference::MutableTypeArguments() noexcept { + return type_args_; +} + +void TypeReference::ClearTypeArguments() { + type_args_.clear(); + InvalidateResolution(); +} + +void TypeReference::AddTypeArgument(TypeReference arg) { + type_args_.emplace_back(std::move(arg)); + InvalidateResolution(); +} + +std::size_t TypeReference::Arity() const noexcept { + return type_args_.size(); +} + +const Nullable& TypeReference::Nullability() const noexcept { + return nullable_; +} + +bool TypeReference::IsNullable() const noexcept { + return nullable_.IsOn(); +} + +void TypeReference::SetNullable(bool on) noexcept { + nullable_.Set(on); +} + +void TypeReference::MakeNullable() noexcept { + nullable_.Enable(); +} + +void TypeReference::MakeNonNullable() noexcept { + nullable_.Disable(); +} + +TypeReference TypeReference::WithoutNullable() const { + TypeReference copy{*this}; + copy.MakeNonNullable(); + copy.InvalidateResolution(); + return copy; +} + +bool TypeReference::IsResolved() const noexcept { + return static_cast(resolved_); +} + +const ResolvedTypeHandle* TypeReference::Resolved() const noexcept { + return resolved_ ? resolved_.get() : nullptr; +} + +void TypeReference::SetResolvedHandle(const void* decl, std::string mangled, bool is_interface) { + resolved_ = std::make_unique(decl, std::move(mangled), is_interface); +} + +void TypeReference::ResetResolvedHandle() noexcept { + resolved_.reset(); +} + +std::string TypeReference::JoinQualified(const std::vector& parts) { + if (parts.empty()) { + return {}; + } + + std::ostringstream out; + for (std::size_t i = 0; i < parts.size(); ++i) { + if (i) { + out << "."; + } + out << parts[i]; + } + return out.str(); +} + +std::string TypeReference::ArgsToString(const std::vector& args) { + std::ostringstream out; + for (std::size_t i = 0; i < args.size(); ++i) { + if (i) { + out << ", "; + } + + out << args[i].StableKey(); + } + return out.str(); +} + +void TypeReference::InvalidateResolution() noexcept { + resolved_.reset(); +} + +} // namespace ovum::compiler::parser diff --git a/lib/parser/types/TypeReference.hpp b/lib/parser/types/TypeReference.hpp new file mode 100644 index 0000000..3aaf354 --- /dev/null +++ b/lib/parser/types/TypeReference.hpp @@ -0,0 +1,79 @@ +#ifndef PARSER_TYPEREFERENCE_HPP_ +#define PARSER_TYPEREFERENCE_HPP_ + +#include +#include +#include +#include + +#include "Nullable.hpp" +#include "ResolvedTypeHandle.hpp" + +namespace ovum::compiler::parser { + +class TypeReference { +public: + TypeReference(); + explicit TypeReference(std::string name); + explicit TypeReference(std::vector qname); + + TypeReference(const TypeReference& ref); + TypeReference(TypeReference&& ref) noexcept; + + ~TypeReference(); + + TypeReference& operator=(const TypeReference& ref); + TypeReference& operator=(TypeReference&& ref) noexcept; + + TypeReference& operator=(std::string name); + + bool StructurallyEquals(const TypeReference& other) const noexcept; + + std::string StableKey() const; + std::string ToStringHuman() const; + + const std::vector& QualifiedName() const noexcept; + std::string_view SimpleName() const noexcept; + + void SetQualifiedName(std::vector qname); + void SetSimpleName(std::string name); + void PushQualifier(std::string qualifier); + bool PopFrontQualifier(); + bool PopBackQualifier(); + + const std::vector& TypeArguments() const noexcept; + std::vector& MutableTypeArguments() noexcept; + + void ClearTypeArguments(); + void AddTypeArgument(TypeReference arg); + std::size_t Arity() const noexcept; + + const Nullable& Nullability() const noexcept; + bool IsNullable() const noexcept; + void SetNullable(bool on) noexcept; + void MakeNullable() noexcept; + void MakeNonNullable() noexcept; + + TypeReference WithoutNullable() const; + + bool IsResolved() const noexcept; + const ResolvedTypeHandle* Resolved() const noexcept; + + void SetResolvedHandle(const void* decl, std::string mangled, bool is_interface); + void ResetResolvedHandle() noexcept; + +private: + static std::string JoinQualified(const std::vector& parts); + static std::string ArgsToString(const std::vector& args); + + void InvalidateResolution() noexcept; + + std::vector qname_; + std::vector type_args_; + Nullable nullable_; + std::unique_ptr resolved_; +}; + +} // namespace ovum::compiler::parser + +#endif // PARSER_TYPEREFERENCE_HPP_