| 2134 | } |
| 2135 | |
| 2136 | void parse_key_value(std::string::iterator& it, std::string::iterator& end, |
| 2137 | table* curr_table) |
| 2138 | { |
| 2139 | auto key_end = [](char c) { return c == '='; }; |
| 2140 | |
| 2141 | auto key_part_handler = [&](const std::string& part) { |
| 2142 | // two cases: this key part exists already, in which case it must |
| 2143 | // be a table, or it doesn't exist in which case we must create |
| 2144 | // an implicitly defined table |
| 2145 | if (curr_table->contains(part)) |
| 2146 | { |
| 2147 | auto val = curr_table->get(part); |
| 2148 | if (val->is_table()) |
| 2149 | { |
| 2150 | curr_table = static_cast<table*>(val.get()); |
| 2151 | } |
| 2152 | else |
| 2153 | { |
| 2154 | throw_parse_exception("Key " + part |
| 2155 | + " already exists as a value"); |
| 2156 | } |
| 2157 | } |
| 2158 | else |
| 2159 | { |
| 2160 | auto newtable = make_table(); |
| 2161 | curr_table->insert(part, newtable); |
| 2162 | curr_table = newtable.get(); |
| 2163 | } |
| 2164 | }; |
| 2165 | |
| 2166 | auto key = parse_key(it, end, key_end, key_part_handler); |
| 2167 | |
| 2168 | if (curr_table->contains(key)) |
| 2169 | throw_parse_exception("Key " + key + " already present"); |
| 2170 | if (it == end || *it != '=') |
| 2171 | throw_parse_exception("Value must follow after a '='"); |
| 2172 | ++it; |
| 2173 | consume_whitespace(it, end); |
| 2174 | curr_table->insert(key, parse_value(it, end)); |
| 2175 | consume_whitespace(it, end); |
| 2176 | } |
| 2177 | |
| 2178 | template <class KeyEndFinder, class KeyPartHandler> |
| 2179 | std::string |
no test coverage detected