diff --git a/.gitignore b/.gitignore index d163863..567609b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -build/ \ No newline at end of file +build/ diff --git a/compiler/.gitignore b/compiler/.gitignore index 5c64952..2a03c28 100644 --- a/compiler/.gitignore +++ b/compiler/.gitignore @@ -1 +1,8 @@ -*.gen.* +# antlr +.antlr/ +*.interp +*.tokens + +# antlr-generated files +plsm*.h +plsm*.cpp diff --git a/.vscode/settings.json b/compiler/.vscode/settings.json similarity index 87% rename from .vscode/settings.json rename to compiler/.vscode/settings.json index f2a4425..956857a 100644 --- a/.vscode/settings.json +++ b/compiler/.vscode/settings.json @@ -1,15 +1,17 @@ - { - "[yacc]": { - "problems.decorations.enabled": false, - }, + "C_Cpp.default.includePath": [ + "${workspaceFolder}/include/", + "/usr/include/antlr4-runtime", + ], "files.associations": { "*.embeddedhtml": "html", + "iosfwd": "cpp", "any": "cpp", "array": "cpp", "atomic": "cpp", "bit": "cpp", "*.tcc": "cpp", + "bitset": "cpp", "cctype": "cpp", "charconv": "cpp", "chrono": "cpp", @@ -28,10 +30,13 @@ "cwchar": "cpp", "cwctype": "cpp", "deque": "cpp", + "forward_list": "cpp", "list": "cpp", "map": "cpp", + "set": "cpp", "string": "cpp", "unordered_map": "cpp", + "unordered_set": "cpp", "vector": "cpp", "exception": "cpp", "algorithm": "cpp", @@ -52,7 +57,6 @@ "fstream": "cpp", "initializer_list": "cpp", "iomanip": "cpp", - "iosfwd": "cpp", "iostream": "cpp", "istream": "cpp", "limits": "cpp", @@ -61,6 +65,7 @@ "numbers": "cpp", "ostream": "cpp", "semaphore": "cpp", + "shared_mutex": "cpp", "span": "cpp", "sstream": "cpp", "stdexcept": "cpp", @@ -72,18 +77,6 @@ "typeinfo": "cpp", "valarray": "cpp", "variant": "cpp", - "int.h": "c", - "macros.h": "c", - "stdint.h": "c", - "type.h": "c", - "stdlib.h": "c", - "bitset": "cpp", - "codecvt": "cpp", - "forward_list": "cpp", - "set": "cpp", - "unordered_set": "cpp", - "source_location": "cpp", - "shared_mutex": "cpp", - "strstream": "cpp" - }, + "*.inc": "cpp" + } } \ No newline at end of file diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index b18caf0..2da6d53 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -3,26 +3,37 @@ cmake_minimum_required(VERSION 3.25) project(plasmatum) set(CMAKE_CXX_STANDARD 23) -set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/src) -set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include) +set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) +set(INC_DIR ${CMAKE_SOURCE_DIR}/include) -find_package(FLEX REQUIRED) -find_package(BISON REQUIRED) +set(GEN_DIR ${CMAKE_SOURCE_DIR}/generated) -BISON_TARGET(parser - ${CMAKE_SOURCE_DIR}/parser.yy - ${SOURCE_DIR}/parser.gen.cpp - DEFINES_FILE ${INCLUDE_DIR}/parser.gen.h) +set(ANTLR_INC ${INC_DIR}/plsmLexer.h ${INC_DIR}/plsmParser.h ${INC_DIR}/plsmVisitor.h ${INC_DIR}/plsmBaseVisitor.h) +set(ANTLR_SRC ${SRC_DIR}/plsmLexer.cpp ${SRC_DIR}/plsmParser.cpp ${SRC_DIR}/plsmVisitor.cpp ${SRC_DIR}/plsmBaseVisitor.cpp) -FLEX_TARGET(lexer - ${CMAKE_SOURCE_DIR}/lexer.ll - ${SOURCE_DIR}/lexer.gen.cpp) +add_custom_command(PRE_BUILD + DEPENDS ${CMAKE_SOURCE_DIR}/plsm.g4 + OUTPUT ${ANTLR_SRC} + OUTPUT ${ANTLR_INC} + COMMENT "Generating plsm_parser" + COMMAND java -jar + ${CMAKE_SOURCE_DIR}/thirdparty/antlr-4.13.1-complete.jar + ${CMAKE_SOURCE_DIR}/plsm.g4 + -o ${GEN_DIR} -Dlanguage=Cpp -no-listener -visitor + COMMAND ${CMAKE_COMMAND} -E copy ${GEN_DIR}/*.h ${INC_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${GEN_DIR}/*.cpp ${SRC_DIR}) -ADD_FLEX_BISON_DEPENDENCY(lexer parser) +file(GLOB_RECURSE sources ${SRC_DIR}/*.cpp) +set(sources ${sources} ${ANTLR_SRC}) -file(GLOB_RECURSE sources ${SOURCE_DIR}/*.cpp) -set(sources ${sources} ${FLEX_lexer_OUTPUTS}) -set(sources ${sources} ${BISON_parser_OUTPUT_SOURCE}) - -include_directories(${CMAKE_SOURCE_DIR}/include) add_executable(plsm ${sources}) + +target_include_directories(plsm PRIVATE ${CMAKE_SOURCE_DIR}/include) +target_include_directories(plsm PRIVATE /usr/include/antlr4-runtime) +target_link_libraries(plsm antlr4-runtime) + +add_custom_target(clean-all + COMMAND ${CMAKE_COMMAND} -E rm -rf + ${GEN_DIR} ${CMAKE_SOURCE_DIR}/build +) + diff --git a/compiler/adscript.g4 b/compiler/adscript.g4 new file mode 100644 index 0000000..5869127 --- /dev/null +++ b/compiler/adscript.g4 @@ -0,0 +1,8 @@ +grammar adscript; + +module:; + +// TODO ;) + +FN: 'fn'; +TYPE: 'type'; diff --git a/compiler/include/AST/Base.h b/compiler/include/AST/Base.h index d70fa28..991c6ab 100644 --- a/compiler/include/AST/Base.h +++ b/compiler/include/AST/Base.h @@ -6,17 +6,27 @@ namespace ast { public: virtual ~ASTNode() = default; + + virtual bool isExpr() { return false; } + virtual bool isStmt() { return false; } + virtual bool isType() { return false; } }; class Expr : public ASTNode { + public: + virtual bool isExpr() override { return true; } }; class Stmt : public ASTNode { + public: + virtual bool isStmt() override { return true; } }; class Type : public ASTNode { + public: + virtual bool isType() override { return true; } }; } \ No newline at end of file diff --git a/compiler/include/AST/Def.h b/compiler/include/AST/Def.h index 9fa74d6..8b323a0 100644 --- a/compiler/include/AST/Def.h +++ b/compiler/include/AST/Def.h @@ -5,17 +5,20 @@ #include "Expr/BinExpr.h" #include "Expr/Block.h" #include "Expr/Call.h" +#include "Expr/Closure.h" #include "Expr/Identifier.h" #include "Expr/UnaryExpr.h" #include "Expr/Value.h" #include "Stmt/ExprStmt.h" #include "Stmt/FnDecl.h" -#include "Stmt/TraitDecl.h" -#include "Stmt/TypeDecl.h" +#include "Stmt/TraitAlias.h" +#include "Stmt/TraitDef.h" +#include "Stmt/TypeAlias.h" +#include "Stmt/TypeDef.h" #include "Stmt/ValDecl.h" -#include "Type/Function.h" +#include "Type/Closure.h" #include "Type/Generic.h" #include "Type/Named.h" #include "Type/Tuple.h" diff --git a/compiler/include/AST/Expr/BinExpr.h b/compiler/include/AST/Expr/BinExpr.h index 8709b3b..4f7fc7c 100644 --- a/compiler/include/AST/Expr/BinExpr.h +++ b/compiler/include/AST/Expr/BinExpr.h @@ -2,33 +2,25 @@ #include "AST/Base.h" #include +#include namespace ast { class BinExpr : public Expr { - public: - BinExpr(const Expr *left, const std::string &op, const Expr *right) - : left(left), op(op), right(right) {} - - ~BinExpr() - { - delete left; - delete right; - } - - const Expr *left; const std::string op; - const Expr *right; + const std::unique_ptr left, right; + + public: + BinExpr(std::unique_ptr &left, const std::string &op, std::unique_ptr &right) + : left(std::move(left)), op(op), right(std::move(right)) {} }; class PrefExpr : public Expr { + const std::unique_ptr expr; + public: - PrefExpr(const Expr *expr) : expr(expr) {} - - ~PrefExpr() { delete expr; } - - const Expr *expr; + PrefExpr(std::unique_ptr &expr) : expr(std::move(expr)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Block.h b/compiler/include/AST/Expr/Block.h index e9301ce..37852da 100644 --- a/compiler/include/AST/Expr/Block.h +++ b/compiler/include/AST/Expr/Block.h @@ -2,19 +2,15 @@ #include "AST/Base.h" #include +#include namespace ast { class BlockExpr : public Expr { - public: - BlockExpr(const std::vector &stmts) : stmts(std::move(stmts)) {} - ~BlockExpr() - { - for (auto &stmt : stmts) - delete stmt; - } + const std::vector> stmts; - const std::vector stmts; + public: + BlockExpr(std::vector> &stmts) : stmts(std::move(stmts)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Call.h b/compiler/include/AST/Expr/Call.h index 2d9cf7e..07f81bb 100644 --- a/compiler/include/AST/Expr/Call.h +++ b/compiler/include/AST/Expr/Call.h @@ -2,23 +2,17 @@ #include "AST/Base.h" #include +#include namespace ast { class CallExpr : public Expr { + const std::unique_ptr callee; + const std::vector> args; + public: - CallExpr(const Expr *callee, const std::vector &args) - : callee(callee), args(std::move(args)) {} - - ~CallExpr() - { - delete callee; - for (auto &arg : args) - delete arg; - } - - const Expr *callee; - const std::vector args; + CallExpr(std::unique_ptr &callee, std::vector> &args) + : callee(std::move(callee)), args(std::move(args)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Closure.h b/compiler/include/AST/Expr/Closure.h index a8e6732..2f9122c 100644 --- a/compiler/include/AST/Expr/Closure.h +++ b/compiler/include/AST/Expr/Closure.h @@ -3,17 +3,17 @@ #include "AST/Base.h" #include #include +#include namespace ast { class Closure : public Expr { - public: - Closure(const std::vector &args, const Expr *body) - : args(std::move(args)), body(body) {} - ~Closure() { delete body; } - const std::vector args; - const Expr *body; + const std::unique_ptr body; + + public: + Closure(std::vector &args, std::unique_ptr &body) + : args(std::move(args)), body(std::move(body)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Identifier.h b/compiler/include/AST/Expr/Identifier.h index 9e36232..a3a7343 100644 --- a/compiler/include/AST/Expr/Identifier.h +++ b/compiler/include/AST/Expr/Identifier.h @@ -7,9 +7,9 @@ namespace ast { class Identifier : public Expr { + const std::string name; + public: Identifier(const std::string &name) : name(name) {} - - const std::string name; }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/UnaryExpr.h b/compiler/include/AST/Expr/UnaryExpr.h index 2e0b2da..2dbf1f8 100644 --- a/compiler/include/AST/Expr/UnaryExpr.h +++ b/compiler/include/AST/Expr/UnaryExpr.h @@ -2,18 +2,17 @@ #include "AST/Base.h" #include +#include namespace ast { class UnaryExpr : public Expr { - public: - UnaryExpr(const std::string &op, const Expr *expr) - : op(op), expr(expr) {} - - ~UnaryExpr() { delete expr; } - const std::string op; - const Expr *expr; + const std::unique_ptr expr; + + public: + UnaryExpr(const std::string &op, std::unique_ptr &expr) + : op(op), expr(std::move(expr)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Expr/Value.h b/compiler/include/AST/Expr/Value.h index 475f2f6..a758e24 100644 --- a/compiler/include/AST/Expr/Value.h +++ b/compiler/include/AST/Expr/Value.h @@ -7,15 +7,17 @@ namespace ast { class IntValue : public Expr { + const int64_t value; + public: IntValue(int64_t value) : value(value) {} - const int64_t value; }; class FloatValue : public Expr { + const double value; + public: FloatValue(double value) : value(value) {} - const double value; }; } diff --git a/compiler/include/AST/Module/Import.h b/compiler/include/AST/Module/Import.h index ec7ef29..f3acd06 100644 --- a/compiler/include/AST/Module/Import.h +++ b/compiler/include/AST/Module/Import.h @@ -7,8 +7,9 @@ namespace ast { class Import : public ASTNode { + const std::string moduleName; + public: Import(const std::string &moduleName) : moduleName(moduleName) {} - const std::string moduleName; }; } \ No newline at end of file diff --git a/compiler/include/AST/Module/Module.h b/compiler/include/AST/Module/Module.h index a25a242..8d0d0b5 100644 --- a/compiler/include/AST/Module/Module.h +++ b/compiler/include/AST/Module/Module.h @@ -2,6 +2,7 @@ #include "AST/Base.h" #include +#include namespace ast { @@ -9,20 +10,11 @@ namespace ast class Module : public ASTNode { + const std::vector> imports; + const std::vector> stmts; + public: - Module(const std::vector &imports, const std::vector &stmts) + Module(std::vector> &imports, std::vector> &stmts) : imports(std::move(imports)), stmts(std::move(stmts)) {} - - ~Module() - { - for (auto &import : imports) - delete import; - - for (auto &stmt : stmts) - delete stmt; - } - - const std::vector &imports; - const std::vector stmts; }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/ExprStmt.h b/compiler/include/AST/Stmt/ExprStmt.h index a51e5ad..7160349 100644 --- a/compiler/include/AST/Stmt/ExprStmt.h +++ b/compiler/include/AST/Stmt/ExprStmt.h @@ -1,15 +1,15 @@ #pragma once #include "AST/Base.h" +#include namespace ast { class ExprStmt : public Stmt { - public: - ExprStmt(const Expr *expr) : expr(expr) {} - ~ExprStmt() { delete expr; } + const std::unique_ptr expr; - const Expr *expr; + public: + ExprStmt(std::unique_ptr &expr) : expr(std::move(expr)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/FnDecl.h b/compiler/include/AST/Stmt/FnDecl.h index 58eff36..bb05ea3 100644 --- a/compiler/include/AST/Stmt/FnDecl.h +++ b/compiler/include/AST/Stmt/FnDecl.h @@ -3,29 +3,21 @@ #include "AST/Base.h" #include #include +#include namespace ast { - typedef std::pair FnArg; + typedef std::pair> FnArg; class FnDecl : public Stmt { - public: - FnDecl(const std::string &name, const std::vector &args, const Type *returnType, const Expr *body) - : name(name), args(std::move(args)), returnType(returnType), body(body) {} - - ~FnDecl() - { - for (auto &arg : args) - delete arg.second; - - delete returnType; - delete body; - } - const std::string name; const std::vector args; - const Type *returnType; - const Expr *body; + const std::unique_ptr returnType; + const std::unique_ptr body; + + public: + FnDecl(const std::string &name, std::vector &args, std::unique_ptr &returnType, std::unique_ptr &body) + : name(name), args(std::move(args)), returnType(std::move(returnType)), body(std::move(body)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TraitAlias.h b/compiler/include/AST/Stmt/TraitAlias.h new file mode 100644 index 0000000..4de89ab --- /dev/null +++ b/compiler/include/AST/Stmt/TraitAlias.h @@ -0,0 +1,19 @@ +#pragma once + +#include "AST/Base.h" +#include +#include +#include + +namespace ast +{ + class TraitAlias : public Stmt + { + const std::string alias; + const std::string aliased; + + public: + TraitAlias(const std::string &alias, const std::string &aliased) + : alias(alias), aliased(aliased) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TraitDecl.h b/compiler/include/AST/Stmt/TraitDecl.h deleted file mode 100644 index 2d0f20b..0000000 --- a/compiler/include/AST/Stmt/TraitDecl.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "AST/Base.h" -#include -#include - -namespace ast -{ - class FnDecl; - - class TraitDecl : public Stmt - { - public: - TraitDecl(const std::string &name, const std::vector &traits) - : name(name), traits(std::move(traits)) {} - ~TraitDecl() - { - for (auto &trait : traits) - delete trait; - } - - const std::string name; - const std::vector traits; - }; -} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TraitDef.h b/compiler/include/AST/Stmt/TraitDef.h new file mode 100644 index 0000000..cd01e06 --- /dev/null +++ b/compiler/include/AST/Stmt/TraitDef.h @@ -0,0 +1,21 @@ +#pragma once + +#include "AST/Base.h" +#include +#include +#include + +namespace ast +{ + class FnDecl; + + class TraitDef : public Stmt + { + const std::string name; + const std::vector> traits; + + public: + TraitDef(const std::string &name, std::vector> &traits) + : name(name), traits(std::move(traits)) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TypeAlias.h b/compiler/include/AST/Stmt/TypeAlias.h new file mode 100644 index 0000000..6dfe87c --- /dev/null +++ b/compiler/include/AST/Stmt/TypeAlias.h @@ -0,0 +1,19 @@ +#pragma once + +#include "AST/Base.h" +#include +#include +#include + +namespace ast +{ + class TypeAlias : public Stmt + { + const std::string alias; + const std::unique_ptr type; + + public: + TypeAlias(const std::string &alias, std::unique_ptr &type) + : alias(alias), type(std::move(type)) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TypeDecl.h b/compiler/include/AST/Stmt/TypeDecl.h deleted file mode 100644 index 1778fce..0000000 --- a/compiler/include/AST/Stmt/TypeDecl.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "AST/Base.h" -#include -#include - -namespace ast -{ - class FnDecl; - - typedef std::pair TypeAttr; - - class TypeDecl : public Stmt - { - public: - TypeDecl(const std::string &name, const std::vector &attrs, const std::vector &members) - : name(name), attrs(std::move(attrs)), members(std::move(members)) {} - ~TypeDecl() - { - for (auto &attr : attrs) - delete attr.second; - - for (auto &member : members) - delete member; - } - - const std::string name; - const std::vector attrs; - const std::vector members; - }; -} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TypeDef.h b/compiler/include/AST/Stmt/TypeDef.h new file mode 100644 index 0000000..736e27f --- /dev/null +++ b/compiler/include/AST/Stmt/TypeDef.h @@ -0,0 +1,24 @@ +#pragma once + +#include "AST/Base.h" +#include +#include +#include + +namespace ast +{ + class FnDecl; + + typedef std::pair> TypeAttr; + + class TypeDef : public Stmt + { + const std::string name; + const std::vector attrs; + const std::vector> members; + + public: + TypeDef(const std::string &name, std::vector &attrs, std::vector> &members) + : name(name), attrs(std::move(attrs)), members(std::move(members)) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/ValDecl.h b/compiler/include/AST/Stmt/ValDecl.h index 783423e..22039fd 100644 --- a/compiler/include/AST/Stmt/ValDecl.h +++ b/compiler/include/AST/Stmt/ValDecl.h @@ -2,23 +2,18 @@ #include "AST/Base.h" #include +#include namespace ast { class ValDecl : public Stmt { - public: - ValDecl(const std::string &name, const Type *type, const Expr *value) - : name(name), type(type), value(value) {} - - ~ValDecl() - { - delete type; - delete value; - } - const std::string name; - const Type *type; - const Expr *value; + const std::unique_ptr type; + const std::unique_ptr value; + + public: + ValDecl(const std::string &name, std::unique_ptr &type, std::unique_ptr &value) + : name(name), type(std::move(type)), value(std::move(value)) {} }; } \ No newline at end of file diff --git a/compiler/include/AST/Type/Closure.h b/compiler/include/AST/Type/Closure.h new file mode 100644 index 0000000..7565d37 --- /dev/null +++ b/compiler/include/AST/Type/Closure.h @@ -0,0 +1,18 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class ClosureType : public Type + { + const std::vector> from; + const std::unique_ptr to; + + public: + ClosureType(std::vector> &from, std::unique_ptr &to) + : from(std::move(from)), to(std::move(to)) {} + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Type/Function.h b/compiler/include/AST/Type/Function.h deleted file mode 100644 index f1a07b6..0000000 --- a/compiler/include/AST/Type/Function.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "AST/Base.h" -#include - -namespace ast -{ - class FunctionType : public Type - { - public: - FunctionType(const std::vector &from, const Type *to) - : from(std::move(from)), to(to) {} - - ~FunctionType() - { - for (auto &arg : from) - delete arg; - - delete to; - } - - const std::vector from; - const Type *to; - }; -} \ No newline at end of file diff --git a/compiler/include/AST/Type/Generic.h b/compiler/include/AST/Type/Generic.h index 49b11e9..df5811c 100644 --- a/compiler/include/AST/Type/Generic.h +++ b/compiler/include/AST/Type/Generic.h @@ -3,22 +3,17 @@ #include "AST/Base.h" #include #include +#include namespace ast { class GenericType : public Type { - public: - GenericType(const std::string &name, const std::vector &types) - : name(name), types(std::move(types)) {} - - ~GenericType() - { - for (auto &type : types) - delete type; - } - const std::string name; - const std::vector types; + const std::vector> types; + + public: + GenericType(const std::string &name, std::vector> &types) + : name(name), types(std::move(types)) {} }; } diff --git a/compiler/include/AST/Type/Named.h b/compiler/include/AST/Type/Named.h index 4b6799b..9c0cdd0 100644 --- a/compiler/include/AST/Type/Named.h +++ b/compiler/include/AST/Type/Named.h @@ -7,8 +7,9 @@ namespace ast { class NamedType : public Type { + const std::string name; + public: NamedType(const std::string &name) : name(name) {} - const std::string name; }; } \ No newline at end of file diff --git a/compiler/include/AST/Type/Tuple.h b/compiler/include/AST/Type/Tuple.h index 56c6463..b8a6595 100644 --- a/compiler/include/AST/Type/Tuple.h +++ b/compiler/include/AST/Type/Tuple.h @@ -2,20 +2,16 @@ #include "AST/Def.h" #include +#include namespace ast { class TupleType : public Type { + const std::vector> types; + public: - TupleType(const std::vector &types) : types(std::move(types)) {} - - ~TupleType() - { - for (auto &type : types) - delete type; - } - - const std::vector types; + TupleType(std::vector> &types) + : types(std::move(types)) {} }; } \ No newline at end of file diff --git a/compiler/include/Parser.h b/compiler/include/Parser.h index 1a289a1..cef89b2 100644 --- a/compiler/include/Parser.h +++ b/compiler/include/Parser.h @@ -1,18 +1,18 @@ #pragma once #include +#include #include "AST/Def.h" -#include "parser.gen.h" +#include "plsmLexer.h" +#include "plsmParser.h" -class Parser +namespace plsm { -public: - Parser() {} + std::unique_ptr parse(const std::string &input); +} - ast::Module *parse(const std::string &file, const std::stringstream &input); - - std::string file; - yy::location location; - ast::Module *module; -}; +namespace adscript +{ + std::unique_ptr parse(const std::string &input); +} diff --git a/compiler/lexer.ll b/compiler/lexer.ll deleted file mode 100644 index 1afe54b..0000000 --- a/compiler/lexer.ll +++ /dev/null @@ -1,67 +0,0 @@ -%{ -#include "parser.gen.h" -#include "Parser.h" - -#undef YY_DECL -#define YY_DECL yy::parser::symbol_type yylex(Parser &driver) - -#define yyterminate() yy::parser::make_END(yy::location()) - -#define _token(token) yy::parser::make_##token(yytext, driver.location) -%} - -%option noyywrap nounput noinput batch - -digit [0-9] -bindigit [0-1] -octdigit [0-7] -hexdigit [0-9a-fA-F] - -letter [a-zA-Z] - -opchar ("+"|"-"|"*"|"/"|"%"|"!"|"&"|"$"|"§"|"|"|"="|"<"|">"|"?"|"~"|"#"|":"|"^"|"\\"|".") - -whitespace [ \n\t\r\v]+ - -%% - -"0b"{bindigit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 2), driver.location); } -"0o"{octdigit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 8), driver.location); } -"0x"{hexdigit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 16), driver.location); } -{digit}+ { return yy::parser::make_INT(std::strtol(yytext, NULL, 10), driver.location); } - -{digit}*"."{digit}+ { return yy::parser::make_FLOAT(std::strtod(yytext, NULL), driver.location); } - - -{opchar}+ { std::string text = yytext; - if (text == "=") return _token(EQUALS); - if (text == "->") return _token(RARR); - if (text == ".") return _token(DOT); - return _token(OPERATOR); } - -"," { return _token(COMMA); } -";" { return _token(SEMI); } -"(" { return _token(LPAREN); } -")" { return _token(RPAREN); } -"[" { return _token(LBRACKET); } -"]" { return _token(RBRACKET); } -"{" { return _token(LBRACE); } -"}" { return _token(RBRACE); } - -"binop" { return _token(BINOP); } -"declare" { return _token(DECLARE); } -"fn" { return _token(FN); } -"import" { return _token(IMPORT); } -"trait" { return _token(TRAIT); } -"type" { return _token(TYPE); } -"unop" { return _token(UNOP); } -"val" { return _token(VAL); } - - -{letter}({digit}|{letter})* { return _token(IDENTIFIER); } - -<> { return yy::parser::make_END(driver.location); } - -{whitespace} { ; } - -%% diff --git a/compiler/parser.yy b/compiler/parser.yy deleted file mode 100644 index 3a9120f..0000000 --- a/compiler/parser.yy +++ /dev/null @@ -1,289 +0,0 @@ -%require "3.8" -%language "c++" - -%header - -%define api.token.raw -%define api.value.type variant -%define api.token.constructor -%define api.token.prefix {TOK_} - -%define parse.assert -%define parse.trace -%define parse.error detailed -%define parse.lac full - -%locations -%define api.location.file "../include/location.gen.h" -%define api.location.include {"location.gen.h"} - -%code requires { -#include "AST/Def.h" -class Parser; -} - -%lex-param { Parser &driver } -%parse-param { Parser &driver } - -%code { -#include "Parser.h" -yy::parser::symbol_type yylex(Parser &driver); -} - -%token INT "integer literal" -%token FLOAT "float literal" - -%token - OPERATOR "operator" - IDENTIFIER "identifier" - - RARR "->" - EQUALS "=" - DOT "." - COMMA "," - SEMI ";" - LPAREN "(" - RPAREN ")" - LBRACKET "[" - RBRACKET "]" - LBRACE "{" - RBRACE "}" - - BINOP "binop" - DECLARE "declare" - FN "fn" - IMPORT "import" - TRAIT "trait" - TYPE "type" - UNOP "unop" - VAL "val" -; - -%token END 0 "end of file" - -%type > - topLevelStmts - blockStmts -; - -%type - topLevelStmt - blockStmt -; - -%type > fnDecls fnDecls0; -%type fnDecl fnDef; -%type valDecl; - -%type > - types - tupleTypes - fnTypeArgs -; - -%type type type1; - -%type > exprs args; - -%type - expr - expr3 - expr2 - expr1 - expr0 - literal -; - -%type fnArg; -%type > fnArgs fnArgs0; - -%type > - lambdaArgs - identifiers -; - -%type - moduleName - type0 - operator - identifier - keyword -; - -%type import; -%type > - imports0 - imports -; - -%type traitDecl; -%type typeDecl; - -%start module - -%% - -module: imports topLevelStmts { driver.module = new ast::Module($1, $2); } - ; - - -imports: %empty { ; } - | imports0 { $$ = std::move($1); } - ; - -imports0: import { $$.push_back($1); } - | imports0 import { $1.push_back($2); $$ = std::move($1); } - ; - -import: IMPORT moduleName ";" { $$ = new ast::Import($2); } - ; - -moduleName: identifier { $$ = $1; } - | moduleName "." identifier { $$ = $1 + $2 + $3; } - ; - -topLevelStmts: topLevelStmt { $$.push_back($1); } - | topLevelStmts topLevelStmt { $1.push_back($2); $$ = std::move($1); } - ; - -topLevelStmt: fnDef { $$ = $1; } - | fnDecl { $$ = $1; } - | valDecl { $$ = $1; } - | typeDecl { $$ = $1; } - | traitDecl { $$ = $1; } - ; - -blockStmts: blockStmt { $$.push_back($1); } - | blockStmts blockStmt { $1.push_back($2); $$ = std::move($1); } - ; - -blockStmt: valDecl { $$ = $1; } - | fnDef { $$ = $1; } - | expr ";" { $$ = new ast::ExprStmt($1); } - ; - -traitDecl: TRAIT identifier "=" "{" fnDecls "}" { $$ = new ast::TraitDecl($2, $5); } - ; - -typeDecl: TYPE identifier "=" "(" fnArgs ")" "{" fnDecls "}" { $$ = new ast::TypeDecl($2, $5, $8); } - ; - -fnDecls: %empty { ; } - | fnDecls0 { $$ = std::move($1); } - ; - -fnDecls0: fnDecl { $$.push_back($1); } - | fnDecls0 fnDecl { $1.push_back($2); $$ = std::move($1); } - ; - -valDecl: VAL identifier "=" expr ";" { $$ = new ast::ValDecl($2, nullptr, $4); } - | VAL identifier type "=" expr ";" { $$ = new ast::ValDecl($2, $3, $5); } - ; - -fnDef : FN identifier "[" fnArgs "]" type "=" expr ";" { $$ = new ast::FnDecl($2, $4, $6, $8); } - ; - -fnDecl: FN identifier "[" fnArgs "]" type ";" { $$ = new ast::FnDecl($2, $4, $6, nullptr); } - ; - -fnArgs: %empty { ; } - | fnArgs0 { $$ = std::move($1); } - ; - -fnArgs0: fnArg { $$.push_back($1); } - | fnArgs0 "," fnArg { $$.push_back($3); $$ = std::move($1); } - ; - -fnArg: identifier type { $$ = ast::FnArg($1, $2); } - ; - -types: type { $$.push_back($1); } - | types "," type { $1.push_back($3); $$ = std::move($1); } - ; - -type: type1 - | "(" type ")" { $$ = $2; } - | "(" tupleTypes ")" { $$ = new ast::TupleType($2); } - | "[" fnTypeArgs "]" "->" type { $$ = new ast::FunctionType($2, $5); } - ; - -type1: type0 { $$ = new ast::NamedType($1); } - | type0 "{" types "}" { $$ = new ast::GenericType($1, $3); } - ; - -type0: identifier; - -tupleTypes: type "," type { $$.push_back($1); $$.push_back($3); } - | tupleTypes "," type { $1.push_back($3); $$ = std::move($1); } - ; - -fnTypeArgs: %empty { ; } - | types { $$ = std::move($1); } - ; - -exprs: expr { $$.push_back($1); } - | exprs "," expr { $1.push_back($3); $$ = std::move($1); } - ; - -expr: expr3 { $$ = $1; } - ; - -expr3: expr2 { $$ = $1; } - | "[" lambdaArgs "]" "->" expr { $$ = nullptr; } - | "{" blockStmts "}" { $$ = new ast::BlockExpr($2); } - ; - -expr2: expr1 { $$ = $1; } - | expr2 operator expr1 { $$ = new ast::BinExpr($1, $2, $3); } - ; - -expr1: expr0 { $$ = $1; } - | operator expr1 { $$ = new ast::UnaryExpr($1, $2); } - ; - -expr0: literal { $$ = $1; } - | identifier { $$ = new ast::Identifier($1); } - | expr0 "[" args "]" { $$ = new ast::CallExpr($1, $3); } - | "(" expr ")" { $$ = new ast::PrefExpr($2); } - | expr0 "." identifier { $$ = $1; } - ; - -lambdaArgs: %empty { ; } - | identifiers { $$ = std::move($1); } - ; - -args: %empty { ; } - | exprs { $$ = std::move($1); } - ; - - -literal: INT { $$ = new ast::IntValue($1); } - | FLOAT { $$ = new ast::FloatValue($1); } - ; - -operator: "->" - | "=" - | OPERATOR - ; - -identifiers: identifier { $$.push_back($1); } - | identifiers "," identifier { $1.push_back($3); $$ = std::move($1); } - ; - -identifier: keyword - | IDENTIFIER - ; - -keyword: FN - | VAL - | UNOP - | BINOP - | IMPORT - | DECLARE - ; - -%% - -void yy::parser::error(const location_type& l, const std::string& m) { - std::cerr << l << ": " << m << '\n'; -} diff --git a/compiler/plsm.g4 b/compiler/plsm.g4 new file mode 100644 index 0000000..7c39214 --- /dev/null +++ b/compiler/plsm.g4 @@ -0,0 +1,78 @@ +grammar plsm; + +module: moduleImport* (let | fnDecl | fnDef | traitDef | typeDef)*; + +moduleImport: IMPORT moduleName ';'; +moduleName: identifier ('.' identifier)*; + +traitDef: TRAIT identifier '=' identifier ';' + | TRAIT identifier '=' '{' (fnDecl)* '}' ';'; + +typeDef: TYPE identifier '=' type ';' + | TYPE identifier '=' ('(' fnDefArgs ')')? '{' (fnDecl | fnDef)* '}' ';'; + +fnDef: FN identifier '[' fnDefArgs? ']' type '=' expr ';'; +fnDefArgs: identifier type (',' identifier type)*; + +fnDecl: FN identifier '[' fnDeclArgs? ']' type ';'; +fnDeclArgs: identifier? type (',' identifier? type)*; + +let: LET identifier type? '=' expr ';'; + +exprStmt: expr ';'; + +type: type2; +type2: type1 + | '(' type ')' + | '(' tupleTypeList ')' // tuple + | '[' typeList? ']' '->' type; // closure +type1: type0 + | type0 '{' typeList '}'; // generic +type0: identifier; + +tupleTypeList: type ',' type (',' type)*; +typeList: type (',' type)*; + + +expr: expr3; +expr3: expr2 + | '[' identifierList? ']' '->' expr // closure + | '{' (let | exprStmt | fnDef)* (expr ';') '}'; +expr2: expr1 + | expr2 operator expr1; // binary expr +expr1: expr0 + | operator expr0; // unary expr +expr0: literal + | identifier + | expr0 '[' exprList? ']' // fn call + | '(' expr ')' + | expr0 '.' identifier; // property accessor + +exprList: expr (',' expr)*; + +identifierList: identifier (',' identifier)*; + +literal: 'null' | INT_LIT | FLOAT_LIT; + +operator: '=' | '->' + | OPERATOR; + +identifier: keyword | IDENTIFIER; +keyword: BINOP | FN | IMPORT | LET | NATIVE | TRAIT | TYPE | UNOP; + + +INT_LIT: [0-9]+ | '0x' [0-9a-fA-F]+ | '0o' [0-7]+ | '0b' [01]+; +FLOAT_LIT: [0-9]+ '.' | [0-9]* '.' [0-9]+; + +OPERATOR: ('+'|'-'|'*'|'/'|'%'|'!'|'&'|'$'|'§'|'|'|'='|'<'|'>'|'?'|'~'|'#'|':'|'^'|'\\'|'.')+; + +BINOP: 'binop'; +FN: 'fn'; +IMPORT: 'import'; +LET: 'let'; +NATIVE: 'native'; +TRAIT: 'trait'; +TYPE: 'type'; +UNOP: 'unop'; + +IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; diff --git a/compiler/src/Parser.cpp b/compiler/src/Parser.cpp index b42ce60..d7c7bc4 100644 --- a/compiler/src/Parser.cpp +++ b/compiler/src/Parser.cpp @@ -1,20 +1,131 @@ #include "Parser.h" +#include "plsmBaseVisitor.h" + #include -#include -void yy_scan_string(const char *); - -ast::Module *Parser::parse(const std::string &file, const std::stringstream &input) +class Visitor : public plsmBaseVisitor { - module = nullptr; +public: + Visitor() {} - this->file = file; - location.initialize(&file); + template + inline T visitT(antlr4::tree::ParseTree *ctx) + { + return std::any_cast(visit(ctx)); + } - yy_scan_string(input.str().data()); + template + inline std::unique_ptr visitU(antlr4::tree::ParseTree *ctx) + { + return std::unique_ptr(visitT(ctx)); + } - int res = yy::parser(*this)(); + virtual std::any visitModule(plsmParser::ModuleContext *ctx) override + { + std::vector> imports; + std::vector> stmts; - return module; + for (auto &child : ctx->children) + { + if (plsmParser::ModuleImportContext *c = dynamic_cast(child)) + imports.push_back(visitU(child)); + else + stmts.push_back(visitU(child)); + } + + return std::any(new ast::Module(imports, stmts)); + } + + virtual std::any visitModuleImport(plsmParser::ModuleImportContext *ctx) override + { + return std::any(new ast::Import(visitT(ctx->moduleName()))); + } + + virtual std::any visitModuleName(plsmParser::ModuleNameContext *ctx) override + { + auto name = visitT(ctx->identifier(0)); + + for (size_t i = 1; ctx->identifier(i); i++) + { + name = name + "." + visitT(ctx->identifier(i)); + } + + return std::any(name); + } + + virtual std::any visitTraitDef(plsmParser::TraitDefContext *ctx) override + { + auto name = visitT(ctx->identifier(0)); + + if (ctx->identifier(1)) + { + auto aliased = visitT(ctx->identifier(1)); + return std::any(new ast::TraitAlias(name, aliased)); + } + + std::vector> fns; + + for (size_t i = 0; ctx->fnDecl(i); i++) + fns.push_back(visitU(ctx->fnDecl(i))); + + return std::any(new ast::TraitDef(name, fns)); + } + + virtual std::any visitTypeDef(plsmParser::TypeDefContext *ctx) override + { + auto name = visitT(ctx->identifier()); + + if (ctx->type()) + { + auto gen = visitU(ctx->type()); + return std::any(new ast::TypeAlias(name, gen)); + } + + std::vector args; + } +}; + +class ErrorListener : public antlr4::BaseErrorListener +{ + std::string *error; + +public: + ErrorListener(std::string *error) : error(error) {} + + virtual void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, size_t charPositionInLine, + const std::string &msg, std::exception_ptr e) override + { + std::stringstream ss; + ss << "line " << line << ":" << charPositionInLine << ": " << msg; + *error = ss.str(); + } +}; + +std::unique_ptr +plsm::parse(const std::string &input) +{ + auto istream = antlr4::ANTLRInputStream(input); + auto lexer = plsmLexer(&istream); + auto tokens = antlr4::CommonTokenStream(&lexer); + auto parser = plsmParser(&tokens); + + std::string error; + ErrorListener listener(&error); + parser.removeErrorListeners(); + parser.addErrorListener(&listener); + + auto tree = parser.module(); + + if (error.size()) + throw std::runtime_error(error); + + auto module = std::any_cast(Visitor().visitModule(tree)); + return std::unique_ptr(module); +} + +std::unique_ptr +adscript::parse(const std::string &input) +{ + throw std::logic_error("adscript::parse not implemented"); } diff --git a/compiler/src/main.cpp b/compiler/src/main.cpp index 0b8326e..cc5d931 100644 --- a/compiler/src/main.cpp +++ b/compiler/src/main.cpp @@ -1,5 +1,3 @@ -#include "Parser.h" - #include #include #include @@ -21,10 +19,10 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - auto module = Parser().parse(argv[1], readFile(argv[1])); + // auto module = Parser().parse(argv[1], readFile(argv[1])); - auto fn = (ast::FnDecl *)module->stmts.at(0); - std::cout << fn->name << std::endl; + // auto fn = (ast::FnDecl *)module->stmts.at(0); + // std::cout << fn->name << std::endl; - delete module; + // delete module; } diff --git a/compiler/thirdparty/antlr-4.13.1-complete.jar b/compiler/thirdparty/antlr-4.13.1-complete.jar new file mode 100644 index 0000000..f539ab0 Binary files /dev/null and b/compiler/thirdparty/antlr-4.13.1-complete.jar differ diff --git a/examples/stdlib.plsm b/examples/stdlib.plsm index a6354c0..4394147 100644 --- a/examples/stdlib.plsm +++ b/examples/stdlib.plsm @@ -1,33 +1,38 @@ type Bool = { - declare unop ! Bool; + native unop ! Bool; - declare binop &&[b Bool] Bool; - declare binop ||[b Bool] Bool; + native binop ||[Bool] Bool; + native binop &&[Bool] Bool; }; +type Byte = {}; + type Int = { - declare unop + Int; - declare unop - Int; + native unop + Int; + native unop - Int; + native unop ~ Int; - declare binop ==[Int] Bool; - declare binop !=[Int] Bool; - declare binop >[Int] Bool; - declare binop <[Int] Bool; - declare binop >=[Int] Bool; - declare binop <=[Int] Bool; + native binop ==[Int] Bool; + native binop !=[Int] Bool; + native binop >[Int] Bool; + native binop <[Int] Bool; + native binop >=[Int] Bool; + native binop <=[Int] Bool; - declare binop +[Int] Int; - declare binop -[Int] Int; - declare binop *[Int] Int; - declare binop /[Int] Int; - declare binop %[Int] Int; + native binop <<[Int] Int; + native binop >>[Int] Int; + native binop |[Int] Int; + native binop &[Int] Int; - declare factory [f Float]; - declare factory []; + native binop +[Int] Int; + native binop -[Int] Int; + native binop *[Int] Int; + native binop /[Int] Int; + native binop %[Int] Int; - declare fn str[] String; + fn str[] String; }; -trait List{T} = { - fn +type Float = { + };