From 29fe37743826ad25df72080c12161040892d9e19 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 8 May 2017 19:08:49 +0900 Subject: [PATCH] add parser for tables --- toml/parser.hpp | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/toml/parser.hpp b/toml/parser.hpp index 4f7cd98..69a85b0 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -3,6 +3,7 @@ #include "value.hpp" #include "acceptor.hpp" #include +#include namespace toml { @@ -696,7 +697,197 @@ struct parse_inline_table } }; +template +struct parse_table_contents +{ + typedef charT value_type; + typedef toml::Table result_type; + template::value_type, + value_type>::value>::type> + static result_type invoke(Iterator iter, Iterator end) + { + result_type result; + while(iter != end) + { + iter = is_empty_lines::invoke(iter); + + Iterator tmp = is_key_value_pair::invoke(iter); + result.emplace(parse_key_value_pair::invoke(iter, tmp)); + iter = is_one_of, is_newline>::invoke(tmp); + + iter = is_empty_lines::invoke(iter); + } + return result; + } +}; + +template +struct parse_standard_table_definition +{ + typedef charT value_type; + typedef std::vector result_type; + + template::value_type, + value_type>::value>::type> + static result_type invoke(Iterator iter, Iterator end) + { + result_type result; + iter = is_any_num_of_ws::invoke(iter); + --end; + assert(*iter == '[' && *end == ']'); + ++iter; + iter = is_any_num_of_ws::invoke(iter); + + Iterator tmp = is_key::invoke(iter); + result.emplace(parse_key::invoke(iter, tmp)); + iter = is_any_num_of_ws::invoke(tmp); + + while(iter != end) + { + iter = is_charactor::invoke(iter); + iter = is_any_num_of_ws::invoke(iter); + + tmp = is_key::invoke(iter); + result.emplace(parse_key::invoke(iter, tmp)); + iter = is_any_num_of_ws::invoke(tmp); + } + return result; + } +}; + +template +struct parse_array_of_table_definition +{ + typedef charT value_type; + typedef std::vector result_type; + + template::value_type, + value_type>::value>::type> + static result_type invoke(Iterator iter, Iterator end) + { + result_type result; + iter = is_any_num_of_ws::invoke(iter); + --end; + assert(*iter == '[' && *std::next(iter) == '[' && + *end == ']' && *std::prev(iter) == ']'); + ++iter; ++iter; --end; + + iter = is_any_num_of_ws::invoke(iter); + + Iterator tmp = is_key::invoke(iter); + result.emplace(parse_key::invoke(iter, tmp)); + iter = is_any_num_of_ws::invoke(tmp); + + while(iter != end) + { + iter = is_charactor::invoke(iter); + iter = is_any_num_of_ws::invoke(iter); + + tmp = is_key::invoke(iter); + result.emplace(parse_key::invoke(iter, tmp)); + iter = is_any_num_of_ws::invoke(tmp); + } + return result; + } +}; + +template +struct parse_data +{ + typedef charT value_type; + typedef toml::Table result_type; + + template::value_type, + value_type>::value>::type> + static result_type invoke(Iterator iter, Iterator end) + { + result_type result; + + Iterator tmp = is_table_contents::invoke(iter); + if(tmp != iter) + { + result = parse_table_contents::invoke(iter, tmp); + } + + while(iter != end) + { + if(iter != (tmp = is_table_definition::invoke(iter))) + { + auto k = parse_standard_table_definition::invoke(iter, tmp); + iter = tmp; + tmp = is_table_contents::invoke(iter); + auto tab = parse_table_contents::invoke(iter, tmp); + push_table(result, std::move(tab), std::begin(k), std::end(k)); + } + else if(iter != (tmp=is_array_of_table_definition::invoke(iter))) + { + auto k = parse_array_of_table_definition::invoke(iter, tmp); + iter = tmp; + tmp = is_table_contents::invoke(iter); + auto tab = parse_table_contents::invoke(iter, tmp); + push_array_of_table(result, std::move(tab), + std::begin(k), std::end(k)); + } + else + throw internal_error("no array "); + } + return result; + } + + template::value_type, + toml::key>::value>::type> + static void + push_table(toml::Table& data, toml::Table&& v, Iterator iter, Iterator end) + { + if(iter == std::prev(end)) + { + if(data.count(*iter) == 1) + throw syntax_error("duplicate key"); + data.emplace(*iter, std::move(v)); + } + + if(data.count(*iter) == 0) + data.emplace(*iter, toml::Table()); + else if(data[*iter].type() != value_t::Table) + throw syntax_error("duplicate key"); + + return push_table(data[*iter].template cast(), + std::move(v), std::next(iter), end); + } + + template::value_type, + toml::key>::value>::type> + static void + push_array_of_table(toml::Table& data, toml::Table&& v, + Iterator iter, Iterator end) + { + if(iter == std::prev(end)) + { + if(data.count(*iter) == 0) + data.emplace(*iter, toml::Array()); + else if(data.at(*iter).type() != value_t::Array) + throw syntax_error("duplicate key"); + + data[*iter].template cast().emplace_back(std::move(v)); + } + + if(data.count(*iter) == 0) + data.emplace(*iter, toml::Table()); + else if(data[*iter].type() != value_t::Table) + throw syntax_error("duplicate key"); + + return push_array_of_table(data[*iter].template cast(), + std::move(v), std::next(iter), end); + } + +}; }// toml #endif// TOML11_PARSER