1 // Copyright Abel Sinkovics (abel@sinkovics.hu)  2015.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <boost/metaparse/string.hpp>
7 #include <boost/metaparse/sequence_apply.hpp>
8 #include <boost/metaparse/last_of.hpp>
9 #include <boost/metaparse/int_.hpp>
10 #include <boost/metaparse/token.hpp>
11 #include <boost/metaparse/lit_c.hpp>
12 #include <boost/metaparse/one_of.hpp>
13 #include <boost/metaparse/empty.hpp>
14 #include <boost/metaparse/entire_input.hpp>
15 #include <boost/metaparse/build_parser.hpp>
16 
17 #include <boost/rational.hpp>
18 
19 #include <boost/config.hpp>
20 
21 #include <boost/mpl/int.hpp>
22 
23 #include <iostream>
24 
25 using boost::metaparse::sequence_apply2;
26 using boost::metaparse::last_of;
27 using boost::metaparse::int_;
28 using boost::metaparse::token;
29 using boost::metaparse::lit_c;
30 using boost::metaparse::one_of;
31 using boost::metaparse::empty;
32 using boost::metaparse::entire_input;
33 using boost::metaparse::build_parser;
34 
35 template <class Num, class Denom>
36 struct rational
37 {
38   typedef rational type;
39 
runrational40   static boost::rational<int> run()
41   {
42     return boost::rational<int>(Num::type::value, Denom::type::value);
43   }
44 };
45 
46 typedef
47   sequence_apply2<
48     rational,
49 
50     token<int_>,
51     one_of<
52       last_of<lit_c<'/'>, token<int_> >,
53       empty<boost::mpl::int_<1> >
54     >
55   >
56   rational_grammar;
57 
58 typedef build_parser<entire_input<rational_grammar> > rational_parser;
59 
60 #ifdef RATIONAL
61 #  error RATIONAL already defined
62 #endif
63 #define RATIONAL(s) \
64   (::rational_parser::apply<BOOST_METAPARSE_STRING(s)>::type::run())
65 
66 #if BOOST_METAPARSE_STD < 2011
67 
main()68 int main()
69 {
70   std::cout << "Please use a compiler that supports constexpr" << std::endl;
71 }
72 
73 #else
74 
main()75 int main()
76 {
77   const boost::rational<int> r1 = RATIONAL("1/3");
78   const boost::rational<int> r2 = RATIONAL("4/4");
79   const boost::rational<int> r3 = RATIONAL("1");
80   const boost::rational<int> r4 = RATIONAL("13/11");
81 
82   // Uncommenting the following line generates a compilation error. On a
83   // number of platforms the error report contains the following (or something
84   // similar):
85   // x__________________PARSING_FAILED__________________x<1, 3, digit_expected>
86   // where 1, 3 is the location of the error inside the string literal.
87 //  const boost::rational<int> r5 = RATIONAL("7/");
88 
89   std::cout
90     << r1 << std::endl
91     << r2 << std::endl
92     << r3 << std::endl
93     << r4 << std::endl;
94 }
95 
96 #endif
97 
98