diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ce4fa034..f3821d1dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,36 +7,72 @@ set(CMAKE_CXX_STANDARD 17) add_subdirectory(deps/zen EXCLUDE_FROM_ALL) -add_executable( - bolt +set(ICU_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build/icu/install") +set(ICU_INCLUDE_DIRS "${ICU_DIR}/include") +set(ICU_LIBRARY_DIRS "${ICU_DIR}/lib") + +add_library( + BoltCore + src/Text.cc src/CST.cc src/Diagnostics.cc src/Scanner.cc src/Parser.cc src/Checker.cc - src/main.cc +) +target_link_directories( + BoltCore + PUBLIC + ${ICU_LIBRARY_DIRS} ) target_compile_options( - bolt + BoltCore PUBLIC -fstandalone-debug ) target_include_directories( - bolt + BoltCore PUBLIC include + ${ICU_LIBRARY_DIRS} +) +target_link_libraries( + BoltCore + PUBLIC + zen + icuuc +) + +add_executable( + bolt + src/main.cc ) target_link_libraries( bolt PUBLIC - zen + BoltCore ) -add_custom_command( - OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/include/bolt/CST.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/CST.cc" - COMMAND scripts/gennodes.py --name=CST ./bolt-cst-spec.txt -Iinclude/ --include-root=bolt --source-root=src/ --namespace=bolt - DEPENDS scripts/gennodes.py - MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/bolt-cst-spec.txt" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" -) +if (BOLT_ENABLE_TESTS) + add_subdirectory(deps/googletest EXCLUDE_FROM_ALL) + add_executable( + alltests + src/TestText.cc + ) + target_link_libraries( + alltests + PUBLIC + BoltCore + gtest + gtest_main + ) +endif() + +#add_custom_command( +# OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/include/bolt/CST.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/CST.cc" +# COMMAND scripts/gennodes.py --name=CST ./bolt-cst-spec.txt -Iinclude/ --include-root=bolt --source-root=src/ --namespace=bolt +# DEPENDS scripts/gennodes.py +# MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/bolt-cst-spec.txt" +# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +#) diff --git a/include/bolt/Text.hpp b/include/bolt/Text.hpp index fb9fa61d2..7e27759ef 100644 --- a/include/bolt/Text.hpp +++ b/include/bolt/Text.hpp @@ -1,11 +1,13 @@ -#ifndef BOLT_TEXT_HPP -#define BOLT_TEXT_HPP -#include "ByteString.hpp" +#pragma once + #include +#include #include +#include "bolt/ByteString.hpp" + namespace bolt { class TextLoc { @@ -34,10 +36,25 @@ namespace bolt { }; class TextFile { + + ByteString Path; + ByteString Text; + + std::vector LineOffsets; + public: - ByteString getText(); + + TextFile(ByteString Path, ByteString Text); + + size_t getLine(size_t Offset); + size_t getColumn(size_t Offset); + size_t getStartOffset(size_t Line); + + ByteString getPath() const; + + ByteString getText() const; + }; } -#endif // of #ifndef BOLT_TEXT_HPP diff --git a/src/TestText.cc b/src/TestText.cc new file mode 100644 index 000000000..7cf5f2465 --- /dev/null +++ b/src/TestText.cc @@ -0,0 +1,47 @@ + +#include "gtest/gtest.h" + +#include "bolt/Text.hpp" + +using namespace bolt; + +TEST(TextFileTest, ReportsCorrectLine) { + TextFile T1 { "foo.txt", "bar\nbaz\nbax\n" }; + ASSERT_EQ(T1.getLine(0), 1); + ASSERT_EQ(T1.getLine(1), 1); + ASSERT_EQ(T1.getLine(2), 1); + ASSERT_EQ(T1.getLine(3), 1); + ASSERT_EQ(T1.getLine(4), 2); + ASSERT_EQ(T1.getLine(5), 2); + ASSERT_EQ(T1.getLine(6), 2); + ASSERT_EQ(T1.getLine(7), 2); + ASSERT_EQ(T1.getLine(8), 3); + ASSERT_EQ(T1.getLine(9), 3); + ASSERT_EQ(T1.getLine(10), 3); + ASSERT_EQ(T1.getLine(11), 3); +} + +TEST(TextFileTest, ReportsCorrectStartOffset) { + TextFile T1 { "foo.txt", "bar\nbaz\nbax\n" }; + ASSERT_EQ(T1.getStartOffset(1), 0); + ASSERT_EQ(T1.getStartOffset(2), 4); + ASSERT_EQ(T1.getStartOffset(3), 8); + ASSERT_EQ(T1.getStartOffset(4), 12); + ASSERT_EQ(T1.getStartOffset(5), 12); +} + +TEST(TextFileTest, ReportsCorrectColumn) { + TextFile T1 { "foo.txt", "bar\nbaz\nbax\n" }; + ASSERT_EQ(T1.getColumn(0), 1); + ASSERT_EQ(T1.getColumn(1), 2); + ASSERT_EQ(T1.getColumn(2), 3); + ASSERT_EQ(T1.getColumn(3), 4); + ASSERT_EQ(T1.getColumn(4), 1); + ASSERT_EQ(T1.getColumn(5), 2); + ASSERT_EQ(T1.getColumn(6), 3); + ASSERT_EQ(T1.getColumn(7), 4); + ASSERT_EQ(T1.getColumn(8), 1); + ASSERT_EQ(T1.getColumn(9), 2); + ASSERT_EQ(T1.getColumn(10), 3); + ASSERT_EQ(T1.getColumn(11), 4); +} diff --git a/src/Text.cc b/src/Text.cc new file mode 100644 index 000000000..17b2f05ba --- /dev/null +++ b/src/Text.cc @@ -0,0 +1,49 @@ + +#include "zen/config.hpp" + +#include "bolt/Text.hpp" +#include "bolt/ByteString.hpp" + +namespace bolt { + + TextFile::TextFile(ByteString Path, ByteString Text): + Path(Path), Text(Text) { + LineOffsets.push_back(0); + for (size_t I = 0; I < Text.size(); I++) { + auto Chr = Text[I]; + if (Chr == '\n') { + LineOffsets.push_back(I+1); + } + } + LineOffsets.push_back(Text.size()); + } + + size_t TextFile::getStartOffset(size_t Line) { + return LineOffsets[Line-1]; + } + + size_t TextFile::getLine(size_t Offset) { + ZEN_ASSERT(Offset < Text.size()); + for (size_t I = 0; I < LineOffsets.size(); ++I) { + if (LineOffsets[I] > Offset) { + return I; + } + } + ZEN_UNREACHABLE + } + + size_t TextFile::getColumn(size_t Offset) { + auto Line = getLine(Offset); + auto StartOffset = getStartOffset(Line); + return Offset - StartOffset + 1 ; + } + + ByteString TextFile::getPath() const { + return Path; + } + + ByteString TextFile::getText() const { + return Text; + } + +}