mirror of
https://github.com/KingDuckZ/kamokan.git
synced 2024-11-23 00:33:44 +00:00
First implementation of a comment skipper.
This commit is contained in:
parent
0e478364ac
commit
0616f45743
2 changed files with 68 additions and 8 deletions
|
@ -26,11 +26,13 @@
|
||||||
#include <boost/spirit/include/qi_kleene.hpp>
|
#include <boost/spirit/include/qi_kleene.hpp>
|
||||||
#include <boost/spirit/include/qi_rule.hpp>
|
#include <boost/spirit/include/qi_rule.hpp>
|
||||||
#include <boost/spirit/include/qi_eol.hpp>
|
#include <boost/spirit/include/qi_eol.hpp>
|
||||||
|
#include <boost/spirit/include/qi_eoi.hpp>
|
||||||
#include <boost/spirit/include/qi_grammar.hpp>
|
#include <boost/spirit/include/qi_grammar.hpp>
|
||||||
#include <boost/spirit/include/qi_hold.hpp>
|
#include <boost/spirit/include/qi_hold.hpp>
|
||||||
#include <boost/spirit/include/qi_char_class.hpp>
|
#include <boost/spirit/include/qi_char_class.hpp>
|
||||||
#include <boost/spirit/include/qi_list.hpp>
|
#include <boost/spirit/include/qi_list.hpp>
|
||||||
#include <boost/spirit/include/qi_optional.hpp>
|
#include <boost/spirit/include/qi_optional.hpp>
|
||||||
|
#include <boost/spirit/include/qi_eps.hpp>
|
||||||
#include <boost/spirit/include/phoenix_stl.hpp>
|
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||||
#include <boost/spirit/include/phoenix_bind.hpp>
|
#include <boost/spirit/include/phoenix_bind.hpp>
|
||||||
|
@ -57,6 +59,31 @@ namespace kamokan {
|
||||||
Iterator m_begin;
|
Iterator m_begin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
struct IniCommentSkipper : boost::spirit::qi::grammar<Iterator> {
|
||||||
|
IniCommentSkipper() :
|
||||||
|
IniCommentSkipper::base_type(start),
|
||||||
|
first_char(true)
|
||||||
|
{
|
||||||
|
namespace px = boost::phoenix;
|
||||||
|
using boost::spirit::qi::blank;
|
||||||
|
using boost::spirit::qi::lit;
|
||||||
|
using boost::spirit::qi::eol;
|
||||||
|
using boost::spirit::qi::char_;
|
||||||
|
using boost::spirit::qi::eps;
|
||||||
|
|
||||||
|
start = skipping[px::ref(first_char) = false];
|
||||||
|
skipping = comment | blank;
|
||||||
|
comment = (eps(px::cref(first_char) == true) | eol) >>
|
||||||
|
*blank >> lit("#") >> *(char_ - eol);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::spirit::qi::rule<Iterator> start;
|
||||||
|
boost::spirit::qi::rule<Iterator> skipping;
|
||||||
|
boost::spirit::qi::rule<Iterator> comment;
|
||||||
|
bool first_char;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Iterator, typename Skipper>
|
template <typename Iterator, typename Skipper>
|
||||||
IniGrammar<Iterator, Skipper>::IniGrammar (const std::string* parString) :
|
IniGrammar<Iterator, Skipper>::IniGrammar (const std::string* parString) :
|
||||||
IniGrammar::base_type(start),
|
IniGrammar::base_type(start),
|
||||||
|
@ -68,6 +95,7 @@ namespace kamokan {
|
||||||
using boost::spirit::qi::_val;
|
using boost::spirit::qi::_val;
|
||||||
using boost::spirit::_1;
|
using boost::spirit::_1;
|
||||||
using boost::spirit::qi::eol;
|
using boost::spirit::qi::eol;
|
||||||
|
using boost::spirit::qi::eoi;
|
||||||
using boost::spirit::qi::raw;
|
using boost::spirit::qi::raw;
|
||||||
using boost::string_view;
|
using boost::string_view;
|
||||||
using boost::spirit::qi::hold;
|
using boost::spirit::qi::hold;
|
||||||
|
@ -79,28 +107,28 @@ namespace kamokan {
|
||||||
[_val = px::bind(
|
[_val = px::bind(
|
||||||
&string_view::substr,
|
&string_view::substr,
|
||||||
px::construct<string_view>(px::ref(*m_master_string)),
|
px::construct<string_view>(px::ref(*m_master_string)),
|
||||||
px::begin(_1) - px::ref(m_begin), px::size(_1)
|
px::begin(_1) - px::cref(m_begin), px::size(_1)
|
||||||
)] >> ']';
|
)] >> ']';
|
||||||
key = raw[(graph - '[' - '=') >> *(graph - '=') >> *(hold[+blank >> +(graph - '=')])][_val = px::bind(
|
key = raw[(graph - '[' - '=') >> *(graph - '=') >> *(hold[+blank >> +(graph - '=')])][_val = px::bind(
|
||||||
&string_view::substr,
|
&string_view::substr,
|
||||||
px::construct<string_view>(px::ref(*m_master_string)),
|
px::construct<string_view>(px::ref(*m_master_string)),
|
||||||
px::begin(_1) - px::ref(m_begin), px::size(_1)
|
px::begin(_1) - px::cref(m_begin), px::size(_1)
|
||||||
)];
|
)];
|
||||||
key_value = key[px::bind(&refpair::first, _val) = _1] >> '=' >>
|
key_value = key[px::bind(&refpair::first, _val) = _1] >> '=' >>
|
||||||
raw[*(graph - eol) >> *(hold[+blank >> +(graph - eol)])][px::bind(&refpair::second, _val) = px::bind(
|
raw[*(graph - eol) % +blank][px::bind(&refpair::second, _val) = px::bind(
|
||||||
&string_view::substr,
|
&string_view::substr,
|
||||||
px::construct<string_view>(px::ref(*m_master_string)),
|
px::construct<string_view>(px::ref(*m_master_string)),
|
||||||
px::begin(_1) - px::ref(m_begin), px::size(_1)
|
px::begin(_1) - px::cref(m_begin), px::size(_1)
|
||||||
)];
|
)];
|
||||||
key_values = -(key_value % (+eol));
|
key_values = -(key_value % (+eol));
|
||||||
start = *(*eol >> section >> +eol >> key_values >> *eol);
|
start = *eol >> *(section >> +eol >> key_values >> *eol);
|
||||||
}
|
}
|
||||||
|
|
||||||
IniFile::IniMapType parse_ini (const std::string* parIni, bool& parParseOk, int& parParsedCharCount) {
|
IniFile::IniMapType parse_ini (const std::string* parIni, bool& parParseOk, int& parParsedCharCount) {
|
||||||
using boost::spirit::qi::blank;
|
|
||||||
using boost::spirit::qi::blank_type;
|
using boost::spirit::qi::blank_type;
|
||||||
|
using skipper_type = IniCommentSkipper<std::string::const_iterator>;
|
||||||
|
|
||||||
IniGrammar<std::string::const_iterator, blank_type> gramm(parIni);
|
IniGrammar<std::string::const_iterator, skipper_type> gramm(parIni);
|
||||||
IniFile::IniMapType result;
|
IniFile::IniMapType result;
|
||||||
|
|
||||||
parParseOk = false;
|
parParseOk = false;
|
||||||
|
@ -112,7 +140,7 @@ namespace kamokan {
|
||||||
start_it,
|
start_it,
|
||||||
parIni->cend(),
|
parIni->cend(),
|
||||||
gramm,
|
gramm,
|
||||||
blank,
|
skipper_type(),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -97,3 +97,35 @@ TEST_CASE ("Test parsing an ini text", "[ini][parser]") {
|
||||||
//CHECK(ini.parsed_characters() == 27);
|
//CHECK(ini.parsed_characters() == 27);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE ("Test parsing an ini with comments", "[ini][parser][comments]") {
|
||||||
|
using kamokan::IniFile;
|
||||||
|
|
||||||
|
std::string text(
|
||||||
|
"#leading comment\n"
|
||||||
|
"[section]\n"
|
||||||
|
"value = key\n"
|
||||||
|
"#this = shoul be ignored\n"
|
||||||
|
"\t#indented = comments should also be ignored\n"
|
||||||
|
"this = #should not be ignored #lol\n"
|
||||||
|
"#comment without newline"
|
||||||
|
);
|
||||||
|
const int text_len = static_cast<int>(text.size());
|
||||||
|
IniFile ini(std::move(text));
|
||||||
|
|
||||||
|
CHECK(ini.parse_success());
|
||||||
|
REQUIRE(ini.parsed_characters() == text_len);
|
||||||
|
|
||||||
|
const IniFile::IniMapType& parsed = ini.parsed();
|
||||||
|
CHECK(parsed.size() == 1);
|
||||||
|
REQUIRE_NOTHROW(parsed.at("section"));
|
||||||
|
|
||||||
|
const IniFile::KeyValueMapType& section = parsed.at("section");
|
||||||
|
REQUIRE(section.size() == 2);
|
||||||
|
REQUIRE_NOTHROW(section.at("value"));
|
||||||
|
REQUIRE_NOTHROW(section.at("this"));
|
||||||
|
CHECK_THROWS(section.at("#this"));
|
||||||
|
|
||||||
|
CHECK(section.at("value") == "key");
|
||||||
|
CHECK(section.at("this") == "#should not be ignored #lol");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue