10 #pragma warning(push, disable : 780) 12 #pragma GCC diagnostic push 13 #pragma GCC diagnostic ignored "-Wshadow" 14 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 15 #pragma GCC diagnostic ignored "-Wunused-parameter" 16 #include "boost/spirit/include/phoenix_bind.hpp" 17 #include "boost/spirit/include/phoenix_operator.hpp" 18 #include "boost/spirit/include/qi.hpp" 19 #include "boost/spirit/include/qi_no_skip.hpp" 20 #include "boost/spirit/include/support_istream_iterator.hpp" 22 #pragma clang diagnostic ignored "-Wpedantic" 24 #pragma GCC diagnostic ignored "-Wpedantic" 26 #include "boost/spirit/repository/home/qi/primitive/iter_pos.hpp" 27 #pragma GCC diagnostic pop 48 namespace ascii = ::boost::spirit::ascii;
49 namespace phx = ::boost::phoenix;
50 namespace qi = ::boost::spirit::qi;
59 using boost::spirit::repository::qi::iter_pos;
63 using namespace shims;
68 using namespace fhicl;
93 <<
"Nested item " << name <<
" has protection " 98 <<
", which is incompatible with an enclosing item's protection of " 103 std::size_t
count = 0;
105 check_element_protections(
111 if (!sname.empty()) {
124 check_element_protections(name, v.
protection, v);
133 if (m == binding_modifier::NONE) {
138 check_protection(name, v);
151 return inf[0] ==
'i' ? (
'+' + inf) : inf;
161 <<
"The string '" << num
162 <<
"' is not representable as a canonical number.";
172 <<
"The string " + str +
173 " is not representable as a canonical string.\n" 174 <<
"It is likely you have an unescaped (or incorrectly escaped) " 179 xvalue_vp(
bool const b,
value_tag const t, std::any
const v)
189 return std::make_pair(c1, c2);
198 set_protection(name, m, value);
199 auto const i = t.
find(name);
201 auto existing_protection = i->second.protection;
204 <<
"Inserting name " << name <<
" would increase protection from " 205 <<
to_string(existing_protection) <<
" to " 207 << i->second.pretty_src_info() <<
")\n";
209 switch (i->second.protection) {
210 case Protection::NONE:
212 case Protection::PROTECT_IGNORE:
215 case Protection::PROTECT_ERROR:
217 <<
'"' << name <<
"\" is protected on " << i->second.pretty_src_info()
231 map_insert(name, m, value, t);
248 auto const i = t.
find(name);
252 switch (i->second.protection) {
253 case Protection::NONE:
255 case Protection::PROTECT_IGNORE:
257 case Protection::PROTECT_ERROR:
259 <<
"Unable to erase " << name <<
" due to protection.\n";
280 template <
typename Skip>
281 struct value_parser : qi::grammar<FwdIter, extended_value(), Skip> {
282 using atom_token = qi::rule<FwdIter, atom_t(), Skip>;
283 using complex_token = qi::rule<FwdIter, complex_t(), Skip>;
284 using sequence_token = qi::rule<FwdIter, sequence_t(), Skip>;
285 using table_token = qi::rule<FwdIter, table_t(), Skip>;
286 using value_token = qi::rule<FwdIter, extended_value(), Skip>;
295 atom_token nil, boolean;
300 complex_token complex;
301 sequence_token sequence;
309 using Skip = qi::rule<iter_t>;
310 struct document_parser : qi::grammar<FwdIter, void(), Skip> {
311 using val_parser = value_parser<Skip>;
312 using atom_token = val_parser::atom_token;
313 using sequence_token = val_parser::sequence_token;
314 using table_token = val_parser::table_token;
315 using value_token = val_parser::value_token;
316 using nothing_token = qi::rule<FwdIter, void(), Skip>;
321 bool in_prolog{
false};
327 atom_token
name, qualname, noskip_qualname, localref, dbref;
328 sequence_token sequence;
331 nothing_token prolog, document;
335 local_lookup(
std::string const& name, iter_t
const pos)
try {
348 database_lookup(iter_t
const pos)
351 "Database lookup error")
353 <<
"\nFHiCL-cpp database lookup not yet available.\n";
362 <<
"key \"" << name <<
"\" does not refer to a table at " 365 auto const& incoming = std::any_cast<
table_t const&>(xval.
value);
366 for (
auto const& [name, value] : incoming) {
367 auto& element = t[
name];
370 auto const incoming_protection = value.protection;
371 if (incoming_protection > element.protection) {
373 <<
"@table::" << name <<
": inserting name " << name
374 <<
" would increase protection from " 375 <<
to_string(element.protection) <<
" to " 376 <<
to_string(incoming_protection) <<
"\n(previous definition on " 377 << element.pretty_src_info() <<
")\n";
379 switch (element.protection) {
380 case Protection::NONE:
382 case Protection::PROTECT_IGNORE:
384 case Protection::PROTECT_ERROR:
386 <<
"@table::" << name <<
": inserting name " << name
387 <<
"would violate protection on existing item" 388 <<
"\n(previous definition on " << element.pretty_src_info()
393 element.set_prolog(in_prolog);
399 insert_table(
std::string const& name, iter_t
const pos)
404 <<
"key \"" << name <<
"\" does not refer to a table at " 407 auto const& incoming = std::any_cast<
table_t const&>(xval.
value);
408 for (
auto const& [name, value] : incoming) {
409 auto element =
value;
410 element.set_prolog(in_prolog);
424 <<
"key \"" << name <<
"\" does not refer to a sequence at " 428 auto it = v.insert(v.end(), incoming.cbegin(), incoming.cend());
429 for (
auto const e = v.end(); it !=
e; ++it) {
431 it->protection = Protection::NONE;
432 it->set_prolog(in_prolog);
438 xvalue_(
value_tag const t, std::any
const v, iter_t
const pos)
446 return phx::bind(&document_parser::xvalue_,
this, t, qi::_2, qi::_1);
450 tbl_erase(
std::string const& name, iter_t
const pos)
try {
451 tbl.erase(name, in_prolog);
463 iter_t
const pos)
try {
464 set_protection(name, m, value);
465 tbl.insert(name, value);
474 set_in_prolog(
bool const value)
483 template <
class Skip>
484 value_parser<Skip>::value_parser() : value_parser::base_type{value}
489 !(
graph - char_(
",]}"))];
492 squoted = lexeme[char_(
'\'') >> *(char_ - char_(
'\'')) >> char_(
'\'') >>
493 !(
graph - char_(
",]}"))];
495 lexeme[
raw[char_(
'\"') >> *(
qi::string(
"\\\"") | (char_ - char_(
'\"'))) >>
496 char_(
'\"') >> !(
graph - char_(
",]}"))]];
498 (
fhicl::uint[_val = phx::bind(canon_num, qi::_1)] |
499 inf[_val = phx::bind(canon_inf, qi::_1)] | fhicl::real[_val = qi::_1] |
501 string = (fhicl::ass | fhicl::dss | squoted |
502 dquoted)[_val = phx::bind(canon_str, ref(qi::_1))];
503 name = fhicl::ass[_val = qi::_1];
504 complex = (
lit(
'(') > number >
lit(
',') > number >
505 lit(
')'))[_val = phx::bind(cplx, qi::_1, qi::_2)];
506 sequence =
lit(
'[') > -(value %
',') >
lit(
']');
509 *((name >> fhicl::binding >>
510 value)[phx::bind(map_insert, ref(qi::_1), qi::_2, ref(qi::_3), _val)] |
512 (
lit(
':') >
lit(
"@erase")))[phx::bind(map_erase, ref(qi::_1), _val)]) >
514 id =
lit(
"@id::") > no_skip[fhicl::dbid][_val = qi::_1];
515 catchall = shims::catchall[_val = phx::bind(canon_str, ref(qi::_1))];
516 value = (nil[_val = phx::bind(xvalue_vp,
false,
NIL, qi::_1)] |
517 boolean[_val = phx::bind(xvalue_vp,
false,
BOOL, qi::_1)] |
518 number[_val = phx::bind(xvalue_vp,
false,
NUMBER, qi::_1)] |
519 complex[_val = phx::bind(xvalue_vp,
false,
COMPLEX, qi::_1)] |
520 string[_val = phx::bind(xvalue_vp,
false,
STRING, qi::_1)] |
521 sequence[_val = phx::bind(xvalue_vp,
false,
SEQUENCE, qi::_1)] |
522 table[_val = phx::bind(xvalue_vp,
false,
TABLE, qi::_1)] |
523 id[_val = phx::bind(xvalue_vp,
false,
TABLEID, qi::_1)] |
524 catchall[_val = phx::bind(xvalue_vp,
false,
STRING, qi::_1)]);
525 nil.name(
"nil token");
526 boolean.name(
"boolean token");
527 inf.name(
"inf token");
528 squoted.name(
"squoted token");
529 dquoted.name(
"dquoted token");
530 number.name(
"number atom");
531 string.name(
"string atom");
532 name.name(
"name atom");
533 complex.name(
"complex atom");
534 sequence.name(
"sequence");
538 catchall.name(
"catchall atom");
544 : document_parser::base_type{document}, sref{s}
548 fhicl::ass[_val = qi::_1] >>
549 *((char_(
'.') > fhicl::ass)[_val += qi::_1 + qi::_2] |
551 char_(
']'))[_val += qi::_1 + qi::_2 + qi::_3]);
556 no_skip[fhicl::ass][_val = qi::_1] >>
557 *((char_(
'.') > fhicl::ass)[_val += qi::_1 + qi::_2] |
559 char_(
']'))[_val += qi::_1 + qi::_2 + qi::_3]);
563 localref =
lit(
"@local::") > noskip_qualname;
564 dbref =
lit(
"@db::") > noskip_qualname;
569 -(((value[phx::bind(seq_insert_value, ref(qi::_1), _val)]) |
570 ((iter_pos >>
lit(
"@sequence::")) >
571 noskip_qualname)[phx::bind(&document_parser::seq_insert_sequence,
577 ((value[phx::bind(seq_insert_value, ref(qi::_1), _val)]) |
578 ((iter_pos >>
lit(
"@sequence::")) >
579 noskip_qualname)[phx::bind(&document_parser::seq_insert_sequence,
583 qi::_1)])) >
lit(
']');
586 *((iter_pos >> name >> fhicl::binding >>
value)[phx::bind(&map_insert_loc,
593 (iter_pos >> name >> (
lit(
':') >
lit(
"@erase")))[phx::bind(
594 &map_erase_loc, ref(qi::_2), _val, qi::_1, sref)] |
595 ((iter_pos >>
lit(
"@table::")) >
596 noskip_qualname)[phx::bind(&document_parser::insert_table_in_table,
600 qi::_1)]) >
lit(
'}');
604 #pragma clang diagnostic push 605 #pragma clang diagnostic ignored "-Wunsequenced" 608 ((iter_pos >> vp.nil)[_val = xvalue_for(
NIL)] |
609 (iter_pos >> vp.boolean)[_val = xvalue_for(
BOOL)] |
610 (iter_pos >> vp.number)[_val = xvalue_for(
NUMBER)] |
611 (iter_pos >> vp.complex)[_val = xvalue_for(
COMPLEX)] |
612 (iter_pos >> vp.string)[_val = xvalue_for(
STRING)] |
614 localref)[_val = phx::bind(
615 &document_parser::local_lookup,
this, qi::_2, qi::_1)] |
616 (iter_pos >> dbref)[_val = phx::bind(
617 &document_parser::database_lookup,
this, qi::_1)] |
618 (iter_pos >> vp.id)[_val = xvalue_for(
TABLEID)] |
619 (iter_pos >> sequence)[_val = xvalue_for(
SEQUENCE)] |
620 (iter_pos >> table)[_val = xvalue_for(
TABLE)] |
621 (iter_pos >> vp.catchall)[_val = xvalue_for(
STRING)]);
623 #pragma clang diagnostic pop 626 lit(
"BEGIN_PROLOG")[phx::bind(
627 &document_parser::set_in_prolog,
this,
true)] >
628 *((iter_pos >> qualname >> fhicl::binding >>
629 value)[phx::bind(&document_parser::tbl_insert,
635 (iter_pos >> qualname >> (
lit(
':') >
lit(
"@erase")))[phx::bind(
636 &document_parser::tbl_erase,
this, qi::_2, qi::_1)] |
637 ((iter_pos >>
lit(
"@table::")) > noskip_qualname)[phx::bind(
638 &document_parser::insert_table,
this, qi::_2, qi::_1)]) >
640 "END_PROLOG")[phx::bind(&document_parser::set_in_prolog,
this,
false)];
641 document = (*prolog) >>
642 *((iter_pos >> qualname >> fhicl::binding >>
643 value)[phx::bind(&document_parser::tbl_insert,
649 (iter_pos >> qualname >> (
lit(
':') >
lit(
"@erase")))[phx::bind(
650 &document_parser::tbl_erase,
this, qi::_2, qi::_1)] |
651 ((iter_pos >>
lit(
"@table::")) > noskip_qualname)[phx::bind(
652 &document_parser::insert_table,
this, qi::_2, qi::_1)]);
653 name.name(
"name atom");
654 localref.name(
"localref atom");
655 dbref.name(
"dbref atom");
656 qualname.name(
"qualified name");
657 noskip_qualname.name(
"qualified name (no pre-skip)");
658 sequence.name(
"sequence");
661 prolog.name(
"prolog");
662 document.name(
"document");
673 using ws_t = qi::rule<FwdIter>;
674 ws_t whitespace = space |
lit(
'#') >> *(char_ -
eol) >>
eol |
676 value_parser<ws_t>
p;
677 auto begin = s.begin();
678 auto const end = s.end();
680 qi::phrase_parse(
begin,
end, p >> *whitespace, whitespace, result) &&
692 qi::rule<iter_t> whitespace = space |
lit(
'#') >> *(char_ -
eol) >>
eol |
694 document_parser
p(s);
699 b = qi::phrase_parse(
begin,
end, p, whitespace);
701 catch (qi::expectation_failure<iter_t>
const&
e) {
705 if (b && unparsed.empty()) {
712 if (unparsed.find(
"BEGIN_PROLOG"s) == 0ull) {
713 e <<
"PROLOG blocks must be both contiguous and not nested.\n";
734 std::istringstream is{s};
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
intermediate_table::complex_t complex_t
size_t erase(Key const &key)
const_iterator end() const
bool parse_value_string(std::string const &s, extended_value &v, std::string &unparsed)
bool canonical_number(std::string const &value, std::string &result)
std::string dquoted(std::string const &s)
bool is_a(value_tag const t) const noexcept
def graph(desc, maker=maker)
const_iterator begin() const
QTextStream & hex(QTextStream &s)
std::string highlighted_whereis(const_iterator const &it) const
int find(char c, int index=0, bool cs=TRUE) const
std::string src_whereis(const_iterator const &it) const
void set_src_info(std::string const &src)
static int max(int a, int b)
static std::string canon_nil()
extended_value::table_t table_t
fhicl::extended_value::sequence_t sequence_t
intermediate_table::atom_t atom_t
extended_value::atom_t atom_t
bool canonical_string(std::string const &str, std::string &result)
std::string squoted(std::string const &s)
intermediate_table parse_document(std::string const &filename, cet::filepath_maker &maker)
QTextStream & bin(QTextStream &s)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
std::string pretty_src_info() const
extended_value::complex_t complex_t
std::string::const_iterator const_iterator
def maker(G, ac, typename)
void set_prolog(bool new_prolog_state)
iterator find(Key const &key)
std::string to_string(ModuleType const mt)
cet::coded_exception< error, detail::translate > exception
extended_value::sequence_t sequence_t