From c09cd7512491cee1e82c1ad8128ce9fd4bc3f79b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 22 Sep 2017 23:32:28 +0200 Subject: Initial modularization with both Clang and VC hacks Note: gave up on VC about half way though. --- libbutl/manifest-parser.mxx | 116 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 libbutl/manifest-parser.mxx (limited to 'libbutl/manifest-parser.mxx') diff --git a/libbutl/manifest-parser.mxx b/libbutl/manifest-parser.mxx new file mode 100644 index 0000000..c21ccc1 --- /dev/null +++ b/libbutl/manifest-parser.mxx @@ -0,0 +1,116 @@ +// file : libbutl/manifest-parser.mxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef __cpp_modules +#pragma once +#endif + +// C includes. + +#ifndef __cpp_lib_modules +#include +#include +#include // uint64_t +#include // pair +#include // runtime_error +#endif + +// Other includes. + +#ifdef __cpp_modules +export module butl.manifest_parser; +#ifdef __cpp_lib_modules +import std.core; +import std.io; +#endif +import butl.char_scanner; +#else +#include +#endif + +#include + +LIBBUTL_MODEXPORT namespace butl +{ + class LIBBUTL_SYMEXPORT manifest_parsing: public std::runtime_error + { + public: + manifest_parsing (const std::string& name, + std::uint64_t line, + std::uint64_t column, + const std::string& description); + + std::string name; + std::uint64_t line; + std::uint64_t column; + std::string description; + }; + + class manifest_name_value + { + public: + std::string name; + std::string value; + + std::uint64_t name_line; + std::uint64_t name_column; + + std::uint64_t value_line; + std::uint64_t value_column; + + bool + empty () const {return name.empty () && value.empty ();} + }; + + class LIBBUTL_SYMEXPORT manifest_parser: protected butl::char_scanner + { + public: + manifest_parser (std::istream& is, const std::string& name) + : char_scanner (is), name_ (name) {} + + const std::string& + name () const {return name_;} + + // The first returned pair is special "start-of-manifest" with + // empty name and value being the format version: {"", ""}. + // After that we have a sequence of ordinary pairs which are + // the manifest. At the end of the manifest we have the special + // "end-of-manifest" pair with empty name and value: {"", ""}. + // After that we can either get another start-of-manifest pair + // (in which case the whole sequence repeats from the beginning) + // or we get another end-of-manifest pair which signals the end + // of stream (aka EOF). To put it another way, the parse sequence + // always has the following form: + // + // ({"", ""} {"", ""}* {"", ""})* {"", ""} + // + manifest_name_value + next (); + + // Split the manifest value, optionally followed by ';' character and a + // comment into the value/comment pair. Note that ';' characters in the + // value must be escaped by the backslash. + // + static std::pair + split_comment (const std::string&); + + private: + void + parse_name (manifest_name_value&); + + void + parse_value (manifest_name_value&); + + // Skip spaces and return the first peeked non-space character. + // + xchar + skip_spaces (); + + private: + const std::string name_; + + enum {start, body, end} s_ = start; + std::string version_; // Current format version. + }; +} -- cgit v1.1