1 #pragma once 2 3 #include "tokens.hpp" 4 #include "hocon/config_exception.hpp" 5 #include <hocon/config_syntax.hpp> 6 7 #include <boost/nowide/fstream.hpp> 8 #include <vector> 9 #include <queue> 10 #include <string> 11 12 namespace hocon { 13 14 // This exception should not leave this file 15 class problem_exception : std::runtime_error { 16 public: 17 problem_exception(problem prob); 18 problem const& get_problem() const; 19 20 private: 21 problem _problem; 22 }; 23 24 class iterator { 25 public: 26 virtual bool has_next() = 0; 27 virtual shared_token next() = 0; 28 }; 29 30 template <typename iter> 31 class iterator_wrapper : public iterator { 32 public: iterator_wrapper(iter begin,iter end)33 iterator_wrapper(iter begin, iter end) 34 : _cur(begin), _end(end) { } 35 has_next()36 bool has_next() override { 37 return _cur != _end; 38 } 39 next()40 shared_token next() override { 41 return *_cur++; 42 } 43 44 private: 45 iter _cur; 46 iter _end; 47 }; 48 49 class token_iterator : public iterator { 50 public: 51 token_iterator(shared_origin origin, std::unique_ptr<std::istream> input, bool allow_comments); 52 token_iterator(shared_origin origin, std::unique_ptr<std::istream> input, config_syntax flavor); 53 54 bool has_next() override; 55 shared_token next() override; 56 57 static std::string render(token_list tokens); 58 59 private: 60 class whitespace_saver { 61 public: 62 whitespace_saver(); 63 void add(char c); 64 shared_token check(token_type type, shared_origin base_origin, int line_number); 65 66 private: 67 shared_token next_is_not_simple_value(shared_origin base_origin, int line_number); 68 shared_token next_is_simple_value(shared_origin origin, int line_number); 69 shared_token create_whitespace_token(shared_origin base_origin, int line_number); 70 71 std::string _whitespace; 72 bool _last_token_was_simple_value; 73 }; 74 75 bool start_of_comment(char c); 76 shared_token pull_comment(char first_char); 77 78 /** Get next char, skipping newline whitespace */ 79 char next_char_after_whitespace(whitespace_saver& saver); 80 81 /** 82 * The rules here are intended to maximize convenience while 83 * avoiding confusion with real valid JSON. Basically anything 84 * that parses as JSON is treated the JSON way and otherwise 85 * we assume it's a string and let the parser sort it out. 86 */ 87 shared_token pull_unquoted_text(); 88 89 shared_token pull_number(char first_char); 90 91 /** 92 * @param parsed The string with the escape sequence parsed. 93 * @param original The string with the escape sequence left as in the original text 94 */ 95 void pull_escape_sequence(std::string& parsed, std::string& original); 96 97 void append_triple_quoted_string(std::string& parsed, std::string& original); 98 99 shared_token pull_quoted_string(); 100 101 shared_token const& pull_plus_equals(); 102 shared_token pull_substitution(); 103 shared_token pull_next_token(whitespace_saver& saver); 104 void queue_next_token(); 105 106 static bool is_simple_value(token_type type); 107 static std::string as_string(char c); 108 static shared_origin line_origin(shared_origin base_origin, int line_number); 109 110 shared_origin _origin; 111 std::unique_ptr<std::istream> _input; 112 bool _allow_comments; 113 int _line_number; 114 shared_origin _line_origin; 115 std::queue<shared_token> _tokens; 116 whitespace_saver _whitespace_saver; 117 }; 118 119 class single_token_iterator : public iterator { 120 public: 121 single_token_iterator(shared_token token); 122 123 bool has_next() override; 124 shared_token next() override; 125 126 private: 127 shared_token _token; 128 bool _has_next; 129 }; 130 131 class token_list_iterator : public iterator { 132 public: 133 token_list_iterator(token_list tokens); 134 135 bool has_next() override; 136 shared_token next() override; 137 138 private: 139 token_list _tokens; 140 int _index; 141 }; 142 143 } // namespace hocon 144