LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
parse.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // parse
4 //
5 // ======================================================================
6 
7 #include "fhiclcpp/parse.h"
8 
9 #include "boost/phoenix/bind.hpp"
10 #include "boost/phoenix/operator.hpp"
11 #include "boost/spirit/include/qi.hpp"
12 #include "boost/spirit/include/qi_no_skip.hpp"
13 #include "boost/spirit/include/support_istream_iterator.hpp"
14 #include "boost/spirit/repository/home/qi/primitive/iter_pos.hpp"
15 
16 #include "cetlib/canonical_number.h"
17 #include "cetlib/canonical_string.h"
18 #include "cetlib/include.h"
19 #include "cetlib/includer.h"
21 #include "fhiclcpp/exception.h"
24 #include "fhiclcpp/parse_shims.h"
25 #include "fhiclcpp/tokens.h"
26 
27 #include <algorithm>
28 #include <any>
29 #include <string>
30 #include <vector>
31 
32 namespace ascii = ::boost::spirit::ascii;
33 namespace phx = ::boost::phoenix;
34 namespace qi = ::boost::spirit::qi;
35 
36 using ascii::char_;
37 using ascii::digit;
38 using ascii::graph;
39 using ascii::space;
40 
41 using phx::ref;
42 
43 using boost::spirit::repository::qi::iter_pos;
44 using qi::_val;
45 using qi::eol;
46 using qi::lexeme;
47 using namespace shims; // using qi::lit; /*moved to parse_shims.h*/
48 using qi::no_skip;
49 using qi::raw;
50 using qi::skip;
51 
52 using namespace fhicl;
58 
59 using fhicl::SEQUENCE;
60 using fhicl::TABLE;
61 using fhicl::TABLEID;
62 
63 // ----------------------------------------------------------------------
64 
65 namespace {
66 
67  void
68  check_element_protections(std::string const& name,
69  Protection const p,
70  extended_value& v)
71  {
72  using std::max;
73  if (v.protection == Protection::NONE) {
74  v.protection = p;
75  } else if (v.protection < p) {
77  << "Nested item " << name << " has protection "
78  << to_string(v.protection)
79  << ((!v.src_info.empty()) ?
80  (std::string(" on ") + v.pretty_src_info()) :
81  "")
82  << ", which is incompatible with an enclosing item's protection of "
83  << to_string(p) << "\n";
84  }
85 
86  if (v.tag == fhicl::SEQUENCE) {
87  std::size_t count = 0;
88  for (auto& subv : sequence_t(v)) {
89  check_element_protections(
90  name + '[' + std::to_string(count) + ']', max(p, v.protection), subv);
91  }
92  } else if (v.tag == fhicl::TABLE) {
93  for (auto& [key, value] : table_t(v)) {
94  std::string sname(name);
95  if (!sname.empty()) {
96  sname.append(".");
97  }
98  sname.append(key);
99  check_element_protections(sname, max(p, v.protection), value);
100  }
101  }
102  }
103 
104  void
105  check_protection(std::string const& name, extended_value& v)
106  {
107  if (v.is_a(SEQUENCE) || v.is_a(TABLE)) {
108  check_element_protections(name, v.protection, v);
109  }
110  }
111 
112  void
113  set_protection(std::string const& name,
114  binding_modifier const m,
115  extended_value& v)
116  {
117  if (m == binding_modifier::NONE) {
118  return;
119  }
120 
121  v.protection = static_cast<Protection>(m);
122  check_protection(name, v);
123  }
124 
125  std::string
126  canon_nil()
127  {
128  static std::string const canon_nil(9, '\0');
129  return canon_nil;
130  }
131 
132  std::string
133  canon_inf(std::string const& inf)
134  {
135  return inf[0] == 'i' ? ('+' + inf) : inf;
136  }
137 
138  std::string
139  canon_num(std::string const& num)
140  {
141  std::string result;
142  return cet::canonical_number(num, result) ?
143  result :
145  << "The string '" << num
146  << "' is not representable as a canonical number.";
147  }
148 
149  std::string
150  canon_str(std::string const& str)
151  {
152  std::string result;
153  return cet::canonical_string(str, result) ?
154  result :
156  << "The string " + str +
157  " is not representable as a canonical string.\n"
158  << "It is likely you have an unescaped (or incorrectly escaped) "
159  "character.";
160  }
161 
163  xvalue_vp(bool const b, value_tag const t, std::any const v)
164  {
165  return extended_value{b, t, v};
166  }
167 
168  using iter_t = cet::includer::const_iterator;
169 
170  complex_t
171  cplx(atom_t const& c1, atom_t const& c2)
172  {
173  return std::make_pair(c1, c2);
174  }
175 
176  void
177  map_insert(std::string const& name,
178  binding_modifier const m,
180  table_t& t)
181  {
182  set_protection(name, m, value);
183  auto const i = t.find(name);
184  if (i != t.end()) {
185  auto existing_protection = i->second.protection;
186  if (value.protection > existing_protection) {
188  << "Inserting name " << name << " would increase protection from "
189  << to_string(existing_protection) << " to "
190  << to_string(value.protection) << "\n(previous definition on "
191  << i->second.pretty_src_info() << ")\n";
192  }
193  switch (i->second.protection) {
194  case Protection::NONE:
195  break;
196  case Protection::PROTECT_IGNORE:
197  // Do not overwrite protected binding.
198  return;
199  case Protection::PROTECT_ERROR:
201  << '"' << name << "\" is protected on " << i->second.pretty_src_info()
202  << '\n';
203  }
204  }
205  t[name] = value;
206  }
207 
208  void
209  map_insert_loc(std::string const& name,
210  binding_modifier const m,
211  extended_value& value,
212  table_t& t,
213  iter_t const pos,
214  cet::includer const& s)
215  try {
216  map_insert(name, m, value, t);
217  }
218  catch (fhicl::exception& e) {
219  throw fhicl::exception(fhicl::error::parse_error, "Error in assignment:", e)
220  << " at " << s.highlighted_whereis(pos) << '\n';
221  }
222 
223  void
224  seq_insert_value(extended_value xval, sequence_t& v)
225  {
226  xval.protection = Protection::NONE;
227  v.emplace_back(std::move(xval));
228  }
229 
230  void
231  map_erase(std::string const& name, table_t& t)
232  {
233  auto const i = t.find(name);
234  if (i == t.end())
235  return;
236 
237  switch (i->second.protection) {
238  case Protection::NONE:
239  t.erase(name);
240  case Protection::PROTECT_IGNORE:
241  return;
242  case Protection::PROTECT_ERROR:
244  << "Unable to erase " << name << " due to protection.\n";
245  }
246  }
247 
248  void
249  map_erase_loc(std::string const& name,
250  table_t& t,
251  iter_t const pos,
252  cet::includer const& s)
253  try {
254  map_erase(name, t);
255  }
256  catch (fhicl::exception& e) {
257  throw fhicl::exception(
258  fhicl::error::parse_error, "Error in erase attempt:", e)
259  << " at " << s.highlighted_whereis(pos) << '\n';
260  }
261 
262  // ----------------------------------------------------------------------
263 
264  using FwdIter = std::string::const_iterator;
265 
266  template <typename Skip>
267  struct value_parser : qi::grammar<FwdIter, extended_value(), Skip> {
268  using atom_token = qi::rule<FwdIter, atom_t(), Skip>;
269  using complex_token = qi::rule<FwdIter, complex_t(), Skip>;
270  using sequence_token = qi::rule<FwdIter, sequence_t(), Skip>;
271  using table_token = qi::rule<FwdIter, table_t(), Skip>;
272  using value_token = qi::rule<FwdIter, extended_value(), Skip>;
273 
274  // default c'tor:
275  value_parser();
276 
277  // data member:
278  extended_value v{};
279 
280  // parser rules:
281  atom_token nil, boolean;
282  atom_token inf;
283  atom_token squoted, dquoted;
284  atom_token number, string, name, catchall;
285  atom_token id;
286  complex_token complex;
287  sequence_token sequence;
288  table_token table;
289  value_token value;
290 
291  }; // value_parser
292 
293  // ----------------------------------------------------------------------
294 
295  using Skip = qi::rule<iter_t>;
296  struct document_parser : qi::grammar<FwdIter, void(), Skip> {
297  using val_parser = value_parser<Skip>;
298  using atom_token = val_parser::atom_token;
299  using sequence_token = val_parser::sequence_token;
300  using table_token = val_parser::table_token;
301  using value_token = val_parser::value_token;
302  using nothing_token = qi::rule<FwdIter, void(), Skip>;
303 
304  explicit document_parser(cet::includer const& s);
305 
306  // data members:
307  bool in_prolog{false};
308  intermediate_table tbl{};
309  val_parser vp{};
310  cet::includer const& sref;
311 
312  // parser rules:
313  atom_token name, qualname, noskip_qualname, localref, dbref;
314  sequence_token sequence;
315  table_token table;
316  value_token value;
317  nothing_token prolog, document;
318 
319  private:
321  local_lookup(std::string const& name, iter_t const pos)
322  try {
323  extended_value result = tbl.find(name);
324  result.set_prolog(in_prolog);
325  result.set_src_info(sref.src_whereis(pos));
326  result.reset_protection();
327  return result;
328  }
329  catch (fhicl::exception const& e) {
330  throw fhicl::exception(fhicl::error::parse_error, "Local lookup error", e)
331  << "at " << sref.highlighted_whereis(pos) << "\n";
332  }
333 
335  database_lookup(iter_t const pos)
336  {
338  "Database lookup error")
339  << "at " << sref.highlighted_whereis(pos)
340  << "\nFHiCL-cpp database lookup not yet available.\n";
341  }
342 
343  void
344  insert_table_in_table(std::string const& name, table_t& t, iter_t const pos)
345  {
346  extended_value const xval = local_lookup(name, pos);
347  if (!xval.is_a(fhicl::TABLE)) {
349  << "key \"" << name << "\" does not refer to a table at "
350  << sref.highlighted_whereis(pos) << "\n";
351  }
352  auto const& incoming = std::any_cast<table_t const&>(xval.value);
353  for (auto const& [name, value] : incoming) {
354  auto& element = t[name];
355  if (!element.is_a(fhicl::UNKNOWN)) {
356  // Already exists.
357  auto const incoming_protection = value.protection;
358  if (incoming_protection > element.protection) {
360  << "@table::" << name << ": inserting name " << name
361  << " would increase protection from "
362  << to_string(element.protection) << " to "
363  << to_string(incoming_protection) << "\n(previous definition on "
364  << element.pretty_src_info() << ")\n";
365  }
366  switch (element.protection) {
367  case Protection::NONE:
368  break;
369  case Protection::PROTECT_IGNORE:
370  continue;
371  case Protection::PROTECT_ERROR:
373  << "@table::" << name << ": inserting name " << name
374  << "would violate protection on existing item"
375  << "\n(previous definition on " << element.pretty_src_info()
376  << ")\n";
377  }
378  }
379  element = value;
380  element.set_prolog(in_prolog);
381  element.set_src_info(sref.src_whereis(pos));
382  }
383  }
384 
385  void
386  insert_table(std::string const& name, iter_t const pos)
387  {
388  extended_value const xval = local_lookup(name, pos);
389  if (!xval.is_a(fhicl::TABLE)) {
391  << "key \"" << name << "\" does not refer to a table at "
392  << sref.highlighted_whereis(pos) << "\n";
393  }
394  auto const& incoming = std::any_cast<table_t const&>(xval.value);
395  for (auto const& [name, value] : incoming) {
396  auto element = value;
397  element.set_prolog(in_prolog);
398  element.set_src_info(sref.src_whereis(pos));
399  tbl.insert(name, std::move(element));
400  }
401  }
402 
403  void
404  seq_insert_sequence(std::string const& name,
405  sequence_t& v,
406  iter_t const pos)
407  {
408  extended_value const xval = local_lookup(name, pos);
409  if (!xval.is_a(fhicl::SEQUENCE)) {
410  throw fhicl::exception(fhicl::error::type_mismatch, "@sequence::")
411  << "key \"" << name << "\" does not refer to a sequence at "
412  << sref.highlighted_whereis(pos) << "\n";
413  }
414  auto const& incoming = std::any_cast<sequence_t const&>(xval.value);
415  auto it = v.insert(v.end(), incoming.cbegin(), incoming.cend());
416  for (auto const e = v.end(); it != e; ++it) {
417  using std::to_string;
418  it->protection = Protection::NONE;
419  it->set_prolog(in_prolog);
420  it->set_src_info(sref.src_whereis(pos));
421  }
422  }
423 
425  xvalue_(value_tag const t, std::any const v, iter_t const pos)
426  {
427  return extended_value{in_prolog, t, v, sref.src_whereis(pos)};
428  }
429 
430  auto
431  xvalue_for(value_tag const t)
432  {
433  return phx::bind(&document_parser::xvalue_, this, t, qi::_2, qi::_1);
434  }
435 
436  void
437  tbl_erase(std::string const& name, iter_t const pos)
438  try {
439  tbl.erase(name, in_prolog);
440  }
441  catch (fhicl::exception& e) {
442  throw fhicl::exception(
443  fhicl::error::parse_error, "Error in erase attempt:", e)
444  << " at " << sref.highlighted_whereis(pos) << '\n';
445  }
446 
447  void
448  tbl_insert(std::string const& name,
449  binding_modifier const m,
450  extended_value& value,
451  iter_t const pos)
452  try {
453  set_protection(name, m, value);
454  tbl.insert(name, value);
455  }
456  catch (fhicl::exception& e) {
457  throw fhicl::exception(
458  fhicl::error::parse_error, "Error in assignment:", e)
459  << " at " << sref.highlighted_whereis(pos) << '\n';
460  }
461 
462  void
463  set_in_prolog(bool const value)
464  {
465  in_prolog = value;
466  }
467 
468  }; // document_parser
469 
470  // ----------------------------------------------------------------------
471 
472  template <class Skip>
473  value_parser<Skip>::value_parser() : value_parser::base_type{value}
474  {
475  nil = lexeme[(qi::string("@nil") >>
476  !(graph - char_(",]}")))[_val = phx::bind(canon_nil)]];
477  boolean = lexeme[(qi::string("true") | qi::string("false")) >>
478  !(graph - char_(",]}"))];
479  inf = lexeme[-(qi::string("+") | qi::string("-")) >>
480  qi::string("infinity") >> !(graph - char_("),]}"))];
481  squoted = lexeme[char_('\'') >> *(char_ - char_('\'')) >> char_('\'') >>
482  !(graph - char_(",]}"))];
483  dquoted =
484  lexeme[raw[char_('\"') >> *(qi::string("\\\"") | (char_ - char_('\"'))) >>
485  char_('\"') >> !(graph - char_(",]}"))]];
486  number =
487  (fhicl::uint[_val = phx::bind(canon_num, qi::_1)] |
488  inf[_val = phx::bind(canon_inf, qi::_1)] | fhicl::real[_val = qi::_1] |
489  fhicl::hex[_val = qi::_1] | fhicl::bin[_val = qi::_1]);
490  string = (fhicl::ass | fhicl::dss | squoted |
491  dquoted)[_val = phx::bind(canon_str, ref(qi::_1))];
492  name = fhicl::ass[_val = qi::_1];
493  complex = (lit('(') > number > lit(',') > number >
494  lit(')'))[_val = phx::bind(cplx, qi::_1, qi::_2)];
495  sequence = lit('[') > -(value % ',') > lit(']');
496  table =
497  lit('{') >
498  *((name >> fhicl::binding >>
499  value)[phx::bind(map_insert, ref(qi::_1), qi::_2, ref(qi::_3), _val)] |
500  (name >>
501  (lit(':') > lit("@erase")))[phx::bind(map_erase, ref(qi::_1), _val)]) >
502  lit('}');
503  id = lit("@id::") > no_skip[fhicl::dbid][_val = qi::_1];
504  catchall = shims::catchall[_val = phx::bind(canon_str, ref(qi::_1))];
505  value = (nil[_val = phx::bind(xvalue_vp, false, NIL, qi::_1)] |
506  boolean[_val = phx::bind(xvalue_vp, false, BOOL, qi::_1)] |
507  number[_val = phx::bind(xvalue_vp, false, NUMBER, qi::_1)] |
508  complex[_val = phx::bind(xvalue_vp, false, COMPLEX, qi::_1)] |
509  string[_val = phx::bind(xvalue_vp, false, STRING, qi::_1)] |
510  sequence[_val = phx::bind(xvalue_vp, false, SEQUENCE, qi::_1)] |
511  table[_val = phx::bind(xvalue_vp, false, TABLE, qi::_1)] |
512  id[_val = phx::bind(xvalue_vp, false, TABLEID, qi::_1)] |
513  catchall[_val = phx::bind(xvalue_vp, false, STRING, qi::_1)]);
514  nil.name("nil token");
515  boolean.name("boolean token");
516  inf.name("inf token");
517  squoted.name("squoted token");
518  dquoted.name("dquoted token");
519  number.name("number atom");
520  string.name("string atom");
521  name.name("name atom");
522  complex.name("complex atom");
523  sequence.name("sequence");
524  table.name("table");
525  id.name("id atom");
526  value.name("value");
527  catchall.name("catchall atom");
528  } // value_parser c'tor
529 
530  // ----------------------------------------------------------------------
531 
532  document_parser::document_parser(cet::includer const& s)
533  : document_parser::base_type{document}, sref{s}
534  {
535  name = fhicl::ass;
536  qualname =
537  fhicl::ass[_val = qi::_1] >>
538  *((char_('.') > fhicl::ass)[_val += qi::_1 + qi::_2] |
539  (char_('[') > fhicl::uint >
540  char_(']'))[_val += qi::_1 + qi::_2 + qi::_3]); // Whitespace permitted
541  // before, and around
542  // delimiters ( '.',
543  // '[', ']').
544  noskip_qualname =
545  no_skip[fhicl::ass][_val = qi::_1] >>
546  *((char_('.') > fhicl::ass)[_val += qi::_1 + qi::_2] |
547  (char_('[') > fhicl::uint >
548  char_(']'))[_val += qi::_1 + qi::_2 + qi::_3]); // Whitespace permitted
549  // around delimiters
550  // ('.', '[', ']')
551  // only.
552  localref = lit("@local::") > noskip_qualname;
553  dbref = lit("@db::") > noskip_qualname;
554  // Can't use simple, "list context" due to the possibility of one of
555  // the list elements actually returning multiple elements.
556  sequence =
557  lit('[') >
558  -(((value[phx::bind(seq_insert_value, ref(qi::_1), _val)]) |
559  ((iter_pos >> lit("@sequence::")) >
560  noskip_qualname)[phx::bind(&document_parser::seq_insert_sequence,
561  this,
562  ref(qi::_2),
563  _val,
564  qi::_1)])) >
565  *(lit(',') >
566  ((value[phx::bind(seq_insert_value, ref(qi::_1), _val)]) |
567  ((iter_pos >> lit("@sequence::")) >
568  noskip_qualname)[phx::bind(&document_parser::seq_insert_sequence,
569  this,
570  ref(qi::_2),
571  _val,
572  qi::_1)])) > lit(']');
573  table =
574  lit('{') >
575  *((iter_pos >> name >> fhicl::binding >> value)[phx::bind(&map_insert_loc,
576  ref(qi::_2),
577  qi::_3,
578  ref(qi::_4),
579  _val,
580  qi::_1,
581  sref)] |
582  (iter_pos >> name >> (lit(':') > lit("@erase")))[phx::bind(
583  &map_erase_loc, ref(qi::_2), _val, qi::_1, sref)] |
584  ((iter_pos >> lit("@table::")) >
585  noskip_qualname)[phx::bind(&document_parser::insert_table_in_table,
586  this,
587  ref(qi::_2),
588  _val,
589  qi::_1)]) > lit('}');
590  // Clang does not like this (multiple unsequenced modifications to '_val'
591  // [-Werror,-Wunsequenced]) TEMPORARILY wrap until validity checked
592 #ifdef __clang__
593 #pragma clang diagnostic push
594 #pragma clang diagnostic ignored "-Wunsequenced"
595 #endif
596  value =
597  ((iter_pos >> vp.nil)[_val = xvalue_for(NIL)] |
598  (iter_pos >> vp.boolean)[_val = xvalue_for(BOOL)] |
599  (iter_pos >> vp.number)[_val = xvalue_for(NUMBER)] |
600  (iter_pos >> vp.complex)[_val = xvalue_for(COMPLEX)] |
601  (iter_pos >> vp.string)[_val = xvalue_for(STRING)] |
602  (iter_pos >>
603  localref)[_val = phx::bind(
604  &document_parser::local_lookup, this, qi::_2, qi::_1)] |
605  (iter_pos >> dbref)[_val = phx::bind(
606  &document_parser::database_lookup, this, qi::_1)] |
607  (iter_pos >> vp.id)[_val = xvalue_for(TABLEID)] |
608  (iter_pos >> sequence)[_val = xvalue_for(SEQUENCE)] |
609  (iter_pos >> table)[_val = xvalue_for(TABLE)] |
610  (iter_pos >> vp.catchall)[_val = xvalue_for(STRING)]);
611 #ifdef __clang__
612 #pragma clang diagnostic pop
613 #endif
614  prolog =
615  lit("BEGIN_PROLOG")[phx::bind(
616  &document_parser::set_in_prolog, this, true)] >
617  *((iter_pos >> qualname >> fhicl::binding >>
618  value)[phx::bind(&document_parser::tbl_insert,
619  this,
620  ref(qi::_2),
621  qi::_3,
622  ref(qi::_4),
623  qi::_1)] |
624  (iter_pos >> qualname >> (lit(':') > lit("@erase")))[phx::bind(
625  &document_parser::tbl_erase, this, qi::_2, qi::_1)] |
626  ((iter_pos >> lit("@table::")) > noskip_qualname)[phx::bind(
627  &document_parser::insert_table, this, qi::_2, qi::_1)]) >
628  lit(
629  "END_PROLOG")[phx::bind(&document_parser::set_in_prolog, this, false)];
630  document = (*prolog) >>
631  *((iter_pos >> qualname >> fhicl::binding >>
632  value)[phx::bind(&document_parser::tbl_insert,
633  this,
634  ref(qi::_2),
635  qi::_3,
636  ref(qi::_4),
637  qi::_1)] |
638  (iter_pos >> qualname >> (lit(':') > lit("@erase")))[phx::bind(
639  &document_parser::tbl_erase, this, qi::_2, qi::_1)] |
640  ((iter_pos >> lit("@table::")) > noskip_qualname)[phx::bind(
641  &document_parser::insert_table, this, qi::_2, qi::_1)]);
642  name.name("name atom");
643  localref.name("localref atom");
644  dbref.name("dbref atom");
645  qualname.name("qualified name");
646  noskip_qualname.name("qualified name (no pre-skip)");
647  sequence.name("sequence");
648  table.name("table");
649  value.name("value");
650  prolog.name("prolog");
651  document.name("document");
652  } // document_parser c'tor
653 }
654 
655 // ----------------------------------------------------------------------
656 
657 bool
658 fhicl::parse_value_string(std::string const& s,
659  extended_value& result,
660  std::string& unparsed)
661 {
662  using ws_t = qi::rule<FwdIter>;
663  ws_t whitespace = space | lit('#') >> *(char_ - eol) >> eol |
664  lit("//") >> *(char_ - eol) >> eol;
665  value_parser<ws_t> p;
666  auto begin = s.begin();
667  auto const end = s.end();
668  bool const b =
669  qi::phrase_parse(begin, end, p >> *whitespace, whitespace, result) &&
670  begin == end;
671  unparsed = std::string(begin, end);
672  return b;
673 } // parse_value_string()
674 
675 // ----------------------------------------------------------------------
676 
677 namespace {
679  parse_document_(cet::includer s)
680  {
681  qi::rule<iter_t> whitespace = space | lit('#') >> *(char_ - eol) >> eol |
682  lit("//") >> *(char_ - eol) >> eol;
683  document_parser p(s);
684  auto begin = s.begin();
685  auto const end = s.end();
686  bool b = false;
687  try {
688  b = qi::phrase_parse(begin, end, p, whitespace);
689  }
690  catch (qi::expectation_failure<iter_t> const& e) {
691  begin = e.first;
692  }
693  std::string const unparsed(begin, end);
694  if (b && unparsed.empty()) {
695  return std::move(p.tbl);
696  }
697 
698  auto e = fhicl::exception(fhicl::parse_error, "detected at or near")
699  << s.highlighted_whereis(begin) << "\n";
700  using namespace std::string_literals;
701  if (unparsed.find("BEGIN_PROLOG"s) == 0ull) {
702  e << "PROLOG blocks must be both contiguous and not nested.\n";
703  }
704  throw e;
705  }
706 }
707 
709 fhicl::parse_document(std::string const& filename, cet::filepath_maker& maker)
710 {
711  return parse_document_(cet::includer{filename, maker});
712 }
713 
715 fhicl::parse_document(std::istream& is, cet::filepath_maker& maker)
716 {
717  return parse_document_(cet::includer(is, maker));
718 }
719 
721 fhicl::parse_document(std::string const& s)
722 {
723  std::istringstream is{s};
724  cet::filepath_maker m;
725  return parse_document(is, m);
726 }
727 
728 // ======================================================================
iterator end() noexcept
Definition: stdmap_shims.h:183
intermediate_table::complex_t complex_t
size_t erase(Key const &key)
Definition: stdmap_shims.h:264
bool parse_value_string(std::string const &s, extended_value &v, std::string &unparsed)
Definition: parse.cc:658
bool is_a(value_tag const t) const noexcept
intermediate_table::const_iterator const_iterator
Raw data description.
Definition: RawTypes.h:6
auto lit(char arg)
Definition: parse_shims.h:11
Protection
Definition: Protection.h:7
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
TCanvas * c1
Definition: plotHisto.C:7
TCanvas * c2
Definition: plot_hist.C:75
void set_src_info(std::string const &src)
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
parameter set interface
static std::string canon_nil()
Definition: coding.cc:30
float bin[41]
Definition: plottest35.C:14
extended_value::table_t table_t
Definition: parse.cc:57
double value
Definition: spectrum.C:18
fhicl::extended_value::sequence_t sequence_t
intermediate_table::atom_t atom_t
extended_value::atom_t atom_t
Definition: parse.cc:54
intermediate_table parse_document(std::string const &filename, cet::filepath_maker &maker)
Definition: parse.cc:709
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
std::string pretty_src_info() const
extended_value::complex_t complex_t
Definition: parse.cc:55
Float_t e
Definition: plot.C:35
void set_prolog(bool new_prolog_state)
iterator find(Key const &key)
Definition: stdmap_shims.h:236
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
extended_value::sequence_t sequence_t
Definition: parse.cc:56