PageRenderTime 59ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/boost_1_45_0/libs/spirit/example/scheme/test/qi/qi_interpreter.cpp

https://bitbucket.org/Tank_Master/boost145
C++ | 656 lines | 513 code | 86 blank | 57 comment | 37 complexity | d3be3703494ac7cf05fd2c03b19e8f5c MD5 | raw file
  1. /*=============================================================================
  2. Copyright (c) 2001-2010 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. =============================================================================*/
  6. #include <boost/detail/lightweight_test.hpp>
  7. #include <boost/config/warning_disable.hpp>
  8. #include <input/sexpr.hpp>
  9. #include <input/parse_sexpr_impl.hpp>
  10. #include <scheme/compiler.hpp>
  11. #include <utree/io.hpp>
  12. #include <boost/spirit/include/qi.hpp>
  13. #include <iostream>
  14. #include <fstream>
  15. #include <strstream>
  16. #include <map>
  17. #include "../../../../test/qi/test.hpp"
  18. #define SCHEME_QI_COMPILER_LIMIT 20
  19. namespace scheme { namespace qi
  20. {
  21. ///////////////////////////////////////////////////////////////////////////
  22. // parser compiler
  23. ///////////////////////////////////////////////////////////////////////////
  24. namespace qi = boost::spirit::qi;
  25. namespace spirit = boost::spirit;
  26. typedef qi::rule<char const*> skipper_type;
  27. typedef qi::rule<char const*, skipper_type> rule_type;
  28. ///////////////////////////////////////////////////////////////////////////
  29. // All rule are stored here. Rules are held in the utree by its id;
  30. // i.e. its index in the vector.
  31. ///////////////////////////////////////////////////////////////////////////
  32. template <typename Rule>
  33. class rule_fragments
  34. {
  35. public:
  36. rule_fragments()
  37. : index(0)
  38. {
  39. };
  40. int new_rule()
  41. {
  42. rules[index];
  43. return index++;
  44. }
  45. template <typename Expr>
  46. void define_rule(int id, Expr const& expr)
  47. {
  48. rules[id] = expr;
  49. std::stringstream str;
  50. str << qi::what(expr);
  51. rules[id].name(str.str());
  52. }
  53. Rule const& operator[](int id) const
  54. {
  55. typename std::map<int, Rule>::const_iterator
  56. iter = rules.find(id);
  57. BOOST_ASSERT(iter != rules.end());
  58. return iter->second;
  59. }
  60. Rule const& operator[](utree const& id) const
  61. {
  62. return (*this)[id.get<int>()];
  63. }
  64. private:
  65. int index;
  66. std::map<int, Rule> rules;
  67. };
  68. ///////////////////////////////////////////////////////////////////////////
  69. // Composes primitive parsers held by index. Handles the compilation of
  70. // primitive (nullary) parsers such as int_, double_, alpha, space and all
  71. // those that require no arguments.
  72. ///////////////////////////////////////////////////////////////////////////
  73. struct primitive_parser_composite : composite<primitive_parser_composite>
  74. {
  75. int id;
  76. primitive_parser_composite(int id)
  77. : id(id)
  78. {
  79. }
  80. function compose(actor_list const& elements) const
  81. {
  82. return val(id);
  83. }
  84. };
  85. template <typename Fragments, typename Expr>
  86. inline primitive_parser_composite
  87. make_primitive_parser_composite(Fragments& fragments, Expr const& expr)
  88. {
  89. int id = fragments.new_rule();
  90. fragments.define_rule(id, expr);
  91. return primitive_parser_composite(id);
  92. }
  93. ///////////////////////////////////////////////////////////////////////////
  94. // Handles the compilation of char_
  95. ///////////////////////////////////////////////////////////////////////////
  96. template <typename Fragments>
  97. struct char_function : actor<char_function<Fragments> >
  98. {
  99. mutable int id;
  100. function a;
  101. function b;
  102. Fragments& fragments;
  103. char_function(
  104. Fragments& fragments, function const& a, function const& b)
  105. : id(-1), a(a), b(b), fragments(fragments)
  106. {
  107. }
  108. void define() const
  109. {
  110. // char_
  111. fragments.define_rule(id, qi::char_);
  112. }
  113. void define(utree const& a) const
  114. {
  115. // $$$ use exceptions here $$$.
  116. BOOST_ASSERT(a.which() == utree_type::string_type);
  117. utf8_string_range a_ = a.get<utf8_string_range>();
  118. if (a_.size() == 1)
  119. {
  120. // char_('x')
  121. fragments.define_rule(id, qi::char_(a_[0]));
  122. }
  123. else
  124. {
  125. // char_("some-regex")
  126. fragments.define_rule(id,
  127. qi::char_(std::string(a_.begin(), a_.end())));
  128. }
  129. }
  130. void define(utree const& a, utree const& b) const
  131. {
  132. // $$$ use exceptions here $$$.
  133. BOOST_ASSERT(a.which() == utree_type::string_type);
  134. BOOST_ASSERT(b.which() == utree_type::string_type);
  135. utf8_string_range a_ = a.get<utf8_string_range>();
  136. utf8_string_range b_ = b.get<utf8_string_range>();
  137. // $$$ use exceptions here $$$.
  138. BOOST_ASSERT(a_.size() == 1);
  139. BOOST_ASSERT(b_.size() == 1);
  140. // char_('x', 'y')
  141. fragments.define_rule(id, qi::char_(a_[0], b_[0]));
  142. }
  143. utree eval(scope const& env) const
  144. {
  145. if (id != -1)
  146. return id;
  147. id = fragments.new_rule();
  148. if (a.empty())
  149. define();
  150. else if (b.empty())
  151. define(a(env));
  152. else
  153. define(a(env), b(env));
  154. return id;
  155. }
  156. };
  157. template <typename Fragments>
  158. struct char_composite
  159. : composite<char_composite<Fragments> >
  160. {
  161. Fragments& fragments;
  162. char_composite(Fragments& fragments)
  163. : fragments(fragments) {}
  164. function compose(actor_list const& elements) const
  165. {
  166. typedef char_function<Fragments> function_type;
  167. actor_list::const_iterator i = elements.begin();
  168. function empty;
  169. function const& a = (i == elements.end())? empty : *i++;
  170. function const& b = (i == elements.end())? empty : *i;
  171. return function(function_type(fragments, a, b));
  172. }
  173. };
  174. ///////////////////////////////////////////////////////////////////////////
  175. // Handles the compilation of kleene *a
  176. ///////////////////////////////////////////////////////////////////////////
  177. template <typename Fragments>
  178. struct kleene_function : actor<kleene_function<Fragments> >
  179. {
  180. mutable int id;
  181. function a;
  182. Fragments& fragments;
  183. kleene_function(
  184. Fragments& fragments, function const& a)
  185. : id(-1), a(a), fragments(fragments)
  186. {
  187. }
  188. void define(utree const& a) const
  189. {
  190. fragments.define_rule(id, *fragments[a]); // *a
  191. }
  192. utree eval(scope const& env) const
  193. {
  194. if (id != -1)
  195. return id;
  196. id = fragments.new_rule();
  197. define(a(env));
  198. return id;
  199. }
  200. };
  201. template <typename Fragments>
  202. struct kleene_composite
  203. : composite<kleene_composite<Fragments> >
  204. {
  205. Fragments& fragments;
  206. kleene_composite(Fragments& fragments)
  207. : fragments(fragments) {}
  208. function compose(actor_list const& elements) const
  209. {
  210. typedef kleene_function<Fragments> function_type;
  211. return function(function_type(fragments, elements.front()));
  212. }
  213. };
  214. ///////////////////////////////////////////////////////////////////////////
  215. // Handles the compilation of difference a - b
  216. ///////////////////////////////////////////////////////////////////////////
  217. template <typename Fragments>
  218. struct difference_function : actor<difference_function<Fragments> >
  219. {
  220. mutable int id;
  221. function a;
  222. function b;
  223. Fragments& fragments;
  224. difference_function(
  225. Fragments& fragments, function const& a, function const& b)
  226. : id(-1), a(a), b(b), fragments(fragments)
  227. {
  228. }
  229. void define(utree const& a, utree const& b) const
  230. {
  231. fragments.define_rule(id,
  232. fragments[a] - fragments[b]); // a - b
  233. }
  234. utree eval(scope const& env) const
  235. {
  236. if (id != -1)
  237. return id;
  238. id = fragments.new_rule();
  239. define(a(env), b(env));
  240. return id;
  241. }
  242. };
  243. template <typename Fragments>
  244. struct difference_composite
  245. : composite<difference_composite<Fragments> >
  246. {
  247. Fragments& fragments;
  248. difference_composite(Fragments& fragments)
  249. : fragments(fragments) {}
  250. function compose(actor_list const& elements) const
  251. {
  252. typedef difference_function<Fragments> function_type;
  253. actor_list::const_iterator i = elements.begin();
  254. function const& a = *i++;
  255. function const& b = *i;
  256. return function(function_type(fragments, a, b));
  257. }
  258. };
  259. ///////////////////////////////////////////////////////////////////////////
  260. // Handles the compilation of sequence a >> b
  261. ///////////////////////////////////////////////////////////////////////////
  262. template <typename Fragments>
  263. struct sequence_function : actor<sequence_function<Fragments> >
  264. {
  265. mutable int id;
  266. actor_list elements;
  267. Fragments& fragments;
  268. sequence_function(
  269. Fragments& fragments, actor_list const& elements)
  270. : id(-1), elements(elements), fragments(fragments)
  271. {
  272. }
  273. void define(utree const& a, utree const& b) const
  274. {
  275. // a >> b
  276. fragments.define_rule(id,
  277. fragments[a] >> fragments[b]);
  278. }
  279. void define(utree const& a, utree const& b, utree const& c) const
  280. {
  281. // a >> b >> c
  282. fragments.define_rule(id,
  283. fragments[a] >> fragments[b] >> fragments[c]);
  284. }
  285. void define(utree const& a, utree const& b, utree const& c,
  286. utree const& d) const
  287. {
  288. // a >> b >> c >> d
  289. fragments.define_rule(id,
  290. fragments[a] >> fragments[b] >> fragments[c] >>
  291. fragments[d]);
  292. }
  293. void define(utree const& a, utree const& b, utree const& c,
  294. utree const& d, utree const& e) const
  295. {
  296. // a >> b >> c >> d >> e
  297. fragments.define_rule(id,
  298. fragments[a] >> fragments[b] >> fragments[c] >>
  299. fragments[d] >> fragments[e]);
  300. }
  301. utree eval(scope const& env) const
  302. {
  303. if (id != -1)
  304. return id;
  305. id = fragments.new_rule();
  306. actor_list::const_iterator i = elements.begin();
  307. switch (elements.size())
  308. {
  309. case 2:
  310. {
  311. function const& a = *i++;
  312. function const& b = *i;
  313. define(a(env), b(env));
  314. break;
  315. }
  316. case 3:
  317. {
  318. function const& a = *i++;
  319. function const& b = *i++;
  320. function const& c = *i;
  321. define(a(env), b(env), c(env));
  322. break;
  323. }
  324. case 4:
  325. {
  326. function const& a = *i++;
  327. function const& b = *i++;
  328. function const& c = *i++;
  329. function const& d = *i;
  330. define(a(env), b(env), c(env), d(env));
  331. break;
  332. }
  333. case 5:
  334. {
  335. function const& a = *i++;
  336. function const& b = *i++;
  337. function const& c = *i++;
  338. function const& d = *i++;
  339. function const& e = *i;
  340. define(a(env), b(env), c(env), d(env), e(env));
  341. break;
  342. }
  343. // $$$ Use Boost PP using SCHEME_QI_COMPILER_LIMIT $$$
  344. }
  345. return id;
  346. }
  347. };
  348. template <typename Fragments>
  349. struct sequence_composite
  350. : composite<sequence_composite<Fragments> >
  351. {
  352. Fragments& fragments;
  353. sequence_composite(Fragments& fragments)
  354. : fragments(fragments) {}
  355. function compose(actor_list const& elements) const
  356. {
  357. typedef sequence_function<Fragments> function_type;
  358. return function(function_type(fragments, elements));
  359. }
  360. };
  361. ///////////////////////////////////////////////////////////////////////////
  362. // Handles the compilation of alternatives a | b
  363. ///////////////////////////////////////////////////////////////////////////
  364. template <typename Fragments>
  365. struct alternative_function : actor<alternative_function<Fragments> >
  366. {
  367. mutable int id;
  368. actor_list elements;
  369. Fragments& fragments;
  370. alternative_function(
  371. Fragments& fragments, actor_list const& elements)
  372. : id(-1), elements(elements), fragments(fragments)
  373. {
  374. }
  375. void define(utree const& a, utree const& b) const
  376. {
  377. // a | b
  378. fragments.define_rule(id,
  379. fragments[a] | fragments[b]);
  380. }
  381. void define(utree const& a, utree const& b, utree const& c) const
  382. {
  383. // a | b | c
  384. fragments.define_rule(id,
  385. fragments[a] | fragments[b] | fragments[c]);
  386. }
  387. void define(utree const& a, utree const& b, utree const& c,
  388. utree const& d) const
  389. {
  390. // a | b | c | d
  391. fragments.define_rule(id,
  392. fragments[a] | fragments[b] | fragments[c] |
  393. fragments[d]);
  394. }
  395. void define(utree const& a, utree const& b, utree const& c,
  396. utree const& d, utree const& e) const
  397. {
  398. // a | b | c | d | e
  399. fragments.define_rule(id,
  400. fragments[a] | fragments[b] | fragments[c] |
  401. fragments[d] | fragments[e]);
  402. }
  403. utree eval(scope const& env) const
  404. {
  405. if (id != -1)
  406. return id;
  407. id = fragments.new_rule();
  408. actor_list::const_iterator i = elements.begin();
  409. switch (elements.size())
  410. {
  411. case 2:
  412. {
  413. function const& a = *i++;
  414. function const& b = *i;
  415. define(a(env), b(env));
  416. break;
  417. }
  418. case 3:
  419. {
  420. function const& a = *i++;
  421. function const& b = *i++;
  422. function const& c = *i;
  423. define(a(env), b(env), c(env));
  424. break;
  425. }
  426. case 4:
  427. {
  428. function const& a = *i++;
  429. function const& b = *i++;
  430. function const& c = *i++;
  431. function const& d = *i;
  432. define(a(env), b(env), c(env), d(env));
  433. break;
  434. }
  435. case 5:
  436. {
  437. function const& a = *i++;
  438. function const& b = *i++;
  439. function const& c = *i++;
  440. function const& d = *i++;
  441. function const& e = *i;
  442. define(a(env), b(env), c(env), d(env), e(env));
  443. break;
  444. }
  445. // $$$ Use Boost PP using SCHEME_QI_COMPILER_LIMIT $$$
  446. }
  447. return id;
  448. }
  449. };
  450. template <typename Fragments>
  451. struct alternative_composite
  452. : composite<alternative_composite<Fragments> >
  453. {
  454. Fragments& fragments;
  455. alternative_composite(Fragments& fragments)
  456. : fragments(fragments) {}
  457. function compose(actor_list const& elements) const
  458. {
  459. typedef alternative_function<Fragments> function_type;
  460. return function(function_type(fragments, elements));
  461. }
  462. };
  463. ///////////////////////////////////////////////////////////////////////////
  464. // Build our scheme compiler environment.
  465. ///////////////////////////////////////////////////////////////////////////
  466. template <typename Fragments>
  467. void build_environment(Fragments& fragments, environment& env)
  468. {
  469. build_basic_environment(env);
  470. env.define("qi:space",
  471. make_primitive_parser_composite(fragments, qi::space), 0, true);
  472. env.define("qi:alpha",
  473. make_primitive_parser_composite(fragments, qi::alpha), 0, true);
  474. env.define("qi:int_",
  475. make_primitive_parser_composite(fragments, qi::int_), 0, true);
  476. env.define("qi:char_",
  477. char_composite<Fragments>(fragments), 0, false);
  478. env.define("qi:*",
  479. kleene_composite<Fragments>(fragments), 1, true);
  480. env.define("qi:-",
  481. difference_composite<Fragments>(fragments), 2, true);
  482. env.define("qi:>>",
  483. sequence_composite<Fragments>(fragments), 2, false);
  484. env.define("qi:|",
  485. alternative_composite<Fragments>(fragments), 2, false);
  486. }
  487. }}
  488. ///////////////////////////////////////////////////////////////////////////////
  489. // Main program
  490. ///////////////////////////////////////////////////////////////////////////////
  491. int main()
  492. {
  493. using scheme::utree;
  494. using scheme::interpreter;
  495. using scheme::environment;
  496. using scheme::qi::build_environment;
  497. using scheme::qi::rule_fragments;
  498. using scheme::qi::rule_type;
  499. using spirit_test::test;
  500. environment env;
  501. rule_fragments<rule_type> fragments;
  502. build_environment(fragments, env);
  503. scheme::qi::skipper_type space = boost::spirit::qi::space;
  504. {
  505. utree src =
  506. "(define charx (qi:char_ \"x\"))"
  507. "(define integer (qi:int_))"
  508. "(define nonzero (qi:- (qi:int_) (qi:char_ \"0\")))"
  509. "(define integers (qi:* (qi:int_)))"
  510. "(define intpair (qi:>> "
  511. "(qi:char_ \"(\") "
  512. "(qi:int_) "
  513. "(qi:char_ \",\") "
  514. "(qi:int_) "
  515. "(qi:char_ \")\")))"
  516. ;
  517. interpreter parser(src, "parse.scm", &env);
  518. BOOST_TEST(test("z", fragments[parser["qi:char_"]()], space));
  519. BOOST_TEST(test("x", fragments[parser["charx"]()], space));
  520. BOOST_TEST(!test("y", fragments[parser["charx"]()], space));
  521. BOOST_TEST(test("1234", fragments[parser["integer"]()], space));
  522. BOOST_TEST(!test("x1234", fragments[parser["integer"]()], space));
  523. BOOST_TEST(test("1 2 3 4", fragments[parser["integers"]()], space));
  524. BOOST_TEST(test("1", fragments[parser["nonzero"]()], space));
  525. BOOST_TEST(!test("0", fragments[parser["nonzero"]()], space));
  526. BOOST_TEST(test("(1, 2)", fragments[parser["intpair"]()], space));
  527. BOOST_TEST(!test("(1, x)", fragments[parser["intpair"]()], space));
  528. }
  529. {
  530. char const* filename = filename = "calc.scm";
  531. std::ifstream in(filename, std::ios_base::in);
  532. BOOST_TEST(in);
  533. // Ignore the BOM marking the beginning of a UTF-8 file in Windows
  534. char c = in.peek();
  535. if (c == '\xef')
  536. {
  537. char s[3];
  538. in >> s[0] >> s[1] >> s[2];
  539. s[3] = '\0';
  540. BOOST_TEST(s != std::string("\xef\xbb\xbf"));
  541. }
  542. interpreter parser(in, filename, &env);
  543. rule_type calc = fragments[parser["expression"]()].alias();
  544. std::string str;
  545. while (std::getline(std::cin, str))
  546. {
  547. if (str.empty() || str[0] == 'q' || str[0] == 'Q')
  548. break;
  549. char const* iter = str.c_str();
  550. char const* end = iter + strlen(iter);
  551. bool r = phrase_parse(iter, end, calc, space);
  552. if (r && iter == end)
  553. {
  554. std::cout << "-------------------------\n";
  555. std::cout << "Parsing succeeded\n";
  556. std::cout << "-------------------------\n";
  557. }
  558. else
  559. {
  560. std::string rest(iter, end);
  561. std::cout << "-------------------------\n";
  562. std::cout << "Parsing failed\n";
  563. std::cout << "stopped at: \": " << rest << "\"\n";
  564. std::cout << "-------------------------\n";
  565. }
  566. }
  567. }
  568. return boost::report_errors();
  569. }