diff --git a/.clangd b/.clangd deleted file mode 100644 index 8bf35b6..0000000 --- a/.clangd +++ /dev/null @@ -1,2 +0,0 @@ -CompileFlags: - CompilationDatabase: "build/Unix" diff --git a/.gitmodules b/.gitmodules index 8f51d00..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "TreeSitterBraneScript"] - path = TreeSitterBraneScript - url = https://github.com/WireWhiz/TreeSitterBraneScript diff --git a/.vscode/launch.json b/.vscode/launch.json index a6682b8..a87114b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,26 +2,28 @@ "version": "0.2.0", "configurations": [ { - "type": "lldb", + "type": "gdb", "request": "launch", "name": "Cli-Debug", - "preLaunchTask": "cmake-build-debug", + "preLaunchTask": "cmake-install-debug", "expressions": "native", - "program": "./build/Debug/executables/BraneScriptCli", + "program": "./build/Debug/cli/BraneScriptCli", "console": "integratedTerminal", "args": [ - "test.bscript" + "exampleScripts/test.bscript" ] }, { - "type": "lldb", + "type": "gdb", "request": "launch", "name": "Cli-Release", - "preLaunchTask": "cmake-build-release", + "preLaunchTask": "cmake-install-release", "expressions": "native", - "program": "./build/Release/executables/BraneScriptCli", - "console": "integratedTerminal" - + "program": "./build/Release/cli/BraneScriptCli", + "console": "integratedTerminal", + "args": [ + "exampleScripts/test.bscript" + ] } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 02a0b88..11b9675 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,6 @@ "version": "2.0.0", "showOutput": "always", "tasks": [ - { "taskName": "cmake-configure-debug", "label": "cmake-configure-debug", @@ -10,7 +9,7 @@ "options": { "cwd": "${workspaceRoot}" }, - "command": "cmake -S. -B./build/Debug -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=\"${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBS_BUILD_TESTS=ON", + "command": "cmake -S. -B./build/Debug -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DVCPKG_TARGET_TRIPLET=x64-mingw-static -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=\"${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBS_BUILD_TESTS=ON", "presentation": "always" }, { @@ -23,44 +22,88 @@ "options": { "cwd": "${workspaceRoot}" }, - "command": "cmake --build ./build/Debug --target BraneScriptCli", + "command": "cmake --build ./build/Debug", "presentation": "always" }, { "taskName": "cmake-configure-release", - "label": "cmake-configure-release", + "label": "cmake-configure-release", "type": "shell", "options": { "cwd": "${workspaceRoot}" }, - "command": "cmake -S. -B./build/Release -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=\"${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBS_BUILD_TESTS=ON", + "command": "cmake -S. -B./build/Release -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DVCPKG_TARGET_TRIPLET=x64-mingw-static -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=\"${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBS_BUILD_TESTS=ON -DTREESITTER_BRANESCRIPT_DIR=../TreeSitterBraneScript", "presentation": "always" }, { "taskName": "cmake-build-release", "label": "cmake-build-release", "type": "shell", - "dependsOn":[ + "dependsOn": [ "cmake-configure-release" ], "options": { "cwd": "${workspaceRoot}" }, - "command": "cmake --build ./build/Release --target BraneScriptCli" + "command": "cmake --build ./build/Release" }, { - "taskName": "cmake-configure", - "label": "cmake-configure", + "taskName": "build-db-debug", + "label": "build-db-debug", "type": "shell", + "dependsOn": [ + "cmake-configure-debug" + ], "options": { "cwd": "${workspaceRoot}" }, + "windows": { + "command": "mv ./build/Debug/compile_commands.json ./build/ -Force" + }, + "linux": { + "command": "mv ./build/Debug/compile_commands.json ./build/ -f" + } + }, + { + "taskName": "build-db-release", + "label": "build-db-release", + "type": "shell", "dependsOn": [ - "cmake-configure-release", - "cmake-configure-debug" + "cmake-configure-release" + ], + "options": { + "cwd": "${workspaceRoot}" + }, + "windows": { + "command": "mv ./build/Release/compile_commands.json ./build/ -Force" + }, + "linux": { + "command": "mv ./build/Release/compile_commands.json ./build/ -f" + } + }, + { + "taskName": "cmake-install-debug", + "label": "cmake-install-debug", + "type": "shell", + "dependsOn": [ + "cmake-build-debug" + ], + "options": { + "cwd": "${workspaceRoot}/build/Debug" + }, + "command": "cmake --install . --component cli --prefix ./cli" + }, + { + "taskName": "cmake-install-cli-release", + "label": "cmake-install-cli-release", + "type": "shell", + "dependsOn": [ + "cmake-build-release" ], - "command": "cmake -S. -B./build/Unix -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=\"${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G \"Unix Makefiles\" -DBS_BUILD_TESTS=ON" + "options": { + "cwd": "${workspaceRoot}/build/Release" + }, + "command": "cmake --install . --component cli --prefix ./cli" } ] } - diff --git a/CMakeLists.txt b/CMakeLists.txt index 08a37dd..4ccb9ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,26 +1,53 @@ cmake_minimum_required(VERSION 3.23) +include(FetchContent) + project(BraneScript VERSION "0.2.0" DESCRIPTION "BraneScript" HOMEPAGE_URL "https://github.com/wirewhiz/branescript" LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) option(BS_BUILD_TESTS "Build tests" ON) +option(TreeSitterBS_DIR "Set a manual path to use for the TreeSitterBraneScript repo") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/executables/$<0:>) +# Fetch and run our parser generator +set(TSBS_REPO https://github.com/BraneReality/TreeSitterBraneScript.git) +if(TSBS_DIR) + FetchContent_Declare( + TreeSitterBraneScript + GIT_REPOSITORY ${TSBS_REPO} + GIT_TAG main + SOURCE_DIR ${TSBS_DIR} + ) +else() + FetchContent_Declare( + TreeSitterBraneScript + GIT_REPOSITORY ${TSBS_REPO} + GIT_TAG main + ) +endif() +FetchContent_MakeAvailable(TreeSitterBraneScript) + +set(GRAMMAR_DIR ${treesitterbranescript_SOURCE_DIR}) -set(GRAMMAR_DIR ${CMAKE_SOURCE_DIR}/TreeSitterBraneScript) -set(GRAMMAR_FILE ${CMAKE_SOURCE_DIR}/TreeSitterBraneScript/grammar.js) +message("Grammar at ${GRAMMAR_DIR}") +set(GRAMMAR_FILE "${GRAMMAR_DIR}/grammar.js") set(GRAMMAR_BUILD_DIR ${CMAKE_BINARY_DIR}/ts-branescript) set(GENERATE_PARSER_CMD tree-sitter generate -b ${GRAMMAR_FILE}) set(PARSER_LIB_NAME parser${CMAKE_SHARED_LIBRARY_SUFFIX}) set(BUILD_PARSER_CMD tree-sitter build -o ${GRAMMAR_BUILD_DIR}/${PARSER_LIB_NAME}) -file(MAKE_DIRECTORY ${GRAMMAR_BUILD_DIR}) +if(MINGW) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -static -static-libgcc -static-libstdc++") + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g2") + endif() +endif(MINGW) +#[[file(MAKE_DIRECTORY ${GRAMMAR_BUILD_DIR}) message("Watching grammar at ${GRAMMAR_FILE}") add_custom_command( OUTPUT ${GRAMMAR_BUILD_DIR}/ts-build-command.stamp @@ -28,13 +55,6 @@ add_custom_command( COMMAND ${GENERATE_PARSER_CMD} COMMAND echo ${BUILD_PARSER_CMD} COMMAND ${BUILD_PARSER_CMD} - COMMAND - ${CMAKE_COMMAND} -E rm -f - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PARSER_LIB_NAME} - COMMAND - ${CMAKE_COMMAND} -E copy - ${GRAMMAR_BUILD_DIR}/${PARSER_LIB_NAME} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PARSER_LIB_NAME} WORKING_DIRECTORY ${GRAMMAR_BUILD_DIR} DEPENDS ${GRAMMAR_FILE} @@ -44,13 +64,7 @@ add_custom_target( tree_sitter_bs_parser DEPENDS ${GRAMMAR_BUILD_DIR}/ts-build-command.stamp -) - -add_library(TreeSitterBraneScript INTERFACE) -add_dependencies(TreeSitterBraneScript tree_sitter_bs_parser) - -target_link_libraries(TreeSitterBraneScript INTERFACE ${GRAMMAR_BUILD_DIR}/parser${CMAKE_STATIC_LIBRARY_SUFFIX}) -target_include_directories(TreeSitterBraneScript INTERFACE ${GRAMMAR_DIR}/bindings/c) +)]] add_subdirectory(src) diff --git a/TreeSitterBraneScript b/TreeSitterBraneScript deleted file mode 160000 index f6623aa..0000000 --- a/TreeSitterBraneScript +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f6623aab857f27fe5095764a0953ced1fade110f diff --git a/test.bscript b/exampleScripts/test.bscript similarity index 100% rename from test.bscript rename to exampleScripts/test.bscript diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1ba78b..fe77ac3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(ir) add_subdirectory(cli) add_subdirectory(parser) -add_subdirectory(compiler) +#add_subdirectory(compiler) add_subdirectory(types) diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 42a46c5..4ed031d 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -11,7 +11,26 @@ llvm_map_components_to_libnames(llvm_libs Support Core IRReader ...) # Link against LLVM libraries target_link_libraries(main PRIVATE ${llvm_libs})]] - add_executable(BraneScriptCli main.cpp) target_link_libraries(BraneScriptCli PRIVATE parser) +install(TARGETS BraneScriptCli + RUNTIME_DEPENDENCIES + PRE_EXCLUDE_REGEXES + ".*tree-sitter-branescript.*" + "api-ms-.*" "ext-ms-.*" # Windows system DLLs + "^/lib.*" # Linux system libraries + "^/usr/lib.*" + POST_EXCLUDE_REGEXES + ".*system32/.*\\.dll" # Windows system directory + "^/lib64/.*" # Linux system directories + "^/usr/lib64/.*" + DESTINATION . + COMPONENT cli) + +install(FILES ${treesitterbranescript_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}tree-sitter-branescript${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION . + COMPONENT cli) +install(DIRECTORY ${PROJECT_SOURCE_DIR}/exampleScripts + DESTINATION . + COMPONENT cli) diff --git a/src/cli/main.cpp b/src/cli/main.cpp index abf044d..8bc2194 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -2,14 +2,15 @@ // Created by WireWhiz on 10/22/2024. // +#include #include #include #include #include #include "parser/documentParser.h" +#include "parser/tree_sitter_branescript.h" #include -#include "../parser/tree_sitter_branescript.h" #include "tree_sitter/api.h" // #include "TSBindings.h" diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index 4a43b60..0cc2f97 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -1,9 +1,9 @@ - find_package(unofficial-tree-sitter CONFIG REQUIRED) +#find_package(TreeSitterBraneScript REQUIRED) add_library(parser STATIC -documentParser.cpp -documentContext.cpp + documentParser.cpp + documentContext.cpp ) -target_link_libraries(parser PUBLIC unofficial::tree-sitter::tree-sitter TreeSitterBraneScript types) +target_link_libraries(parser PUBLIC unofficial::tree-sitter::tree-sitter tree-sitter-branescript types) diff --git a/src/parser/documentParser.cpp b/src/parser/documentParser.cpp index ddfd115..1da305f 100644 --- a/src/parser/documentParser.cpp +++ b/src/parser/documentParser.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include #include #include #include "parser/documentContext.h" @@ -354,10 +356,10 @@ namespace BraneScript } } - std::string message = std::vformat("Found \"{}\", but was expecting one of the following:\n", - std::make_format_args(nodeText(node))); + std::string message = + std::format("Found \"{}\", but was expecting one of the following:\n", nodeText(node)); for(auto t : types) - message += std::vformat("{}\n", std::make_format_args(typeToName(t))); + message += std::format("{}\n", typeToName(t)); errorMessage(node, message); return false; } diff --git a/src/parser/documentParser.cpp~ b/src/parser/documentParser.cpp~ deleted file mode 100644 index 11e112a..0000000 --- a/src/parser/documentParser.cpp~ +++ /dev/null @@ -1,855 +0,0 @@ -// -// Created by WireWhiz on 10/28/2024. -// - -#include "documentParser.h" - -#include -#include -#include -#include -#include -#include -#include -#include "parser/documentContext.h" -#include "tree_sitter_branescript.h" -#include - - -#define Expect(node, _optional, _errorMessage) \ - if(!_optional) \ - { \ - errorMessage(node, _errorMessage); \ - return std::nullopt; \ - } - -namespace BraneScript -{ - template - struct overloads : Ts... - { - using Ts::operator()...; - }; - - template - bool tryCastVariant(std::variant value, std::optional>& result) - { - return std::visit(overloads{[&](auto&& inner) -> bool { - if constexpr(((std::is_same_v) || ...)) - { - result = inner; - return false; - } - result = std::nullopt; - return false; - }}, - std::move(value)); - } - - enum class TSNodeType : uint16_t - { - Unknown = 0, - Number, - Identifier, - ScopedIdentifier, - Type, - TemplateArgument, - TemplateArguments, - Add, - Sub, - Mul, - Div, - Assign, - Block, - VarDefPrefix, - SinkDef, - SinkList, - SourceDef, - SourceList, - Call, - PipelineStage, - AsyncOperation, - Function, - Pipeline, - Module, - SourceFile - }; - - void foreachNodeChild(TSNode node, const std::function& f) - { - uint32_t childCount = ts_node_child_count(node); - for(uint32_t i = 0; i < childCount; ++i) - f(ts_node_child(node, i)); - } - - void foreachNamedNodeChild(TSNode node, const std::function& f) - { - uint32_t childCount = ts_node_named_child_count(node); - for(uint32_t i = 0; i < childCount; ++i) - f(ts_node_named_child(node, i)); - } - - TSRange nodeRange(TSNode node) - { - return {ts_node_start_point(node), ts_node_end_point(node), ts_node_start_byte(node), ts_node_end_byte(node)}; - } - - std::string_view nodeName(TSNode node) - { - return ts_language_symbol_name(tree_sitter_branescript(), ts_node_symbol(node)); - } - - class TSSymbolLookupTable - { - private: - std::vector symbolToNodeType; - std::vector nodeTypeToSymbol; - - void add_entry(const TSLanguage* lang, std::string_view ident, TSNodeType nodeType) - { - auto symbol = ts_language_symbol_for_name(lang, ident.data(), ident.size(), true); - if(symbol >= symbolToNodeType.size()) - symbolToNodeType.resize(symbol + 1, (TSNodeType)UINT16_MAX); - if((uint16_t)nodeType >= nodeTypeToSymbol.size()) - nodeTypeToSymbol.resize((uint16_t)nodeType + 1, (TSSymbol)UINT16_MAX); - symbolToNodeType[symbol] = nodeType; - nodeTypeToSymbol[(uint16_t)nodeType] = symbol; - } - - public: - TSSymbolLookupTable(const TSLanguage* lang) - { - add_entry(lang, "number", TSNodeType::Number); - add_entry(lang, "module", TSNodeType::Module); - add_entry(lang, "identifier", TSNodeType::Identifier); - add_entry(lang, "scopedIdentifier", TSNodeType::ScopedIdentifier); - add_entry(lang, "type", TSNodeType::Type); - add_entry(lang, "templateArgument", TSNodeType::TemplateArgument); - add_entry(lang, "templateArguments", TSNodeType::TemplateArguments); - add_entry(lang, "add", TSNodeType::Add); - add_entry(lang, "sub", TSNodeType::Sub); - add_entry(lang, "mul", TSNodeType::Mul); - add_entry(lang, "div", TSNodeType::Div); - add_entry(lang, "assign", TSNodeType::Assign); - add_entry(lang, "block", TSNodeType::Block); - add_entry(lang, "varDefPrefix", TSNodeType::VarDefPrefix); - add_entry(lang, "sinkDef", TSNodeType::SinkDef); - add_entry(lang, "sinkList", TSNodeType::SinkList); - add_entry(lang, "sourceDef", TSNodeType::SourceDef); - add_entry(lang, "sourceList", TSNodeType::SourceList); - add_entry(lang, "call", TSNodeType::Call); - add_entry(lang, "PipelineStage", TSNodeType::PipelineStage); - add_entry(lang, "asyncOperation", TSNodeType::AsyncOperation); - add_entry(lang, "function", TSNodeType::Function); - add_entry(lang, "pipeline", TSNodeType::Pipeline); - add_entry(lang, "sourceFile", TSNodeType::SourceFile); - } - - std::optional tryToNodeType(TSSymbol symbol) const - { - if(symbol > symbolToNodeType.size()) - return std::nullopt; - auto nodeType = symbolToNodeType[symbol]; - return (uint16_t)nodeType == UINT16_MAX ? std::nullopt : std::make_optional(nodeType); - } - - std::optional tryToSymbol(TSNodeType nodeType) const - { - if((uint16_t)nodeType > nodeTypeToSymbol.size()) - return std::nullopt; - auto symbol = nodeTypeToSymbol[(uint16_t)nodeType]; - return symbol == UINT16_MAX ? std::nullopt : std::make_optional(symbol); - } - }; - - enum class TSFieldName : uint16_t - { - Id = 0, - Child, - Type, - Value, - Mut, - Defs, - Sources, - Sinks, - Stages, - TemplateArgs, - }; - - class TSFieldLookupTable - { - private: - std::vector _fieldIds; - - void add_entry(const TSLanguage* lang, std::string_view textName, TSFieldName fieldName) - { - auto fID = ts_language_field_id_for_name(lang, textName.data(), textName.size()); - - if((uint16_t)fieldName >= _fieldIds.size()) - _fieldIds.resize((uint16_t)fieldName + 1, (TSFieldId)0); - _fieldIds[(uint16_t)fieldName] = fID; - } - - public: - TSFieldLookupTable(const TSLanguage* lang) - { - add_entry(lang, "id", TSFieldName::Id); - add_entry(lang, "child", TSFieldName::Child); - add_entry(lang, "type", TSFieldName::Type); - add_entry(lang, "value", TSFieldName::Value); - add_entry(lang, "mut", TSFieldName::Mut); - add_entry(lang, "defs", TSFieldName::Defs); - add_entry(lang, "sinks", TSFieldName::Sinks); - add_entry(lang, "sources", TSFieldName::Sources); - add_entry(lang, "stages", TSFieldName::Stages); - add_entry(lang, "templateArgs", TSFieldName::TemplateArgs); - } - - TSFieldId get(TSFieldName name) const - { - assert((uint16_t)name < _fieldIds.size() && "Make sure all fields are defined in the constructor"); - return _fieldIds[(uint16_t)name]; - } - }; - - const TSSymbolLookupTable symbolLookupTable = TSSymbolLookupTable(tree_sitter_branescript()); - const TSFieldLookupTable fieldLookupTable = TSFieldLookupTable(tree_sitter_branescript()); - - std::string_view typeToName(TSNodeType type) - { - auto symbol = symbolLookupTable.tryToSymbol(type); - if(!symbol) - return "Unknown"; - return ts_language_symbol_name(tree_sitter_branescript(), symbol.value()); - } - - TSNodeType nodeType(TSNode node) - { - auto nodeType = symbolLookupTable.tryToNodeType(ts_node_symbol(node)); - if(!nodeType) - return TSNodeType::Unknown; - return *nodeType; - } - - template - bool nodeIsType(TSNode node) - { - auto nt = nodeType(node); - return ((nt == Types) || ...); - } - - template - void advanceWhileType(TSNode node, const std::function& f) - { - bool nodeIsCorrectType = true; - if(!ts_node_is_named(node)) - node = ts_node_next_named_sibling(node); - while(!ts_node_is_null(node) && nodeIsType(node)) - { - f(node); - node = ts_node_next_named_sibling(node); - } - } - - struct ScopedScope - { - std::list>& scopes; - Node node; - - ScopedScope(std::list>& scopes, Node node) : scopes(scopes), node(node) {} - - ScopedScope(const ScopedScope&) = delete; - - ScopedScope(ScopedScope&& o) noexcept : scopes(o.scopes) - { - node = o.node; - o.node = nullptr; - } - - ~ScopedScope() - { - if(!node) - return; - assert(scopes.back() == node); - scopes.pop_back(); - } - }; - - struct ParserAPI - { - std::filesystem::path path; - std::string_view source; - std::shared_ptr parser; - std::vector messages; - TSTree* tree; - - std::list> scopes; - - std::optional> currentScope() - { - if(scopes.empty()) - return std::nullopt; - return scopes.back(); - } - - ScopedScope pushScope(Node node) - { - scopes.emplace_back(node); - return ScopedScope(scopes, node); - } - - void verboseMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Verbose, nodeRange(ctx), std::move(message)); - } - - void logMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Log, nodeRange(ctx), std::move(message)); - } - - void warningMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Warning, nodeRange(ctx), std::move(message)); - } - - void errorMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Error, nodeRange(ctx), std::move(message)); - } - - std::optional getField(TSNode node, TSFieldName field) - { - auto result = ts_node_child_by_field_id(node, fieldLookupTable.get(field)); - if(ts_node_is_null(result)) - return std::nullopt; - return result; - } - - bool expectNode(TSNode node, TSNodeType type) - { - auto nodeType = symbolLookupTable.tryToNodeType(ts_node_symbol(node)); - if(nodeType && type == nodeType) - return true; - - std::string message = - std::format("Was expecting \"{}\" but found \"{}\" \n", typeToName(type), nodeText(node)); - errorMessage(node, message); - return false; - } - - bool expectField(TSNode node, const std::vector& types) - { - auto nodeType = symbolLookupTable.tryToNodeType(ts_node_symbol(node)); - if(nodeType) - { - for(auto t : types) - { - if(t == nodeType) - return true; - } - } - - std::string message = std::vformat("Found \"{}\", but was expecting one of the following:\n", - std::make_format_args(nodeText(node))); - for(auto t : types) - message += std::vformat("{}\n", std::make_format_args(typeToName(t))); - errorMessage(node, message); - return false; - } - - std::string_view nodeText(TSNode node) - { - auto start = ts_node_start_byte(node); - auto end = ts_node_end_byte(node); - return {source.data() + start, end - start}; - } - - template - Node makeNode(TSNode context) - { - static_assert(std::is_base_of().value); - - auto new_node = std::make_shared(); - new_node->range = nodeRange(context); - new_node->parent = currentScope(); - - return new_node; - } - - std::optional parse(TSNode node) - { - switch(nodeType(node)) - { - case TSNodeType::SourceFile: - assert(false && "Cannot call parse on root node!"); - return std::nullopt; - case TSNodeType::Module: - return parseModule(node); - case TSNodeType::Pipeline: - return parsePipeline(node); - case TSNodeType::Function: - return parseFunction(node); - case TSNodeType::AsyncOperation: - return parseAsyncOperation(node); - case TSNodeType::Call: - return parseCall(node); - case TSNodeType::SourceList: - return parseSourceList(node); - case TSNodeType::SinkList: - return parseSinkList(node); - case TSNodeType::Block: - return parseBlock(node); - case TSNodeType::Assign: - return parseAssign(node); - case TSNodeType::Div: - return parseDiv(node); - case TSNodeType::Mul: - return parseMul(node); - case TSNodeType::Sub: - return parseSub(node); - case TSNodeType::Add: - return parseAdd(node); - /*case TSNodeType::TemplateArguments: - return parseTemplateArguments(node); - case TSNodeType::TemplateArgument: - return parseTemplateArgument(node);*/ - case TSNodeType::Type: - return parseType(node); - case TSNodeType::ScopedIdentifier: - return parseScopedIdentifier(node); - case TSNodeType::Identifier: - return parseIdentifier(node); - case TSNodeType::Number: - return parseNumber(node); - case TSNodeType::SourceDef: - return parseSourceDef(node); - case TSNodeType::SinkDef: - return parseSinkDef(node); - case TSNodeType::VarDefPrefix: - assert(false && "This node cannot be parsed independently!"); - return std::nullopt; - case TSNodeType::Unknown: - default: - assert(false && "TSNodeType unhandled!"); - return std::nullopt; - } - } - - std::optional parseExpression(TSNode node) - { - auto parsed = parse(node); - if(!parsed) - return std::nullopt; - - std::optional out; - tryCastVariant(*parsed, out); - return out; - } - - template - std::optional parseT(TSNode node) - {} - - std::optional> parseNumber(TSNode root) - { - std::string_view text = nodeText(root); - float value; - auto [ptr, res] = std::from_chars(text.data(), text.data() + text.size(), value); - if(res == std::errc()) - { - errorMessage(root, std::format("Error parsing float: {}", std::make_error_code(res).message())); - return std::nullopt; - } - auto constNode = makeNode(root); - constNode->value = value; - return constNode; - } - - std::optional> parseIdentifier(TSNode root) - { - if(!expectNode(root, TSNodeType::Identifier)) - return std::nullopt; - auto ident = makeNode(root); - ident->text = nodeText(root); - return ident; - } - - std::optional> parseScopedIdentifier(TSNode root) - { - if(!expectNode(root, TSNodeType::ScopedIdentifier)) - return std::nullopt; - auto scopedId = makeNode(root); - auto scope = pushScope(scopedId); - foreachNamedNodeChild(root, [&](TSNode ident) { - auto id = parseIdentifier(ident); - if(!id) - return; - scopedId->scopes.emplace_back(*id); - }); - if(scopedId->scopes.empty()) - { - errorMessage(root, "Expected Identifier!"); - return std::nullopt; - } - return scopedId; - } - - std::optional> parseType(TSNode root) - { - if(!expectNode(root, TSNodeType::Type)) - return std::nullopt; - - auto type = makeNode(root); - auto scope = pushScope(type); - - bool queuedReference = false; - foreachNodeChild(root, [&](TSNode node) { - if(!ts_node_is_named(node)) - { - auto text = nodeText(node); - if(text == "&") - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::ConstRef); - queuedReference = true; - } - else if(text == "mut") - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::MutRef); - queuedReference = false; - } - else if(text == "const") - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::ConstRef); - queuedReference = false; - } - } - else - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::ConstRef); - auto scopedId = parseScopedIdentifier(node); - if(!scopedId) - { - errorMessage(node, "Expected Identifier"); - return; - } - type->baseType = scopedId.value(); - } - }); - - if(!type->baseType) - { - errorMessage(root, "Missing identifier"); - return std::nullopt; - } - - return type; - } - - // std::optional> parseTemplateArguments(TSNode root); - // std::optional> parseTemplateArgument(TSNode root); - std::optional> parseAdd(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseSub(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseMul(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseDiv(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseAssign(TSNode root) - { - warningMessage(root, std::format("Assignments not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseBlock(TSNode root) - { - warningMessage(root, std::format("Blocks not supproted yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseSinkDef(TSNode root) - { - if(!expectNode(root, TSNodeType::SinkDef)) - return std::nullopt; - - auto def = makeNode(root); - auto scope = pushScope(def); - - auto tsIdNode = getField(root, TSFieldName::Id); - Expect(root, tsIdNode, "Expected Identifier"); - auto idNode = parseIdentifier(*tsIdNode); - if(!idNode) - return std::nullopt; - def->id = *idNode; - - auto tsValueNode = getField(root, TSFieldName::Value); - Expect(root, tsValueNode, "Expected Expression"); - auto valueNode = parseExpression(*tsValueNode); - if(!valueNode) - return std::nullopt; - def->expression = *valueNode; - return def; - } - - std::optional> parseSinkList(TSNode root) - { - if(!expectNode(root, TSNodeType::SinkList)) - return std::nullopt; - - auto list = makeNode(root); - auto scope = pushScope(list); - - foreachNamedNodeChild(root, [&](TSNode tsSinkDefNode) { - auto sinkDefNode = parseSinkDef(tsSinkDefNode); - if(!sinkDefNode) - return; - list->values.push_back(*sinkDefNode); - }); - - return list; - } - - std::optional> parseSourceDef(TSNode root) - { - if(!expectNode(root, TSNodeType::SourceDef)) - return std::nullopt; - - auto def = makeNode(root); - auto scope = pushScope(def); - - def->isLValue = true; - - auto mutField = getField(root, TSFieldName::Mut); - def->isMut = mutField.has_value(); - - auto tsIdNode = getField(root, TSFieldName::Id); - Expect(root, tsIdNode, "Expected identifier"); - def->label = parseIdentifier(*tsIdNode); - - auto tsTypeNode = getField(root, TSFieldName::Type); - Expect(root, tsTypeNode, "Expected type"); - auto typeNode = parseType(*tsTypeNode); - if(!typeNode) - return std::nullopt; - def->type = *typeNode; - - return def; - } - - std::optional> parseSourceList(TSNode root) - { - if(!expectNode(root, TSNodeType::SourceList)) - return std::nullopt; - - auto list = makeNode(root); - auto scope = pushScope(list); - - foreachNamedNodeChild(root, [&](TSNode tsSourceDefNode) { - auto sourceDefNode = parseSourceDef(tsSourceDefNode); - if(!sourceDefNode) - return; - list->defs.push_back(*sourceDefNode); - }); - - return list; - } - - std::optional> parseCall(TSNode root) - { - auto range = nodeRange(root); - warningMessage(root, - "Function calls not implemented yet! \n\"" + - std::string(source.substr(range.start_byte, range.end_byte - range.start_byte)) + - "\" will be ignored"); - return std::nullopt; - } - - std::optional> parseAsyncOperation(TSNode root) - { - auto range = nodeRange(root); - warningMessage(root, - "Async Operations not implemented yet! \n\"" + - std::string(source.substr(range.start_byte, range.end_byte - range.start_byte)) + - "\" will be ignored"); - return std::nullopt; - } - - std::optional> parseFunction(TSNode root) - { - warningMessage(root, "Functions not implemented yet!"); - return std::nullopt; - } - - std::optional> parsePipeline(TSNode root) - { - if(!expectNode(root, TSNodeType::Pipeline)) - return std::nullopt; - auto tsIdNode = getField(root, TSFieldName::Id); - Expect(root, tsIdNode, "Identifier was not found"); - auto idNode = parseIdentifier(*tsIdNode); - auto pipe = makeNode(root); - idNode.value()->parent = pipe; - pipe->identifier = *idNode; - - auto tsSourcesNode = getField(root, TSFieldName::Sources); - Expect(root, tsSourcesNode, "Pipeline sources list not found"); - auto sourcesNode = parseSourceList(*tsSourcesNode); - if(!sourcesNode) - return std::nullopt; - pipe->sources = *sourcesNode; - - auto tsSinksNode = getField(root, TSFieldName::Sinks); - Expect(root, tsSinksNode, "Pipeline sinks not found"); - auto sinksNode = parseSinkList(*tsSinksNode); - if(!sinksNode) - return std::nullopt; - pipe->sinks = *sinksNode; - - auto tsStagesNode = getField(root, TSFieldName::Stages); - Expect(root, tsStagesNode, "Pipeline must have at least one stage"); - advanceWhileType(*tsStagesNode, - [&](TSNode tsStageNode) { - auto stageNode = parse(tsStageNode); - if(!stageNode) - return; - std::visit(overloads{[&](Node stage) { pipe->stages.push_back(stage); }, - [&](Node asyncOp) { - pipe->stages.back()->asyncExpressions.push_back(asyncOp); - }, - [&](auto& none) { - errorMessage(tsStageNode, - std::string("Grammer was correct, but context created was wrong: ") + - typeid(none).name()); - }}, - *stageNode); - }); - - return pipe; - } - - std::optional> parseModule(TSNode root) - { - if(!expectNode(root, TSNodeType::Module)) - return std::nullopt; - auto mod = makeNode(root); - auto scope = pushScope(mod); - - auto identifier = getField(root, TSFieldName::Id); - if(!identifier) - return std::nullopt; - - auto idNode = parseIdentifier(*identifier); - if(!idNode) - return std::nullopt; - idNode.value()->parent = mod; - mod->identifier = *idNode; - - auto firstDef = getField(root, TSFieldName::Defs); - if(!firstDef) - return mod; - for(auto currentDef = *firstDef; !ts_node_is_null(currentDef) && ts_node_is_named(currentDef); - currentDef = ts_node_next_named_sibling(currentDef)) - { - std::optional def = parse(currentDef); - if(!def) - continue; - std::visit( - overloads{[&](Node& pipeline) { mod->pipelines.push_back(std::move(pipeline)); }, - [&](Node& function) { mod->functions.push_back(std::move(function)); }, - [&](auto& none) { - errorMessage(currentDef, - std::string("Grammer was correct, but context created was wrong: ") + - typeid(none).name()); - }}, - *def); - } - return mod; - } - - ParserResult parseDocument() - { - tree = ts_parser_parse_string(parser->parser(), nullptr, source.data(), source.size()); - - auto doc = std::make_shared(); - auto scope = pushScope(doc); - - doc->source = path; - - TSNode root = ts_tree_root_node(tree); - - foreachNodeChild(root, [&](TSNode node) { - auto newMod = parseModule(node); - if(newMod) - doc->modules.insert({newMod.value()->identifier->text, newMod.value()}); - }); - - return {doc, std::move(messages)}; - } - }; - - BraneScriptParser::BraneScriptParser() - { - _value = ts_parser_new(); - ts_parser_set_language(_value, tree_sitter_branescript()); - } - - BraneScriptParser::BraneScriptParser(BraneScriptParser&& other) noexcept - { - _value = other._value; - other._value = nullptr; - } - - BraneScriptParser::~BraneScriptParser() - { - if(_value) - ts_parser_delete(_value); - } - - TSParser* BraneScriptParser::parser() const { return _value; } - - ParsedDocument::ParsedDocument(std::filesystem::path path, - std::string source, - std::shared_ptr parser) - : _path(std::move(path)), _source(std::move(source)), _parser(std::move(parser)) - {} - - std::string_view ParsedDocument::source() const { return _source; } - - void ParsedDocument::update(TSRange updateRange, std::string newText) - { - // TODO implement - assert(false && "Update not implemented!"); - } - - ParserResult ParsedDocument::getDocumentContext() - { - if(_cachedResult) - return _cachedResult.value(); - ParserAPI ctx{_path, _source, _parser}; - _cachedResult = std::make_optional(ctx.parseDocument()); - return _cachedResult.value(); - } - - -} // namespace BraneScript diff --git a/src/parser/documentParser.cpz~ b/src/parser/documentParser.cpz~ deleted file mode 100644 index 320e16a..0000000 --- a/src/parser/documentParser.cpz~ +++ /dev/null @@ -1,888 +0,0 @@ -// -// Created by WireWhiz on 10/28/2024. -// - -#include "documentParser.h" - -#include -#include -#include -#include -#include -#include -#include -#include "parser/documentContext.h" -#include "tree_sitter_branescript.h" -#include - - -#define Expect(node, _optional, _errorMessage) \ - if(!_optional) \ - { \ - errorMessage(node, _errorMessage); \ - return std::nullopt; \ - } - -namespace BraneScript -{ - template - struct overloads : Ts... - { - using Ts::operator()...; - }; - - template - bool tryCastVariant(std::variant value, std::optional>& result) - { - return std::visit(overloads{[&](auto&& inner) -> bool { - if constexpr(((std::is_same_v) || ...)) - { - result = inner; - return false; - } - result = std::nullopt; - return false; - }}, - std::move(value)); - } - - enum class TSNodeType : uint16_t - { - Unknown = 0, - Number, - Identifier, - ScopedIdentifier, - Type, - TemplateArgument, - TemplateArguments, - Add, - Sub, - Mul, - Div, - Assign, - Block, - VarDefPrefix, - SinkDef, - SinkList, - SourceDef, - SourceList, - Call, - PipelineStage, - AsyncOperation, - Function, - Pipeline, - Module, - SourceFile - }; - - void foreachNodeChild(TSNode node, const std::function& f) - { - uint32_t childCount = ts_node_child_count(node); - for(uint32_t i = 0; i < childCount; ++i) - f(ts_node_child(node, i)); - } - - void foreachNamedNodeChild(TSNode node, const std::function& f) - { - uint32_t childCount = ts_node_named_child_count(node); - for(uint32_t i = 0; i < childCount; ++i) - f(ts_node_named_child(node, i)); - } - - TSRange nodeRange(TSNode node) - { - return {ts_node_start_point(node), ts_node_end_point(node), ts_node_start_byte(node), ts_node_end_byte(node)}; - } - - std::string_view nodeName(TSNode node) - { - return ts_language_symbol_name(tree_sitter_branescript(), ts_node_symbol(node)); - } - - class TSSymbolLookupTable - { - private: - std::vector symbolToNodeType; - std::vector nodeTypeToSymbol; - - void add_entry(const TSLanguage* lang, std::string_view ident, TSNodeType nodeType) - { - auto symbol = ts_language_symbol_for_name(lang, ident.data(), ident.size(), true); - if(symbol >= symbolToNodeType.size()) - symbolToNodeType.resize(symbol + 1, (TSNodeType)UINT16_MAX); - if((uint16_t)nodeType >= nodeTypeToSymbol.size()) - nodeTypeToSymbol.resize((uint16_t)nodeType + 1, (TSSymbol)UINT16_MAX); - symbolToNodeType[symbol] = nodeType; - nodeTypeToSymbol[(uint16_t)nodeType] = symbol; - } - - public: - TSSymbolLookupTable(const TSLanguage* lang) - { - add_entry(lang, "number", TSNodeType::Number); - add_entry(lang, "module", TSNodeType::Module); - add_entry(lang, "identifier", TSNodeType::Identifier); - add_entry(lang, "scopedIdentifier", TSNodeType::ScopedIdentifier); - add_entry(lang, "type", TSNodeType::Type); - add_entry(lang, "templateArgument", TSNodeType::TemplateArgument); - add_entry(lang, "templateArguments", TSNodeType::TemplateArguments); - add_entry(lang, "add", TSNodeType::Add); - add_entry(lang, "sub", TSNodeType::Sub); - add_entry(lang, "mul", TSNodeType::Mul); - add_entry(lang, "div", TSNodeType::Div); - add_entry(lang, "assign", TSNodeType::Assign); - add_entry(lang, "block", TSNodeType::Block); - add_entry(lang, "varDefPrefix", TSNodeType::VarDefPrefix); - add_entry(lang, "sinkDef", TSNodeType::SinkDef); - add_entry(lang, "sinkList", TSNodeType::SinkList); - add_entry(lang, "sourceDef", TSNodeType::SourceDef); - add_entry(lang, "sourceList", TSNodeType::SourceList); - add_entry(lang, "call", TSNodeType::Call); - add_entry(lang, "pipelineStage", TSNodeType::PipelineStage); - add_entry(lang, "asyncOperation", TSNodeType::AsyncOperation); - add_entry(lang, "function", TSNodeType::Function); - add_entry(lang, "pipeline", TSNodeType::Pipeline); - add_entry(lang, "sourceFile", TSNodeType::SourceFile); - } - - std::optional tryToNodeType(TSSymbol symbol) const - { - if(symbol > symbolToNodeType.size()) - return std::nullopt; - auto nodeType = symbolToNodeType[symbol]; - return (uint16_t)nodeType == UINT16_MAX ? std::nullopt : std::make_optional(nodeType); - } - - std::optional tryToSymbol(TSNodeType nodeType) const - { - if((uint16_t)nodeType > nodeTypeToSymbol.size()) - return std::nullopt; - auto symbol = nodeTypeToSymbol[(uint16_t)nodeType]; - return symbol == UINT16_MAX ? std::nullopt : std::make_optional(symbol); - } - }; - - enum class TSFieldName : uint16_t - { - Id = 0, - Child, - Type, - Value, - Mut, - Defs, - Sources, - Sinks, - Stages, - TemplateArgs, - }; - - class TSFieldLookupTable - { - private: - std::vector _fieldIds; - - void add_entry(const TSLanguage* lang, std::string_view textName, TSFieldName fieldName) - { - auto fID = ts_language_field_id_for_name(lang, textName.data(), textName.size()); - - if((uint16_t)fieldName >= _fieldIds.size()) - _fieldIds.resize((uint16_t)fieldName + 1, (TSFieldId)0); - _fieldIds[(uint16_t)fieldName] = fID; - } - - public: - TSFieldLookupTable(const TSLanguage* lang) - { - add_entry(lang, "id", TSFieldName::Id); - add_entry(lang, "child", TSFieldName::Child); - add_entry(lang, "type", TSFieldName::Type); - add_entry(lang, "value", TSFieldName::Value); - add_entry(lang, "mut", TSFieldName::Mut); - add_entry(lang, "defs", TSFieldName::Defs); - add_entry(lang, "sinks", TSFieldName::Sinks); - add_entry(lang, "sources", TSFieldName::Sources); - add_entry(lang, "stages", TSFieldName::Stages); - add_entry(lang, "templateArgs", TSFieldName::TemplateArgs); - } - - TSFieldId get(TSFieldName name) const - { - assert((uint16_t)name < _fieldIds.size() && "Make sure all fields are defined in the constructor"); - return _fieldIds[(uint16_t)name]; - } - }; - - const TSSymbolLookupTable symbolLookupTable = TSSymbolLookupTable(tree_sitter_branescript()); - const TSFieldLookupTable fieldLookupTable = TSFieldLookupTable(tree_sitter_branescript()); - - std::string_view typeToName(TSNodeType type) - { - auto symbol = symbolLookupTable.tryToSymbol(type); - if(!symbol) - return "Unknown"; - return ts_language_symbol_name(tree_sitter_branescript(), symbol.value()); - } - - TSNodeType nodeType(TSNode node) - { - auto nodeType = symbolLookupTable.tryToNodeType(ts_node_symbol(node)); - if(!nodeType) - return TSNodeType::Unknown; - return *nodeType; - } - - template - bool nodeIsType(TSNode node) - { - auto nt = nodeType(node); - return ((nt == Types) || ...); - } - - template - void advanceWhileType(TSNode node, const std::function& f) - { - bool nodeIsCorrectType = true; - if(!ts_node_is_named(node)) - node = ts_node_next_named_sibling(node); - while(!ts_node_is_null(node) && nodeIsType(node)) - { - f(node); - node = ts_node_next_named_sibling(node); - } - } - - struct ScopedScope - { - std::list>& scopes; - Node node; - - ScopedScope(std::list>& scopes, Node node) : scopes(scopes), node(node) {} - - ScopedScope(const ScopedScope&) = delete; - - ScopedScope(ScopedScope&& o) noexcept : scopes(o.scopes) - { - node = o.node; - o.node = nullptr; - } - - ~ScopedScope() - { - if(!node) - return; - assert(scopes.back() == node); - scopes.pop_back(); - } - }; - - struct ParserAPI - { - std::filesystem::path path; - std::string_view source; - std::shared_ptr parser; - std::vector messages; - TSTree* tree; - - std::list> scopes; - - std::optional> currentScope() - { - if(scopes.empty()) - return std::nullopt; - return scopes.back(); - } - - ScopedScope pushScope(Node node) - { - scopes.emplace_back(node); - return ScopedScope(scopes, node); - } - - void verboseMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Verbose, nodeRange(ctx), std::move(message)); - } - - void logMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Log, nodeRange(ctx), std::move(message)); - } - - void warningMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Warning, nodeRange(ctx), std::move(message)); - } - - void errorMessage(TSNode ctx, std::string message) - { - messages.emplace_back(MessageType::Error, nodeRange(ctx), std::move(message)); - } - - std::optional getField(TSNode node, TSFieldName field) - { - auto result = ts_node_child_by_field_id(node, fieldLookupTable.get(field)); - if(ts_node_is_null(result)) - return std::nullopt; - return result; - } - - bool expectNode(TSNode node, TSNodeType type) - { - auto nodeType = symbolLookupTable.tryToNodeType(ts_node_symbol(node)); - if(nodeType && type == nodeType) - return true; - - std::string message = - std::format("Was expecting \"{}\" but found \"{}\" \n", typeToName(type), nodeText(node)); - errorMessage(node, message); - return false; - } - - bool expectField(TSNode node, const std::vector& types) - { - auto nodeType = symbolLookupTable.tryToNodeType(ts_node_symbol(node)); - if(nodeType) - { - for(auto t : types) - { - if(t == nodeType) - return true; - } - } - - std::string message = std::vformat("Found \"{}\", but was expecting one of the following:\n", - std::make_format_args(nodeText(node))); - for(auto t : types) - message += std::vformat("{}\n", std::make_format_args(typeToName(t))); - errorMessage(node, message); - return false; - } - - std::string_view nodeText(TSNode node) - { - auto start = ts_node_start_byte(node); - auto end = ts_node_end_byte(node); - return {source.data() + start, end - start}; - } - - template - Node makeNode(TSNode context) - { - static_assert(std::is_base_of().value); - - auto new_node = std::make_shared(); - new_node->range = nodeRange(context); - new_node->parent = currentScope(); - - return new_node; - } - - std::optional parse(TSNode node) - { - switch(nodeType(node)) - { - case TSNodeType::SourceFile: - assert(false && "Cannot call parse on root node!"); - return std::nullopt; - case TSNodeType::Module: - return parseModule(node); - case TSNodeType::Pipeline: - return parsePipeline(node); - case TSNodeType::Function: - return parseFunction(node); - case TSNodeType::PipelineStage: - return parsePipelineStage(node); - case TSNodeType::AsyncOperation: - return parseAsyncOperation(node); - case TSNodeType::Call: - return parseCall(node); - case TSNodeType::SourceList: - return parseSourceList(node); - case TSNodeType::SinkList: - return parseSinkList(node); - case TSNodeType::Block: - return parseBlock(node); - case TSNodeType::Assign: - return parseAssign(node); - case TSNodeType::Div: - return parseDiv(node); - case TSNodeType::Mul: - return parseMul(node); - case TSNodeType::Sub: - return parseSub(node); - case TSNodeType::Add: - return parseAdd(node); - /*case TSNodeType::TemplateArguments: - return parseTemplateArguments(node); - case TSNodeType::TemplateArgument: - return parseTemplateArgument(node);*/ - case TSNodeType::Type: - return parseType(node); - case TSNodeType::ScopedIdentifier: - return parseScopedIdentifier(node); - case TSNodeType::Identifier: - return parseIdentifier(node); - case TSNodeType::Number: - return parseNumber(node); - case TSNodeType::SourceDef: - return parseSourceDef(node); - case TSNodeType::SinkDef: - return parseSinkDef(node); - case TSNodeType::VarDefPrefix: - assert(false && "This node cannot be parsed independently!"); - return std::nullopt; - case TSNodeType::Unknown: - default: - std::cout << "Unknown TSNode type for: " << nodeText(node) << std::endl; - assert(false && "TSNodeType unhandled!"); - return std::nullopt; - } - } - - std::optional parseExpression(TSNode node) - { - auto parsed = parse(node); - if(!parsed) - return std::nullopt; - - std::optional out; - tryCastVariant(*parsed, out); - return out; - } - - template - std::optional parseT(TSNode node) - {} - - std::optional> parseNumber(TSNode root) - { - std::string_view text = nodeText(root); - float value; - auto [ptr, res] = std::from_chars(text.data(), text.data() + text.size(), value); - if(res == std::errc()) - { - errorMessage(root, std::format("Error parsing float: {}", std::make_error_code(res).message())); - return std::nullopt; - } - auto constNode = makeNode(root); - constNode->value = value; - return constNode; - } - - std::optional> parseIdentifier(TSNode root) - { - if(!expectNode(root, TSNodeType::Identifier)) - return std::nullopt; - auto ident = makeNode(root); - ident->text = nodeText(root); - return ident; - } - - std::optional> parseScopedIdentifier(TSNode root) - { - if(!expectNode(root, TSNodeType::ScopedIdentifier)) - return std::nullopt; - auto scopedId = makeNode(root); - auto scope = pushScope(scopedId); - foreachNamedNodeChild(root, [&](TSNode ident) { - auto id = parseIdentifier(ident); - if(!id) - return; - scopedId->scopes.emplace_back(*id); - }); - if(scopedId->scopes.empty()) - { - errorMessage(root, "Expected Identifier!"); - return std::nullopt; - } - return scopedId; - } - - std::optional> parseType(TSNode root) - { - if(!expectNode(root, TSNodeType::Type)) - return std::nullopt; - - auto type = makeNode(root); - auto scope = pushScope(type); - - bool queuedReference = false; - foreachNodeChild(root, [&](TSNode node) { - if(!ts_node_is_named(node)) - { - auto text = nodeText(node); - if(text == "&") - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::ConstRef); - queuedReference = true; - } - else if(text == "mut") - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::MutRef); - queuedReference = false; - } - else if(text == "const") - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::ConstRef); - queuedReference = false; - } - } - else - { - if(queuedReference) - type->modifiers.push_back(TypeModifiers::ConstRef); - auto scopedId = parseScopedIdentifier(node); - if(!scopedId) - { - errorMessage(node, "Expected Identifier"); - return; - } - type->baseType = scopedId.value(); - } - }); - - if(!type->baseType) - { - errorMessage(root, "Missing identifier"); - return std::nullopt; - } - - return type; - } - - // std::optional> parseTemplateArguments(TSNode root); - // std::optional> parseTemplateArgument(TSNode root); - std::optional> parseAdd(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseSub(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseMul(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseDiv(TSNode root) - { - warningMessage(root, std::format("This operator not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseAssign(TSNode root) - { - warningMessage(root, std::format("Assignments not supported yet, ignoring {}", nodeText(root))); - return std::nullopt; - } - - std::optional> parseBlock(TSNode root) - { - if(!expectNode(root, TSNodeType::AsyncOperation)) - return std::nullopt; - auto block = makeNode(root); - auto scope = pushScope(block); - - foreachNamedNodeChild(root, [&](TSNode node) { - auto expr = parseExpression(node); - if(!expr) - return; - block->expressions.push_back(*expr); - }); - - return block; - } - - std::optional> parseSinkDef(TSNode root) - { - if(!expectNode(root, TSNodeType::SinkDef)) - return std::nullopt; - - auto def = makeNode(root); - auto scope = pushScope(def); - - auto tsIdNode = getField(root, TSFieldName::Id); - Expect(root, tsIdNode, "Expected Identifier"); - auto idNode = parseIdentifier(*tsIdNode); - if(!idNode) - return std::nullopt; - def->id = *idNode; - - auto tsValueNode = getField(root, TSFieldName::Value); - Expect(root, tsValueNode, "Expected Expression"); - auto valueNode = parseExpression(*tsValueNode); - if(!valueNode) - return std::nullopt; - def->expression = *valueNode; - return def; - } - - std::optional> parseSinkList(TSNode root) - { - if(!expectNode(root, TSNodeType::SinkList)) - return std::nullopt; - - auto list = makeNode(root); - auto scope = pushScope(list); - - foreachNamedNodeChild(root, [&](TSNode tsSinkDefNode) { - auto sinkDefNode = parseSinkDef(tsSinkDefNode); - if(!sinkDefNode) - return; - list->values.push_back(*sinkDefNode); - }); - - return list; - } - - std::optional> parseSourceDef(TSNode root) - { - if(!expectNode(root, TSNodeType::SourceDef)) - return std::nullopt; - - auto def = makeNode(root); - auto scope = pushScope(def); - - def->isLValue = true; - - auto mutField = getField(root, TSFieldName::Mut); - def->isMut = mutField.has_value(); - - auto tsIdNode = getField(root, TSFieldName::Id); - Expect(root, tsIdNode, "Expected identifier"); - def->label = parseIdentifier(*tsIdNode); - - auto tsTypeNode = getField(root, TSFieldName::Type); - Expect(root, tsTypeNode, "Expected type"); - auto typeNode = parseType(*tsTypeNode); - if(!typeNode) - return std::nullopt; - def->type = *typeNode; - - return def; - } - - std::optional> parseSourceList(TSNode root) - { - if(!expectNode(root, TSNodeType::SourceList)) - return std::nullopt; - - auto list = makeNode(root); - auto scope = pushScope(list); - - foreachNamedNodeChild(root, [&](TSNode tsSourceDefNode) { - auto sourceDefNode = parseSourceDef(tsSourceDefNode); - if(!sourceDefNode) - return; - list->defs.push_back(*sourceDefNode); - }); - - return list; - } - - std::optional> parseCall(TSNode root) - { - auto range = nodeRange(root); - warningMessage(root, - "Function calls not implemented yet! \n\"" + - std::string(source.substr(range.start_byte, range.end_byte - range.start_byte)) + - "\" will be ignored"); - return std::nullopt; - } - - std::optional> parsePipelineStage(TSNode root) - { - if(!expectNode(root, TSNodeType::PipelineStage)) - return std::nullopt; - auto stage = makeNode(root); - auto scope = pushScope(stage); - - foreachNamedNodeChild(root, [&](TSNode node) { - auto expr = parseExpression(node); - if(!expr) - return; - stage->expressions.push_back(*expr); - }); - - return stage; - } - - std::optional> parseAsyncOperation(TSNode root) - { - if(!expectNode(root, TSNodeType::AsyncOperation)) - return std::nullopt; - auto range = nodeRange(root); - warningMessage(root, - "Async Operations not implemented yet! \n\"" + - std::string(source.substr(range.start_byte, range.end_byte - range.start_byte)) + - "\" will be ignored"); - return std::nullopt; - } - - std::optional> parseFunction(TSNode root) - { - warningMessage(root, "Functions not implemented yet!"); - return std::nullopt; - } - - std::optional> parsePipeline(TSNode root) - { - if(!expectNode(root, TSNodeType::Pipeline)) - return std::nullopt; - auto tsIdNode = getField(root, TSFieldName::Id); - Expect(root, tsIdNode, "Identifier was not found"); - auto idNode = parseIdentifier(*tsIdNode); - auto pipe = makeNode(root); - idNode.value()->parent = pipe; - pipe->identifier = *idNode; - - auto tsSourcesNode = getField(root, TSFieldName::Sources); - Expect(root, tsSourcesNode, "Pipeline sources list not found"); - auto sourcesNode = parseSourceList(*tsSourcesNode); - if(!sourcesNode) - return std::nullopt; - pipe->sources = *sourcesNode; - - auto tsSinksNode = getField(root, TSFieldName::Sinks); - Expect(root, tsSinksNode, "Pipeline sinks not found"); - auto sinksNode = parseSinkList(*tsSinksNode); - if(!sinksNode) - return std::nullopt; - pipe->sinks = *sinksNode; - - auto tsStagesNode = getField(root, TSFieldName::Stages); - Expect(root, tsStagesNode, "Pipeline must have at least one stage"); - advanceWhileType(*tsStagesNode, - [&](TSNode tsStageNode) { - auto stageNode = parse(tsStageNode); - if(!stageNode) - return; - std::visit(overloads{[&](Node stage) { pipe->stages.push_back(stage); }, - [&](Node asyncOp) { - pipe->stages.back()->asyncExpressions.push_back(asyncOp); - }, - [&](auto& none) { - errorMessage(tsStageNode, - std::string("Grammer was correct, but context created was wrong: ") + - typeid(none).name()); - }}, - *stageNode); - }); - - return pipe; - } - - std::optional> parseModule(TSNode root) - { - if(!expectNode(root, TSNodeType::Module)) - return std::nullopt; - auto mod = makeNode(root); - auto scope = pushScope(mod); - - auto identifier = getField(root, TSFieldName::Id); - if(!identifier) - return std::nullopt; - - auto idNode = parseIdentifier(*identifier); - if(!idNode) - return std::nullopt; - idNode.value()->parent = mod; - mod->identifier = *idNode; - - auto firstDef = getField(root, TSFieldName::Defs); - if(!firstDef) - return mod; - for(auto currentDef = *firstDef; !ts_node_is_null(currentDef) && ts_node_is_named(currentDef); - currentDef = ts_node_next_named_sibling(currentDef)) - { - std::optional def = parse(currentDef); - if(!def) - continue; - std::visit( - overloads{[&](Node& pipeline) { mod->pipelines.push_back(std::move(pipeline)); }, - [&](Node& function) { mod->functions.push_back(std::move(function)); }, - [&](auto& none) { - errorMessage(currentDef, - std::string("Grammer was correct, but context created was wrong: ") + - typeid(none).name()); - }}, - *def); - } - return mod; - } - - ParserResult parseDocument() - { - tree = ts_parser_parse_string(parser->parser(), nullptr, source.data(), source.size()); - - auto doc = std::make_shared(); - auto scope = pushScope(doc); - - doc->source = path; - - TSNode root = ts_tree_root_node(tree); - - foreachNodeChild(root, [&](TSNode node) { - auto newMod = parseModule(node); - if(newMod) - doc->modules.insert({newMod.value()->identifier->text, newMod.value()}); - }); - - return {doc, std::move(messages)}; - } - }; - - BraneScriptParser::BraneScriptParser() - { - _value = ts_parser_new(); - ts_parser_set_language(_value, tree_sitter_branescript()); - } - - BraneScriptParser::BraneScriptParser(BraneScriptParser&& other) noexcept - { - _value = other._value; - other._value = nullptr; - } - - BraneScriptParser::~BraneScriptParser() - { - if(_value) - ts_parser_delete(_value); - } - - TSParser* BraneScriptParser::parser() const { return _value; } - - ParsedDocument::ParsedDocument(std::filesystem::path path, - std::string source, - std::shared_ptr parser) - : _path(std::move(path)), _source(std::move(source)), _parser(std::move(parser)) - {} - - std::string_view ParsedDocument::source() const { return _source; } - - void ParsedDocument::update(TSRange updateRange, std::string newText) - { - // TODO implement - assert(false && "Update not implemented!"); - } - - ParserResult ParsedDocument::getDocumentContext() - { - if(_cachedResult) - return _cachedResult.value(); - ParserAPI ctx{_path, _source, _parser}; - _cachedResult = std::make_optional(ctx.parseDocument()); - return _cachedResult.value(); - } - - -} // namespace BraneScript diff --git a/test.bscript.txt b/test.bscript.txt deleted file mode 100644 index ae34abc..0000000 --- a/test.bscript.txt +++ /dev/null @@ -1,27 +0,0 @@ -mod test { - pipe Foo - (a: i32, b: i32){ - [ - let r: i32 = a + b; - ] - hold r - call (r)Bar(o: f32) - [ - o = o + 2; - ] - }(value: o) - - - pipe Bar - (a: i32){ - [ - (in: a)f32(o: f32); - ] - }(value: o) -} - -mod test2 -{} - -mod hello_world{} - diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c32e3f9..358d2a4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,7 @@ target_link_libraries(bs_tests PRIVATE GTest::gtest_main) #target_link_libraries(bs_tests PUBLIC GTest::gtest_main BraneScriptCompiler) include(GoogleTest) -gtest_discover_tests(bs_tests WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/executables) +gtest_discover_tests(bs_tests) -file(GLOB TEST_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/*.bs) -file(COPY ${TEST_SCRIPTS} DESTINATION ${CMAKE_BINARY_DIR}/executables/testScripts) +#file(GLOB TEST_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/*.bs) +#file(COPY ${TEST_SCRIPTS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tree_sitter_bs b/tree_sitter_bs deleted file mode 100644 index e69de29..0000000 diff --git a/vcpkg.json b/vcpkg.json index b6d8d00..209aa74 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,15 +1,10 @@ { - "dependencies": [ - { - "name": "llvm", - "default-features": false, - "features": ["enable-assertions", "default-targets"] - }, - { - "name": "tree-sitter" - }, - { - "name": "gtest" - } - ] -} \ No newline at end of file + "dependencies": [ + { + "name": "tree-sitter" + }, + { + "name": "gtest" + } + ] +}