From 839cf3eccfeb0e1b9bbba8a109a4f6e3caa1224a Mon Sep 17 00:00:00 2001 From: Zengtudor Date: Sat, 12 Jul 2025 00:35:49 +0800 Subject: [PATCH] update --- CMakeLists.txt | 5 +- include/Lexer.hpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++ include/Tools.hpp | 55 ++++++++++++++++++++++ src/main.cpp | 1 + tests/test.cpp | 14 ++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 include/Tools.hpp create mode 100644 tests/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9615e46..4221130 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,4 +9,7 @@ set(CMAKE_CXX_STANDARD 26 file(GLOB_RECURSE SRC_CPP ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp) add_executable(${PROJECT_NAME} ${SRC_CPP}) -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include) \ No newline at end of file + +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include) +add_executable(${PROJECT_NAME}_test ${CMAKE_CURRENT_LIST_DIR}/tests/test.cpp) +target_include_directories(${PROJECT_NAME}_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include) \ No newline at end of file diff --git a/include/Lexer.hpp b/include/Lexer.hpp index 3f59c93..acc992e 100644 --- a/include/Lexer.hpp +++ b/include/Lexer.hpp @@ -1,2 +1,118 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include "Lexer.hpp" +#include "Tools.hpp" + +namespace ztl{ + namespace lexer{ + struct Token{std::string data;}; + struct Keywords:Token{}; + struct Identifiers:Token{}; + struct Literals:Token{}; + struct Operators:Token{}; + struct Separators:Token{}; + struct Comments:Token{}; + struct EOF_Token:Token{}; + + struct CharProvider{ + std::string buffer; + std::vector white_spaces{'\n','\t',' '}; + size_t idx=0; + Result peek(){ + if (idx(buffer[idx]); + }else{ + return Result(Err("got EOF")); + } + } + Result consume(){ + return ztl::match(peek(), [this](char c){ + idx++; + return Result(c); + },[](const Err &e){ + return Result(e); + }); + } + Result match(char c){ + return ztl::match(peek(),[this](char c){ + if(c==buffer[idx]){ + idx++; + return Result(true); + }else{ + return Result(false); + } + },[this](const Err &e){ + return Result(e); + }); + } + Result consume_until(std::function func){ + size_t start_idx = idx; + while(idx(Err("don't hava any string")); + } + return Result(buffer.substr(start_idx,idx-start_idx+1)); + } + void skip_whitespace(){ + while(1) { + if( + !ztl::match(peek(),[this](char c){ + bool is_ws = false; + for(char ws:white_spaces){ + if(c==ws){ + consume(); + is_ws=true; + } + } + return is_ws; + },[](const Err &e){ + return false; + }) + ){ + return; + } + } + } + }; + + inline bool is_digit(char c){ + return '0'<=c&&c<='9'; + } + + inline bool is_alpha(char c){ + return 'A'<=c&&c<='z'; + } + + inline bool is_alphanumeric(char c){ + return is_digit(c) || is_alpha(c); + } + + inline std::vector lexer(const std::string&s){ + CharProvider cp(s); + std::vector tokens; + while(1){ + bool should_break=false; + cp.skip_whitespace(); + match(cp.peek(),[&cp,&tokens](char c){ + if (is_alpha(c)){ + tokens.push_back(Keywords{cp.consume_until(is_alphanumeric).unwrap()}); + } + },[&should_break](const Err &e){ + should_break=true; + }); + if(should_break)break; + } + return tokens; + } + } +} \ No newline at end of file diff --git a/include/Tools.hpp b/include/Tools.hpp new file mode 100644 index 0000000..73404c0 --- /dev/null +++ b/include/Tools.hpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + + +namespace ztl{ + template + struct overloaded:Ts...{using Ts::operator()...;}; + + template + overloaded(Ts...)->overloaded; + + template + auto match(std::variant& v, Fs&&... func) { + return std::visit(ztl::overloaded{std::forward(func)...}, v); + } + template + auto match(const std::variant& v, Fs&&... func) { + return std::visit(ztl::overloaded{std::forward(func)...}, v); + } + template + auto match(std::variant&& v, Fs&&... func) { + return std::visit(ztl::overloaded{std::forward(func)...}, std::move(v)); + } + struct Err:std::string{}; + + // template + // struct Ok{ + // T data; + // }; + + template + struct Result:std::variant{ + T unwrap(){ + return match(*this,[](const T&t){ + return t; + },[](const Err &e){ + throw std::runtime_error(e); + T t; + return t; + }); + } + }; + + template + void logger(Ts&&...v){ + #ifndef NDEBUG + std::cout<<"log["; + (std::cout<<...< int main(){ diff --git a/tests/test.cpp b/tests/test.cpp new file mode 100644 index 0000000..8cc7099 --- /dev/null +++ b/tests/test.cpp @@ -0,0 +1,14 @@ +#include "Lexer.hpp" +#include +#include + +#define NV(v) {std::cout<<#v<<" : '"<<(v)<<"'\n";} + +int main(){ + std::string hello_world = R"( + print("hello ztl!"); + )"; + std::cout<<"This is a ztl's test\n"; + NV(hello_world) + ztl::lexer::lexer(hello_world); +} \ No newline at end of file