#pragma once #include #include #include #include #include #include "bufio.h" struct BXParseError: std::exception { BXParseError(std::string msg): message(msg) {} std::string message; const char *what() const noexcept override { return message.c_str(); } }; using BXVariables = std::unordered_map>; class BXParser { public: static const int FLAG_NONE = 0; static const int FLAG_ONE_LINE = 1 << 0; BXParser(std::istream &stream, int flags, int line = 1, int ch = 1): flags_(flags), line_(line), ch_(ch), buf_(stream) {} void parse(BXVariables &vars); void parseList(const BXVariables &vars, std::vector &values); int get(); int peek(); int peek2(); void skip(char expected); void skip() { get(); } int line() const { return line_; } int ch() const { return ch_; } private: enum class Operator { COLON_EQUALS, PLUS_EQUALS, EQUALS_PLUS, NONE, }; [[noreturn]] void error(std::string); Operator readOperator(); void skipWhitespaceLine(); void skipWhitespace(); char parseEscape(); void parseExpansion(const BXVariables &vars, std::vector &values); void parseQuotedExpansion(const BXVariables &vars, std::string &content); void parseQuotedString(const BXVariables &vars, std::string &content); bool parseString(const BXVariables &vars, std::string &content, int sep = -1); bool parseIdentifier(std::string &content); int flags_; int line_; int ch_; bufio::IBuf<> buf_; }; class BXWriter { public: BXWriter(std::ostream &stream): buf_(stream) {} void write(const BXVariables &vars); private: void newline(); void escape(const std::string &str); bufio::OBuf<> buf_; };