printing.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. #ifndef BOOST_PARSER_DETAIL_PRINTING_HPP
  2. #define BOOST_PARSER_DETAIL_PRINTING_HPP
  3. #include <boost/parser/parser_fwd.hpp>
  4. #include <boost/parser/tuple.hpp>
  5. #include <boost/parser/detail/detection.hpp>
  6. #include <boost/parser/detail/hl.hpp>
  7. #include <boost/parser/detail/text/unpack.hpp>
  8. #if defined(_MSC_VER) && defined(BOOST_PARSER_TRACE_TO_VS_OUTPUT)
  9. #include <boost/parser/detail/vs_output_stream.hpp>
  10. #endif
  11. #include <boost/parser/detail/text/transcode_view.hpp>
  12. #include <iomanip>
  13. #include <iostream>
  14. #include <optional>
  15. #include <sstream>
  16. #include <string>
  17. #include <variant>
  18. #include <cctype>
  19. namespace boost { namespace parser { namespace detail {
  20. template<typename Context>
  21. decltype(auto) _indent(Context const & context);
  22. template<typename Char>
  23. std::ostream & print_char(std::ostream & os, Char c)
  24. {
  25. if constexpr (
  26. #if defined(__cpp_char8_t)
  27. std::is_same_v<
  28. char8_t,
  29. std::remove_cv_t<std::remove_reference_t<Char>>>
  30. #else
  31. false
  32. #endif
  33. ) {
  34. os << char(c);
  35. } else {
  36. os << c;
  37. }
  38. return os;
  39. }
  40. enum { parser_component_limit = 4 };
  41. template<
  42. typename Context,
  43. typename Parser,
  44. typename DelimiterParser,
  45. typename MinType,
  46. typename MaxType>
  47. void print_parser(
  48. Context const & context,
  49. repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
  50. std::ostream & os,
  51. int components = 0);
  52. template<typename Context, typename Parser>
  53. void print_parser(
  54. Context const & context,
  55. opt_parser<Parser> const & parser,
  56. std::ostream & os,
  57. int components = 0);
  58. template<typename Context, typename ParserTuple>
  59. void print_parser(
  60. Context const & context,
  61. or_parser<ParserTuple> const & parser,
  62. std::ostream & os,
  63. int components = 0);
  64. template<typename Context, typename ParserTuple, typename DelimiterParser>
  65. void print_parser(
  66. Context const & context,
  67. perm_parser<ParserTuple, DelimiterParser> const & parser,
  68. std::ostream & os,
  69. int components = 0);
  70. template<
  71. typename Context,
  72. typename ParserTuple,
  73. typename BacktrackingTuple,
  74. typename CombiningGroups>
  75. void print_parser(
  76. Context const & context,
  77. seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
  78. parser,
  79. std::ostream & os,
  80. int components = 0);
  81. template<typename Context, typename Parser, typename Action>
  82. void print_parser(
  83. Context const & context,
  84. action_parser<Parser, Action> const & parser,
  85. std::ostream & os,
  86. int components = 0);
  87. template<typename Context, typename Parser, typename F>
  88. void print_parser(
  89. Context const & context,
  90. transform_parser<Parser, F> const & parser,
  91. std::ostream & os,
  92. int components = 0);
  93. template<typename Context, typename Parser>
  94. void print_parser(
  95. Context const & context,
  96. omit_parser<Parser> const & parser,
  97. std::ostream & os,
  98. int components = 0);
  99. template<typename Context, typename Parser>
  100. void print_parser(
  101. Context const & context,
  102. raw_parser<Parser> const & parser,
  103. std::ostream & os,
  104. int components = 0);
  105. #if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
  106. template<typename Context, typename Parser>
  107. void print_parser(
  108. Context const & context,
  109. string_view_parser<Parser> const & parser,
  110. std::ostream & os,
  111. int components = 0);
  112. #endif
  113. template<typename Context, typename Parser>
  114. void print_parser(
  115. Context const & context,
  116. lexeme_parser<Parser> const & parser,
  117. std::ostream & os,
  118. int components = 0);
  119. template<typename Context, typename Parser>
  120. void print_parser(
  121. Context const & context,
  122. no_case_parser<Parser> const & parser,
  123. std::ostream & os,
  124. int components = 0);
  125. template<typename Context, typename Parser, typename SkipParser>
  126. void print_parser(
  127. Context const & context,
  128. skip_parser<Parser, SkipParser> const & parser,
  129. std::ostream & os,
  130. int components = 0);
  131. template<typename Context, typename Parser, bool FailOnMatch>
  132. void print_parser(
  133. Context const & context,
  134. expect_parser<Parser, FailOnMatch> const & parser,
  135. std::ostream & os,
  136. int components = 0);
  137. template<
  138. typename Context,
  139. bool UseCallbacks,
  140. typename Parser,
  141. typename Attribute,
  142. typename LocalState,
  143. typename ParamsTuple>
  144. void print_parser(
  145. Context const & context,
  146. rule_parser<
  147. UseCallbacks,
  148. Parser,
  149. Attribute,
  150. LocalState,
  151. ParamsTuple> const & parser,
  152. std::ostream & os,
  153. int components = 0);
  154. template<typename Context, typename T>
  155. void print_parser(
  156. Context const & context,
  157. symbol_parser<T> const & parser,
  158. std::ostream & os,
  159. int components = 0);
  160. template<typename Context, typename Predicate>
  161. void print_parser(
  162. Context const & context,
  163. eps_parser<Predicate> const & parser,
  164. std::ostream & os,
  165. int components = 0);
  166. template<typename Context>
  167. void print_parser(
  168. Context const & context,
  169. eps_parser<nope> const & parser,
  170. std::ostream & os,
  171. int components = 0);
  172. template<typename Context>
  173. void print_parser(
  174. Context const & context,
  175. eoi_parser const & parser,
  176. std::ostream & os,
  177. int components = 0);
  178. template<typename Context, typename Atribute>
  179. void print_parser(
  180. Context const & context,
  181. attr_parser<Atribute> const & parser,
  182. std::ostream & os,
  183. int components = 0);
  184. template<typename Context, typename Expected, typename AttributeType>
  185. void print_parser(
  186. Context const & context,
  187. char_parser<Expected, AttributeType> const & parser,
  188. std::ostream & os,
  189. int components = 0);
  190. template<typename Context>
  191. void print_parser(
  192. Context const & context,
  193. digit_parser const & parser,
  194. std::ostream & os,
  195. int components = 0);
  196. template<typename Context>
  197. void print_parser(
  198. Context const & context,
  199. char_subrange_parser<hex_digit_subranges> const & parser,
  200. std::ostream & os,
  201. int components = 0);
  202. template<typename Context>
  203. void print_parser(
  204. Context const & context,
  205. char_subrange_parser<control_subranges> const & parser,
  206. std::ostream & os,
  207. int components = 0);
  208. template<typename Context>
  209. void print_parser(
  210. Context const & context,
  211. char_set_parser<punct_chars> const & parser,
  212. std::ostream & os,
  213. int components = 0);
  214. template<typename Context>
  215. void print_parser(
  216. Context const & context,
  217. char_set_parser<symb_chars> const & parser,
  218. std::ostream & os,
  219. int components = 0);
  220. template<typename Context>
  221. void print_parser(
  222. Context const & context,
  223. char_set_parser<lower_case_chars> const & parser,
  224. std::ostream & os,
  225. int components = 0);
  226. template<typename Context>
  227. void print_parser(
  228. Context const & context,
  229. char_set_parser<upper_case_chars> const & parser,
  230. std::ostream & os,
  231. int components = 0);
  232. template<typename Context, typename Expected, typename AttributeType>
  233. void print_parser(
  234. Context const & context,
  235. omit_parser<char_parser<Expected, AttributeType>> const & parser,
  236. std::ostream & os,
  237. int components = 0);
  238. template<typename Context, typename StrIter, typename StrSentinel>
  239. void print_parser(
  240. Context const & context,
  241. string_parser<StrIter, StrSentinel> const & parser,
  242. std::ostream & os,
  243. int components = 0);
  244. template<typename Context, typename StrIter, typename StrSentinel>
  245. void print_parser(
  246. Context const & context,
  247. omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
  248. std::ostream & os,
  249. int components = 0);
  250. template<
  251. typename Context,
  252. typename Quotes,
  253. typename Escapes,
  254. typename CharParser>
  255. void print_parser(
  256. Context const & context,
  257. quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
  258. std::ostream & os,
  259. int components = 0);
  260. template<typename Context, bool NewlinesOnly, bool NoNewlines>
  261. void print_parser(
  262. Context const & context,
  263. ws_parser<NewlinesOnly, NoNewlines> const & parser,
  264. std::ostream & os,
  265. int components = 0);
  266. template<typename Context>
  267. void print_parser(
  268. Context const & context,
  269. bool_parser const & parser,
  270. std::ostream & os,
  271. int components = 0);
  272. template<
  273. typename Context,
  274. typename T,
  275. int Radix,
  276. int MinDigits,
  277. int MaxDigits,
  278. typename Expected>
  279. void print_parser(
  280. Context const & context,
  281. uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
  282. std::ostream & os,
  283. int components = 0);
  284. template<
  285. typename Context,
  286. typename T,
  287. int Radix,
  288. int MinDigits,
  289. int MaxDigits,
  290. typename Expected>
  291. void print_parser(
  292. Context const & context,
  293. int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
  294. std::ostream & os,
  295. int components = 0);
  296. template<typename Context, typename T>
  297. void print_parser(
  298. Context const & context,
  299. float_parser<T> const & parser,
  300. std::ostream & os,
  301. int components = 0);
  302. template<typename Context>
  303. void print_parser(
  304. Context const & context,
  305. float_parser<float> const & parser,
  306. std::ostream & os,
  307. int components = 0);
  308. template<typename Context>
  309. void print_parser(
  310. Context const & context,
  311. float_parser<double> const & parser,
  312. std::ostream & os,
  313. int components = 0);
  314. template<typename Context, typename SwitchValue, typename OrParser>
  315. void print_parser(
  316. Context const & context,
  317. switch_parser<SwitchValue, OrParser> const & parser,
  318. std::ostream & os,
  319. int components = 0);
  320. enum { trace_indent_factor = 2 };
  321. inline void trace_indent(std::ostream & os, int indent)
  322. {
  323. for (int i = 0, end = trace_indent_factor * indent; i != end; ++i) {
  324. os << ' ';
  325. }
  326. }
  327. template<typename Iter, typename Sentinel, int SizeofValueType>
  328. struct trace_input_impl
  329. {
  330. static void call(
  331. std::ostream & os,
  332. Iter first_,
  333. Sentinel last_,
  334. bool quote,
  335. int64_t trace_input_cps)
  336. {
  337. auto utf8 = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_) | text::as_utf8;
  338. auto first = utf8.begin();
  339. auto last = utf8.end();
  340. if (quote)
  341. os << '"';
  342. for (int64_t i = 0; i < trace_input_cps && first != last;
  343. ++i, ++first) {
  344. detail::print_char(os, *first);
  345. }
  346. if (quote)
  347. os << '"';
  348. }
  349. };
  350. template<typename Iter, typename Sentinel>
  351. struct trace_input_impl<Iter, Sentinel, 1>
  352. {
  353. static void call(
  354. std::ostream & os,
  355. Iter first_,
  356. Sentinel last_,
  357. bool quote,
  358. int64_t trace_input_cps)
  359. {
  360. auto r = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_);
  361. auto r_unpacked =
  362. detail::text::unpack_iterator_and_sentinel(first_, last_);
  363. auto utf32 = r | text::as_utf32;
  364. auto first = utf32.begin();
  365. auto const last = utf32.end();
  366. for (int64_t i = 0; i < trace_input_cps && first != last; ++i) {
  367. ++first;
  368. }
  369. if (quote)
  370. os << '"';
  371. auto first_repacked = r_unpacked.repack(first.base());
  372. for (Iter it = first_, end = first_repacked; it != end; ++it) {
  373. detail::print_char(os, *it);
  374. }
  375. if (quote)
  376. os << '"';
  377. }
  378. };
  379. template<typename Iter, typename Sentinel>
  380. inline void trace_input(
  381. std::ostream & os,
  382. Iter first,
  383. Sentinel last,
  384. bool quote = true,
  385. int64_t trace_input_cps = 8)
  386. {
  387. trace_input_impl<Iter, Sentinel, sizeof(*first)>::call(
  388. os, first, last, quote, trace_input_cps);
  389. }
  390. template<typename Iter, typename Sentinel>
  391. inline void trace_begin_match(
  392. std::ostream & os,
  393. Iter first,
  394. Sentinel last,
  395. int indent,
  396. std::string_view name)
  397. {
  398. detail::trace_indent(os, indent);
  399. os << "[begin " << name << "; input=";
  400. detail::trace_input(os, first, last);
  401. os << "]" << std::endl;
  402. }
  403. template<typename Iter, typename Sentinel>
  404. inline void trace_end_match(
  405. std::ostream & os,
  406. Iter first,
  407. Sentinel last,
  408. int indent,
  409. std::string_view name)
  410. {
  411. detail::trace_indent(os, indent);
  412. os << "[end " << name << "; input=";
  413. detail::trace_input(os, first, last);
  414. os << "]" << std::endl;
  415. }
  416. template<typename Iter, typename Sentinel, typename Context>
  417. void trace_prefix(
  418. std::ostream & os,
  419. Iter first,
  420. Sentinel last,
  421. Context const & context,
  422. std::string_view name)
  423. {
  424. int & indent = detail::_indent(context);
  425. detail::trace_begin_match(os, first, last, indent, name);
  426. ++indent;
  427. }
  428. template<typename Iter, typename Sentinel, typename Context>
  429. void trace_suffix(
  430. std::ostream & os,
  431. Iter first,
  432. Sentinel last,
  433. Context const & context,
  434. std::string_view name)
  435. {
  436. int & indent = detail::_indent(context);
  437. --indent;
  438. detail::trace_end_match(os, first, last, indent, name);
  439. }
  440. template<typename T>
  441. using streamable =
  442. decltype(std::declval<std::ostream &>() << std::declval<T const &>());
  443. template<typename T, bool Streamable = is_detected_v<streamable, T>>
  444. struct printer
  445. {
  446. std::ostream & operator()(std::ostream & os, T const &)
  447. {
  448. return os << "<<unprintable-value>>";
  449. }
  450. };
  451. template<typename T>
  452. void print_printable(std::ostream & os, T const & x)
  453. {
  454. os << x;
  455. }
  456. inline void print_printable(std::ostream & os, char c)
  457. {
  458. if (std::isprint(c)) {
  459. os << "'" << c << "'";
  460. } else {
  461. unsigned char c_ = c;
  462. os << "'\\x" << std::hex << std::setfill('0') << (uint32_t)c_
  463. << "'";
  464. }
  465. }
  466. inline void print_printable(std::ostream & os, char32_t c)
  467. {
  468. if (c < 256) {
  469. os << "U";
  470. detail::print_printable(os, (char)c);
  471. } else {
  472. os << "U'\\U" << std::hex << std::setfill('0') << (int32_t)c << "'";
  473. }
  474. }
  475. template<typename T>
  476. struct printer<T, true>
  477. {
  478. std::ostream & operator()(std::ostream & os, T const & x)
  479. {
  480. detail::print_printable(os, x);
  481. return os;
  482. }
  483. };
  484. template<typename T>
  485. constexpr bool is_variant_v = enable_variant<T>;
  486. template<typename Attribute>
  487. inline void print(std::ostream & os, Attribute const & attr)
  488. {
  489. using just_attribute =
  490. std::remove_cv_t<std::remove_reference_t<Attribute>>;
  491. if constexpr (is_tuple<just_attribute>{}) {
  492. os << "(";
  493. bool first = true;
  494. hl::for_each(attr, [&](auto const & a) {
  495. if (!first)
  496. os << ", ";
  497. detail::print(os, a);
  498. first = false;
  499. });
  500. os << ")";
  501. } else if constexpr (is_optional_v<just_attribute>) {
  502. if (!attr)
  503. os << "<<empty>>";
  504. else
  505. detail::print(os, *attr);
  506. } else if constexpr (is_variant_v<just_attribute>) {
  507. os << "<<variant>>";
  508. } else {
  509. printer<just_attribute>{}(os, attr);
  510. }
  511. }
  512. template<typename Attribute>
  513. inline void
  514. print_attribute(std::ostream & os, Attribute const & attr, int indent)
  515. {
  516. detail::trace_indent(os, indent);
  517. os << "attribute: ";
  518. detail::print(os, attr);
  519. os << "\n";
  520. }
  521. inline void print_attribute(std::ostream &, nope const &, int) {}
  522. constexpr inline bool do_trace(flags f)
  523. {
  524. return (uint32_t(f) & uint32_t(flags::trace)) == uint32_t(flags::trace);
  525. }
  526. template<typename Context, typename T>
  527. auto resolve(Context const & context, T const & x);
  528. template<typename Context>
  529. auto resolve(Context const &, nope n);
  530. template<
  531. bool DoTrace,
  532. typename Iter,
  533. typename Sentinel,
  534. typename Context,
  535. typename Attribute>
  536. struct scoped_trace_t
  537. {
  538. scoped_trace_t(
  539. std::ostream & os,
  540. Iter & first,
  541. Sentinel last,
  542. Context const & context,
  543. flags f,
  544. Attribute const & attr,
  545. std::string name) :
  546. os_(os),
  547. initial_first_(first),
  548. first_(first),
  549. last_(last),
  550. context_(context),
  551. flags_(f),
  552. attr_(attr),
  553. name_(std::move(name))
  554. {
  555. if (!detail::do_trace(flags_))
  556. return;
  557. detail::trace_prefix(os, first_, last_, context_, name_);
  558. }
  559. ~scoped_trace_t()
  560. {
  561. if (!detail::do_trace(flags_))
  562. return;
  563. detail::trace_indent(os_, detail::_indent(context_));
  564. if (*context_.pass_) {
  565. os_ << "matched ";
  566. detail::trace_input(os_, initial_first_, first_);
  567. os_ << "\n";
  568. detail::print_attribute(
  569. os_,
  570. detail::resolve(context_, attr_),
  571. detail::_indent(context_));
  572. } else {
  573. os_ << "no match\n";
  574. }
  575. detail::trace_suffix(os_, first_, last_, context_, name_);
  576. }
  577. std::ostream & os_;
  578. Iter initial_first_;
  579. Iter & first_;
  580. Sentinel last_;
  581. Context const & context_;
  582. flags flags_;
  583. Attribute const & attr_;
  584. std::string name_;
  585. };
  586. template<
  587. typename Iter,
  588. typename Sentinel,
  589. typename Context,
  590. typename Attribute>
  591. struct scoped_trace_t<false, Iter, Sentinel, Context, Attribute>
  592. {
  593. scoped_trace_t() {}
  594. };
  595. template<
  596. typename Parser,
  597. typename Iter,
  598. typename Sentinel,
  599. typename Context,
  600. typename Attribute>
  601. auto scoped_trace(
  602. Parser const & parser,
  603. Iter & first,
  604. Sentinel last,
  605. Context const & context,
  606. flags f,
  607. Attribute const & attr)
  608. {
  609. if constexpr (Context::do_trace) {
  610. std::stringstream oss;
  611. detail::print_parser(context, parser, oss);
  612. std::ostream & os = BOOST_PARSER_TRACE_OSTREAM;
  613. return scoped_trace_t<true, Iter, Sentinel, Context, Attribute>(
  614. os, first, last, context, f, attr, oss.str());
  615. } else {
  616. return scoped_trace_t<false, Iter, Sentinel, Context, Attribute>{};
  617. }
  618. }
  619. template<typename Context, typename Attribute>
  620. auto final_trace(Context const & context, flags f, Attribute const & attr)
  621. {
  622. if (!detail::do_trace(f))
  623. return;
  624. std::ostream & os = BOOST_PARSER_TRACE_OSTREAM;
  625. os << "--------------------\n";
  626. if (*context.pass_) {
  627. os << "parse succeeded\n";
  628. detail::print_attribute(os, detail::resolve(context, attr), 0);
  629. } else {
  630. os << "parse failed\n";
  631. }
  632. os << "--------------------" << std::endl;
  633. }
  634. }}}
  635. #endif