diff options
Diffstat (limited to 'tools/minicargo')
-rw-r--r-- | tools/minicargo/Makefile | 9 | ||||
-rw-r--r-- | tools/minicargo/build.h | 2 | ||||
-rw-r--r-- | tools/minicargo/debug.cpp | 80 | ||||
-rw-r--r-- | tools/minicargo/debug.h | 68 | ||||
-rw-r--r-- | tools/minicargo/helpers.h | 53 | ||||
-rw-r--r-- | tools/minicargo/manifest.h | 3 | ||||
-rw-r--r-- | tools/minicargo/path.cpp | 194 | ||||
-rw-r--r-- | tools/minicargo/path.h | 181 | ||||
-rw-r--r-- | tools/minicargo/toml.cpp | 414 | ||||
-rw-r--r-- | tools/minicargo/toml.h | 151 |
10 files changed, 8 insertions, 1147 deletions
diff --git a/tools/minicargo/Makefile b/tools/minicargo/Makefile index 71e266b0..01010fb5 100644 --- a/tools/minicargo/Makefile +++ b/tools/minicargo/Makefile @@ -14,10 +14,10 @@ OBJDIR := .obj/ BIN := ../bin/minicargo$(EXESUF) OBJS := main.o build.o manifest.o repository.o -OBJS += toml.o path.o debug.o LINKFLAGS := -g -lpthread CXXFLAGS := -Wall -std=c++14 -g -O2 +CXXFLAGS += -I ../common OBJS := $(OBJS:%=$(OBJDIR)%) @@ -28,15 +28,18 @@ all: $(BIN) clean: rm $(BIN) $(OBJS) -$(BIN): $(OBJS) +$(BIN): $(OBJS) ../bin/common_lib.a @mkdir -p $(dir $@) @echo [CXX] -o $@ - $V$(CXX) -o $@ $(OBJS) $(LINKFLAGS) + $V$(CXX) -o $@ $(OBJS) ../bin/common_lib.a $(LINKFLAGS) $(OBJDIR)%.o: %.cpp @mkdir -p $(dir $@) @echo [CXX] $< $V$(CXX) -o $@ -c $< $(CXXFLAGS) -MMD -MP -MF $@.dep +../bin/common_lib.a: + make -C ../common + -include $(OBJS:%.o=%.o.dep) diff --git a/tools/minicargo/build.h b/tools/minicargo/build.h index 0b3e949b..54d03575 100644 --- a/tools/minicargo/build.h +++ b/tools/minicargo/build.h @@ -1,7 +1,7 @@ #pragma once #include "manifest.h" -#include "path.h" +#include <path.h> class StringList; class StringListKV; diff --git a/tools/minicargo/debug.cpp b/tools/minicargo/debug.cpp deleted file mode 100644 index a3fb9956..00000000 --- a/tools/minicargo/debug.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * MiniCargo - mrustc's minimal clone of cargo - * - By John Hodge (Mutabah/thePowersGang) - * - * debug.cpp - * - Debugging helpers - */ -#if defined(__MINGW32__) -# define DISABLE_MULTITHREAD // Mingw32 doesn't have c++11 threads -#endif -#include <set> -#include <iostream> -#include "debug.h" -#include <mutex> - -static int giIndentLevel = 0; -static const char* gsDebugPhase = ""; -static ::std::set<::std::string> gmDisabledDebug; -#ifndef DISABLE_MULTITHREAD -static ::std::mutex gDebugLock; -#endif - -void Debug_SetPhase(const char* phase_name) -{ - gsDebugPhase = phase_name; -} -bool Debug_IsEnabled() -{ - if( gmDisabledDebug.find(gsDebugPhase) != gmDisabledDebug.end() ) - return false; - return true; -} -void Debug_DisablePhase(const char* phase_name) -{ - gmDisabledDebug.insert( ::std::string(phase_name) ); -} -void Debug_Print(::std::function<void(::std::ostream& os)> cb) -{ - if( !Debug_IsEnabled() ) - return ; -#ifndef DISABLE_MULTITHREAD - ::std::unique_lock<::std::mutex> _lh { gDebugLock }; -#endif - - ::std::cout << gsDebugPhase << "- "; - for(auto i = giIndentLevel; i --; ) - ::std::cout << " "; - cb(::std::cout); - ::std::cout << ::std::endl; -} -void Debug_EnterScope(const char* name, dbg_cb_t cb) -{ - if( !Debug_IsEnabled() ) - return ; -#ifndef DISABLE_MULTITHREAD - ::std::unique_lock<::std::mutex> _lh { gDebugLock }; -#endif - - ::std::cout << gsDebugPhase << "- "; - for(auto i = giIndentLevel; i --; ) - ::std::cout << " "; - ::std::cout << ">>> " << name << "("; - cb(::std::cout); - ::std::cout << ")" << ::std::endl; - giIndentLevel ++; -} -void Debug_LeaveScope(const char* name, dbg_cb_t cb) -{ - if( !Debug_IsEnabled() ) - return ; -#ifndef DISABLE_MULTITHREAD - ::std::unique_lock<::std::mutex> _lh { gDebugLock }; -#endif - - ::std::cout << gsDebugPhase << "- "; - giIndentLevel --; - for(auto i = giIndentLevel; i --; ) - ::std::cout << " "; - ::std::cout << "<<< " << name << ::std::endl; -} diff --git a/tools/minicargo/debug.h b/tools/minicargo/debug.h deleted file mode 100644 index ace00876..00000000 --- a/tools/minicargo/debug.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include <functional> -#include <vector> -#include <sstream> - -typedef ::std::function<void(::std::ostream& os)> dbg_cb_t; -extern void Debug_SetPhase(const char* phase_name); -extern void Debug_DisablePhase(const char* phase_name); -extern bool Debug_IsEnabled(); -extern void Debug_EnterScope(const char* name, dbg_cb_t ); -extern void Debug_LeaveScope(const char* name, dbg_cb_t ); -extern void Debug_Print(dbg_cb_t cb); - -#if defined(NOLOG) -# define DEBUG(fmt) do { } while(0) -# define TRACE_FUNCTION_F(fmt) do{}while(0) -#else -# define DEBUG(fmt) do { Debug_Print([&](auto& os){ os << "DEBUG: " << fmt; }); } while(0) -# define TRACE_FUNCTION_F(fmt) DebugFunctionScope trace_function_hdr { __FUNCTION__, [&](auto& os){ os << fmt; } } -#endif -#define TODO(fmt) do { ::std::cerr << "TODO: " << fmt << ::std::endl; abort(); } while(0) - -namespace { - static inline void format_to_stream(::std::ostream& os) { - } - template<typename T, typename... A> - static inline void format_to_stream(::std::ostream& os, const T& v, const A&... a) { - os << v; - format_to_stream(os, a...); - } -} - -struct DebugFunctionScope { - const char* m_name; - DebugFunctionScope(const char* name, dbg_cb_t cb): - m_name(name) - { - Debug_EnterScope(m_name, cb); - } - ~DebugFunctionScope() - { - Debug_LeaveScope(m_name, [](auto& ){}); - } -}; - -template<typename ...T> -::std::string format(const T&... v) -{ - ::std::stringstream ss; - format_to_stream(ss, v...); - return ss.str(); -} - -template<typename T> -::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v) -{ - bool first = true; - for(const auto& e : v) - { - if(!first) - os << ","; - os << e; - first = false; - } - return os; -} - diff --git a/tools/minicargo/helpers.h b/tools/minicargo/helpers.h deleted file mode 100644 index 8111483a..00000000 --- a/tools/minicargo/helpers.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include <string> -#include <cstring> -#include <iostream> - -namespace helpers { - -class string_view -{ - const char* m_start; - const size_t m_len; -public: - string_view(const char* s, size_t n): - m_start(s), m_len(n) - { - } - - bool operator==(const ::std::string& s) const { - return *this == s.c_str(); - } - bool operator==(const char* s) const { - if(::std::strncmp(m_start, s, m_len) != 0) - return false; - return s[m_len] == '\0'; - } - - char operator[](size_t n) const { - return m_start[n]; - } - - operator ::std::string() const { - return ::std::string { m_start, m_start + m_len }; - } - friend ::std::string& operator+=(::std::string& x, const string_view& sv) { - x.append(sv.m_start, sv.m_start+sv.m_len); - return x; - } - friend ::std::ostream& operator<<(::std::ostream& os, const string_view& sv) { - os.write(sv.m_start, sv.m_len); - return os; - } - - const char* begin() const { - return m_start; - } - const char* end() const { - return m_start+m_len; - } -}; - - -} // namespace helpers diff --git a/tools/minicargo/manifest.h b/tools/minicargo/manifest.h index bbe2c34b..e48e7f2a 100644 --- a/tools/minicargo/manifest.h +++ b/tools/minicargo/manifest.h @@ -5,8 +5,7 @@ #include <map> #include <memory> #include <functional> -#include "path.h" -#include <functional> +#include <path.h> class PackageManifest; class Repository; diff --git a/tools/minicargo/path.cpp b/tools/minicargo/path.cpp deleted file mode 100644 index 12e505bb..00000000 --- a/tools/minicargo/path.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - */ -#include "path.h" -#if _WIN32 -# include <Windows.h> -#else -# include <unistd.h> // getcwd/chdir -#endif - -helpers::path::path(const char* s): - m_str(s) -{ - // 1. Normalise path separators to the system specified separator - for(size_t i = 0; i < m_str.size(); i ++) - { - if( m_str[i] == '/' || m_str[i] == '\\' ) - m_str[i] = SEP; - } - - // 2. Remove any trailing separators - if( !m_str.empty() ) - { - while(!m_str.empty() && m_str.back() == SEP ) - m_str.pop_back(); - if(m_str.empty()) - { - m_str.push_back(SEP); - } - } - else - { - throw ::std::runtime_error("Empty path being constructed"); - } -} - -helpers::path helpers::path::to_absolute() const -{ - if(!this->is_valid()) - throw ::std::runtime_error("Calling to_absolute() on an invalid path"); - - if(this->m_str[0] == SEP) - return *this; - - #if _WIN32 - char cwd[1024]; - GetCurrentDirectoryA(sizeof(cwd), cwd); - #else - char cwd[1024]; - if( !getcwd(cwd, sizeof(cwd)) ) - throw ::std::runtime_error("Calling getcwd() failed in path::to_absolute()"); - #endif - auto rv = path(cwd); - for(auto comp : *this) - { - if(comp == ".") - ; - else if( comp == ".." ) - rv.pop_component(); - else - rv /= comp; - } - #if _WIN32 - #else - #endif - return rv; -} - -helpers::path helpers::path::normalise() const -{ - path rv; - rv.m_str.reserve( m_str.size()+1 ); - - for(auto comp : *this) - { - if( comp == "." ) { - // Ignore. - } - else if( comp == ".." ) - { - // If the path is empty, OR the last element is a "..", push the element - if( rv.m_str.empty() - || (rv.m_str.size() == 3 && rv.m_str[0] == '.' && rv.m_str[1] == '.' && rv.m_str[2] == SEP) - || (rv.m_str.size() > 4 && *(rv.m_str.end()-4) == SEP && *(rv.m_str.end()-3) == '.' && *(rv.m_str.end()-2) == '.' && *(rv.m_str.end()-1) == SEP ) - ) - { - // Push - rv.m_str += comp; - rv.m_str += SEP; - } - else - { - rv.m_str.pop_back(); - auto pos = rv.m_str.find_last_of(SEP); - if(pos == ::std::string::npos) - { - rv.m_str.resize(0); - } - else if( pos == 0 ) - { - // Keep. - } - else - { - rv.m_str.resize(pos+1); - } - } - } - else - { - rv.m_str += comp; - rv.m_str += SEP; - } - } - rv.m_str.pop_back(); - return rv; -} - -#if 0 -void helpers::path::normalise_in_place() -{ - size_t insert_point = 0; - - for(size_t read_pos = 0; read_pos < m_str.size(); read_pos ++) - { - auto pos = m_str.find_first_of(SEP, read_pos); - if(pos == ::std::string::npos) - pos = m_str.size(); - auto comp = string_view(m_str.c_str() + read_pos, pos - read_pos); - - bool append; - if(comp == ".") - { - // Advance read without touching insert - append = false; - } - else if( comp == ".." ) - { - // Consume parent (if not a relative component already) - // Move insertion point back to the previous separator - auto pos = m_str.find_last_of(SEP, insert_point); - if(pos == ::std::string::npos) - { - // Only one component currently (or empty) - append = true; - } - else if(string_view(m_str.c_str() + pos+1, insert_point - pos-1) == "..") - { - // Last component is ".." - keep adding - append = true; - } - else - { - insert_point = pos; - append = false; - } - } - else - { - append = true; - } - - if(append) - { - if( read_pos != insert_point ) - { - //assert(read_pos > insert_point); - while(read_pos < pos) - { - m_str[insert_point++] = m_str[read_pos++]; - } - } - } - else - { - read_pos = pos; - } - } -} -#endif - -void helpers::path::ComponentsIter::operator++() -{ - if(end == p.m_str.size()) - { - pos = end; - } - else - { - pos = end+1; - end = p.m_str.find(SEP, pos); - if(end == ::std::string::npos) - end = p.m_str.size(); - } -} diff --git a/tools/minicargo/path.h b/tools/minicargo/path.h deleted file mode 100644 index dd97f9be..00000000 --- a/tools/minicargo/path.h +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once - -#include <string> -#include <stdexcept> -#include "helpers.h" - -namespace helpers { - -/// Path helper class (because I don't want to include boost) -class path -{ -#ifdef _WIN32 - static const char SEP = '\\'; -#else - static const char SEP = '/'; -#endif - - ::std::string m_str; - -public: - path() - { - } - path(const ::std::string& s): - path(s.c_str()) - { - } - path(const char* s); - - bool is_valid() const { - return m_str != ""; - } - - path& operator/=(const path& p) - { - if(!p.is_valid()) - throw ::std::runtime_error("Appending from an invalid path"); - - return *this /= p.m_str.c_str(); - } - path& operator/=(const char* o) - { - if(!this->is_valid()) - throw ::std::runtime_error("Appending to an invalid path"); - if(o[0] == '/') - throw ::std::runtime_error("Appending an absolute path to another path"); - this->m_str.push_back(SEP); - this->m_str.append(o); - return *this; - } - path& operator/=(const string_view& o) - { - if(!this->is_valid()) - throw ::std::runtime_error("Appending to an invalid path"); - if(o[0] == '/') - throw ::std::runtime_error("Appending an absolute path to another path"); - this->m_str.push_back(SEP); - this->m_str += o; - return *this; - } - - path operator/(const path& p) const - { - auto rv = *this; - rv /= p; - return rv; - } - /// Append a relative path - path operator/(const char* o) const - { - auto rv = *this; - rv /= o; - return rv; - } - /// Add an arbitary string to the final component - path operator+(const char* o) const - { - if(!this->is_valid()) - throw ::std::runtime_error("Appending a string to an invalid path"); - if( ::std::strchr(o, SEP) != nullptr ) - throw ::std::runtime_error("Appending a string containing the path separator (with operator+)"); - auto rv = *this; - rv.m_str.append(o); - return rv; - } - - bool pop_component() - { - if(!this->is_valid()) - throw ::std::runtime_error("Calling pop_component() on an invalid path"); - auto pos = m_str.find_last_of(SEP); - if(pos == ::std::string::npos || pos == 0) - { - return false; - } - else - { - this->m_str.resize(pos); - return true; - } - } - path parent() const - { - if(!this->is_valid()) - throw ::std::runtime_error("Calling parent() on an invalid path"); - auto pos = m_str.find_last_of(SEP); - if(pos == ::std::string::npos) - { - return *this; - } - else - { - path rv; - rv.m_str = m_str.substr(0, pos); - return rv; - } - } - path to_absolute() const; - ::std::string basename() const - { - if(!this->is_valid()) - throw ::std::runtime_error("Calling basename() on an invalid path"); - - auto pos = m_str.find_last_of(SEP); - if(pos == ::std::string::npos) - { - return m_str; - } - else - { - return m_str.substr(pos+1); - } - } - - const ::std::string& str() const - { - return m_str; - } - operator ::std::string() const - { - return m_str; - } - - class ComponentsIter - { - const path& p; - size_t pos; - size_t end; - - friend class path; - ComponentsIter(const path& p, size_t i): p(p), pos(i) { - end = p.m_str.find(SEP, pos); - if(end == ::std::string::npos) - end = p.m_str.size(); - } - public: - string_view operator*() const { - return string_view(p.m_str.c_str() + pos, end - pos); - } - void operator++(); - bool operator!=(const ComponentsIter& x) const { - return pos != x.pos; - } - }; - ComponentsIter begin() const { - return ComponentsIter(*this, 0); - } - ComponentsIter end() const { - return ComponentsIter(*this, m_str.size()); - } - - path normalise() const; - //void normalise_in_place(); - - friend ::std::ostream& operator<<(::std::ostream& os, const path& p) - { - return os << p.m_str; - } -}; - -} diff --git a/tools/minicargo/toml.cpp b/tools/minicargo/toml.cpp deleted file mode 100644 index 9fad0ec4..00000000 --- a/tools/minicargo/toml.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * A very bad streaming TOML parser - */ -#define NOLOG -#include "toml.h" -#include "debug.h" -#include <cassert> -#include <string> - - -struct Token -{ - enum class Type - { - Eof, - SquareOpen, - SquareClose, - BraceOpen, - BraceClose, - Assign, - Newline, - Comma, - Dot, - - Ident, - String, - Integer, - }; - - Type m_type; - ::std::string m_data; - int64_t m_intval = 0; - - Token(Type ty): - m_type(ty) - { - } - Token(Type ty, ::std::string s): - m_type(ty), - m_data(s) - { - } - Token(Type ty, int64_t i): - m_type(ty), - m_intval(i) - { - } - - - static Token lex_from(::std::ifstream& is); - static Token lex_from_inner(::std::ifstream& is); - - const ::std::string& as_string() const { - assert(m_type == Type::Ident || m_type == Type::String); - return m_data; - } - - friend ::std::ostream& operator<<(::std::ostream& os, const Token& x) { - switch(x.m_type) - { - case Type::Eof: os << "Eof"; break; - case Type::SquareOpen: os << "SquareOpen"; break; - case Type::SquareClose: os << "SquareClose"; break; - case Type::BraceOpen: os << "BraceOpen"; break; - case Type::BraceClose: os << "BraceClose"; break; - case Type::Assign: os << "Assign"; break; - case Type::Newline: os << "Newline"; break; - case Type::Comma: os << "Comma"; break; - case Type::Dot: os << "Dot"; break; - case Type::Ident: os << "Ident(" << x.m_data << ")"; break; - case Type::String: os << "String(" << x.m_data << ")"; break; - case Type::Integer: os << "Integer(" << x.m_intval << ")"; break; - } - return os; - } -}; - -TomlFile::TomlFile(const ::std::string& filename): - m_if(filename) -{ - if( !m_if.is_open() ) { - throw ::std::runtime_error("Unable to open file '" + filename + "'"); - } -} -TomlFileIter TomlFile::begin() -{ - TomlFileIter rv { *this }; - ++rv; - return rv; -} -TomlFileIter TomlFile::end() -{ - return TomlFileIter { *this }; -} - -TomlKeyValue TomlFile::get_next_value() -{ - auto t = Token::lex_from(m_if); - - if(m_current_composite.empty()) - { - while( t.m_type == Token::Type::Newline ) - t = Token::lex_from(m_if); - - // Expect '[', a string, or an identifier - switch(t.m_type) - { - case Token::Type::Eof: - // Empty return indicates the end of the list - return TomlKeyValue {}; - case Token::Type::SquareOpen: - m_current_block.clear(); - do - { - t = Token::lex_from(m_if); - bool is_array = false; - if(t.m_type == Token::Type::SquareOpen) - { - is_array = true; - t = Token::lex_from(m_if); - } - assert(t.m_type == Token::Type::Ident || t.m_type == Token::Type::String); - m_current_block.push_back(t.as_string()); - if(is_array) - { - m_current_block.push_back(::format(m_array_counts[t.as_string()]++)); - t = Token::lex_from(m_if); - assert(t.m_type == Token::Type::SquareClose); - } - - t = Token::lex_from(m_if); - } while(t.m_type == Token::Type::Dot); - if( t.m_type != Token::Type::SquareClose ) - { - throw ::std::runtime_error(::format("Unexpected token in block header - ", t)); - } - t = Token::lex_from(m_if); - if (t.m_type != Token::Type::Newline) - { - throw ::std::runtime_error(::format("Unexpected token after block block - ", t)); - } - DEBUG("Start block " << m_current_block); - // Recurse! - return get_next_value(); - default: - break; - } - } - else - { - // Expect a string or an identifier - if( t.m_type == Token::Type::Eof ) - { - // EOF isn't allowed here - throw ::std::runtime_error(::format("Unexpected EOF in composite")); - } - } - switch (t.m_type) - { - case Token::Type::String: - case Token::Type::Ident: - break; - default: - throw ::std::runtime_error(::format("Unexpected token for key - ", t)); - } - ::std::string key_name = t.as_string(); - t = Token::lex_from(m_if); - - if(t.m_type != Token::Type::Assign) - throw ::std::runtime_error(::format("Unexpected token after key - ", t)); - t = Token::lex_from(m_if); - - TomlKeyValue rv; - switch(t.m_type) - { - case Token::Type::String: - rv.path = m_current_block; - rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); - rv.path.push_back(key_name); - - rv.value = TomlValue { t.m_data }; - break; - case Token::Type::SquareOpen: - rv.path = m_current_block; - rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); - rv.path.push_back(key_name); - - rv.value.m_type = TomlValue::Type::List; - while( (t = Token::lex_from(m_if)).m_type != Token::Type::SquareClose ) - { - while( t.m_type == Token::Type::Newline ) - t = Token::lex_from(m_if); - if( t.m_type == Token::Type::SquareClose ) - break; - - // TODO: Recurse parse a value - switch(t.m_type) - { - case Token::Type::String: - rv.value.m_sub_values.push_back(TomlValue { t.as_string() }); - break; - default: - throw ::std::runtime_error(::format("Unexpected token in array value position - ", t)); - } - - t = Token::lex_from(m_if); - if(t.m_type != Token::Type::Comma) - break; - } - if(t.m_type != Token::Type::SquareClose) - throw ::std::runtime_error(::format("Unexpected token after array - ", t)); - break; - case Token::Type::BraceOpen: - m_current_composite.push_back(key_name); - DEBUG("Enter composite block " << m_current_block << ", " << m_current_composite); - // Recurse to restart parse - return get_next_value(); - case Token::Type::Integer: - rv.path = m_current_block; - rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); - rv.path.push_back(key_name); - rv.value = TomlValue { t.m_intval }; - return rv; - case Token::Type::Ident: - if( t.m_data == "true" ) - { - rv.path = m_current_block; - rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); - rv.path.push_back(key_name); - rv.value = TomlValue { true }; - } - else if( t.m_data == "false" ) - { - rv.path = m_current_block; - rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); - rv.path.push_back(key_name); - - rv.value = TomlValue { false }; - } - else - { - throw ::std::runtime_error(::format("Unexpected identifier in value position - ", t)); - } - break; - default: - throw ::std::runtime_error(::format("Unexpected token in value position - ", t)); - } - - t = Token::lex_from(m_if); - while (!m_current_composite.empty() && t.m_type == Token::Type::BraceClose) - { - DEBUG("Leave composite block " << m_current_block << ", " << m_current_composite); - m_current_composite.pop_back(); - t = Token::lex_from(m_if); - } - if( m_current_composite.empty() ) - { - // TODO: Allow EOF? - if(t.m_type != Token::Type::Newline) - throw ::std::runtime_error(::format("Unexpected token in TOML file after entry - ", t)); - } - else - { - if( t.m_type != Token::Type::Comma ) - throw ::std::runtime_error(::format("Unexpected token in TOML file after composite entry - ", t)); - } - return rv; -} - -Token Token::lex_from(::std::ifstream& is) -{ - auto rv = Token::lex_from_inner(is); - //DEBUG("lex_from: " << rv); - return rv; -} -Token Token::lex_from_inner(::std::ifstream& is) -{ - int c; - do - { - c = is.get(); - } while( c != EOF && c != '\n' && isspace(c) ); - - ::std::string str; - switch(c) - { - case EOF: return Token { Type::Eof }; - case '[': return Token { Type::SquareOpen }; - case ']': return Token { Type::SquareClose }; - case '{': return Token { Type::BraceOpen }; - case '}': return Token { Type::BraceClose }; - case ',': return Token { Type::Comma }; - case '.': return Token { Type::Dot }; - case '=': return Token { Type::Assign }; - case '\n': return Token { Type::Newline }; - case '#': - while(c != '\n') - { - c = is.get(); - if(c == EOF) - return Token { Type::Eof }; - } - return Token { Type::Newline }; - case '\'': - c = is.get(); - while (c != '\'') - { - if (c == EOF) - throw ::std::runtime_error("Unexpected EOF in single-quoted string"); - if (c == '\\') - { - // TODO: Escaped strings - throw ::std::runtime_error("TODO: Escaped sequences in strings (single)"); - } - str += (char)c; - c = is.get(); - } - return Token { Type::String, str }; - case '"': - c = is.get(); - if(c == '"') - { - c = is.get(); - if( c != '"' ) - { - is.putback(c); - return Token { Type::String, "" }; - } - else - { - // Keep reading until """ - for(;;) - { - c = is.get(); - if(c == '"') - { - c = is.get(); - if(c == '"') - { - c = is.get(); - if(c == '"') - { - break; - } - str += '"'; - } - str += '"'; - } - if( c == EOF ) - throw ::std::runtime_error("Unexpected EOF in triple-quoted string"); - if(c == '\\') - { - // TODO: Escaped strings - throw ::std::runtime_error("TODO: Escaped sequences in strings (triple)"); - } - str += (char)c; - } - } - } - else - { - while(c != '"') - { - if (c == EOF) - throw ::std::runtime_error("Unexpected EOF in double-quoted string"); - if (c == '\\') - { - // TODO: Escaped strings - c = is.get(); - switch(c) - { - case '"': str += '"'; break; - case 'n': str += '\n'; break; - default: - throw ::std::runtime_error("TODO: Escaped sequences in strings"); - } - c = is.get(); - continue ; - } - str += (char)c; - c = is.get(); - } - } - return Token { Type::String, str }; - default: - if(isalpha(c)) - { - // Identifier - while(isalnum(c) || c == '-' || c == '_') - { - str += (char)c; - c = is.get(); - } - is.putback(c); - return Token { Type::Ident, str }; - } - else if( isdigit(c) ) - { - int64_t val = 0; - while(isdigit(c)) - { - val *= 10; - val += c - '0'; - c = is.get(); - } - is.putback(c); - return Token { Type::Integer, val }; - } - else - { - throw ::std::runtime_error(::format("Unexpected chracter '", (char)c, "' in file")); - } - } -} diff --git a/tools/minicargo/toml.h b/tools/minicargo/toml.h deleted file mode 100644 index 315cf62f..00000000 --- a/tools/minicargo/toml.h +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once - -#include <fstream> -#include <vector> -#include <string> -#include <unordered_map> - -class TomlFileIter; -struct TomlKeyValue; - -class TomlFile -{ - /// Input file stream - ::std::ifstream m_if; - - /// Name of the current `[]` block - ::std::vector<::std::string> m_current_block; - - /// Path suffix of the current composite (none if empty) - ::std::vector<::std::string> m_current_composite; - - /// Index of the next array field (if zero, not parsing an array) - unsigned int m_next_array_index; - - /// Next indexes if top-level defined arrays (e.g. `[[foo]]`) - ::std::unordered_map<::std::string,unsigned> m_array_counts; - -public: - TomlFile(const ::std::string& filename); - - TomlFileIter begin(); - TomlFileIter end(); - - TomlKeyValue get_next_value(); -}; - -struct TomlValue -{ - enum class Type - { - Boolean, - String, - Integer, - List, - }; - struct TypeError: - public ::std::exception - { - Type have; - Type exp; - - TypeError(Type h, Type e): - have(h), - exp(e) - { - } - - const char* what() const noexcept override { - return "toml type error"; - } - }; - - Type m_type; - uint64_t m_int_value; - ::std::string m_str_value; - ::std::vector<TomlValue> m_sub_values; - - TomlValue(): - m_type(Type::String) - { - } - TomlValue(::std::string s): - m_type( Type::String ), - m_str_value(::std::move(s)) - { - } - TomlValue(int64_t v): - m_type(Type::Integer), - m_int_value(v) - { - } - TomlValue(bool v) : - m_type(Type::Boolean), - m_int_value(v ? 1 : 0) - { - } - - const ::std::string& as_string() const { - if( m_type != Type::String ) { - throw TypeError { m_type, Type::String }; - } - return m_str_value; - } - bool as_bool() const { - if(m_type != Type::Boolean) { - throw TypeError { m_type, Type::Boolean }; - } - return m_int_value != 0; - } - - friend ::std::ostream& operator<<(::std::ostream& os, const TomlValue& x) { - switch(x.m_type) - { - case Type::Boolean: os << (x.m_int_value != 0 ? "true" : "false"); break; - case Type::Integer: os << x.m_int_value; break; - case Type::List: - os << "["; - for(auto& e : x.m_sub_values) - os << e << ","; - os << "]"; - break; - case Type::String: - os << "\"" << x.m_str_value << "\""; - break; - } - return os; - } -}; - -struct TomlKeyValue -{ - ::std::vector<::std::string> path; - TomlValue value; -}; - -class TomlFileIter -{ - friend class TomlFile; - TomlFile& m_reader; - TomlKeyValue m_cur_value; - - TomlFileIter(TomlFile& tf): - m_reader(tf) - { - - } - -public: - TomlKeyValue operator*() const - { - return m_cur_value; - } - void operator++() - { - m_cur_value = m_reader.get_next_value(); - } - bool operator!=(const TomlFileIter& x) const - { - return m_cur_value.path != x.m_cur_value.path; - } -}; |