carl  24.04
Computer ARithmetic Library
parser.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <boost/optional.hpp>
4 
5 #define BOOST_SPIRIT_USE_PHOENIX_V3
6 #include <boost/spirit/include/phoenix_bind.hpp>
7 #include <boost/spirit/include/phoenix_core.hpp>
8 #include <boost/spirit/include/phoenix_operator.hpp>
9 #include <boost/spirit/include/qi.hpp>
10 #include <boost/spirit/include/qi_parse.hpp>
11 
12 #include "../typetraits.h"
13 
14 namespace carl {
15 namespace parser {
16 
17  namespace qi = boost::spirit::qi;
18  namespace px = boost::phoenix;
19 
20  using Skipper = qi::space_type;
21 
22  template<bool is_int> struct isDivisible {};
23  template<> struct isDivisible<true> {
24  template<typename Attr>
25  bool operator()(const Attr& n, std::size_t exp) {
26  std::cout << "Checking mod(" << n << ", " << Attr(carl::pow(Attr(10), exp)) << ")" << std::endl;
27  return is_zero(carl::mod(n, Attr(carl::pow(Attr(10), exp))));
28  }
29  };
30  template<> struct isDivisible<false> {
31  template<typename Attr>
32  bool operator()(const Attr&, std::size_t) {
33  return true;
34  }
35  };
36 
37  /**
38  * Specialization of qi::real_policies for our rational types.
39  * Specifies that neither NaN nor Inf is allowed.
40  */
41  template<typename T>
42  struct RationalPolicies : qi::real_policies<T> {
44  static constexpr bool allow_leading_dot = true;
45  static constexpr bool allow_trailing_dot = true;
46  static constexpr bool expect_dot = false;
47 
48  template <typename It>
49  static bool parse_dot(It& first, const It& last) {
50  return qi::real_policies<T>::parse_dot(first, last);
51  }
52 #if BOOST_VERSION >= 105900
53  template <typename It, typename Attr>
54  static bool parse_frac_n(It& first, const It& last, Attr& attr, int& frac_digits) {
55  It save = first;
56  if (T_is_int) {
57  Attr local_attr;
58  int local_frac_digits;
59  bool res = qi::real_policies<T>::parse_frac_n(first, last, local_attr, local_frac_digits);
60  if (!res) return false;
61  if (!is_zero(local_attr)) {
62  first = save;
63  return false;
64  }
65  return true;
66  }
67  return qi::real_policies<T>::parse_frac_n(first, last, attr, frac_digits);
68  }
69 #else
70  template <typename It, typename Attr>
71  static bool parse_frac_n(It& first, const It& last, Attr& attr) {
72  It save = first;
73  if (T_is_int) {
74  Attr local_attr;
75  bool res = qi::real_policies<T>::parse_frac_n(first, last, local_attr);
76  first = save;
77  if (!res) return false;
78  if (!is_zero(local_attr)) {
79  return false;
80  }
81  }
82  return qi::real_policies<T>::parse_frac_n(first, last, attr);
83  }
84 #endif
85  template <typename It, typename Attr>
86  static bool parse_exp_n(It& first, const It& last, Attr& attr_) {
87  bool res = qi::real_policies<T>::parse_exp_n(first, last, attr_);
88  if (!res) return false;
89  if (T_is_int) return attr_ >= 0;
90  return true;
91  }
92  template <typename It, typename Attr>
93  static bool parse_nan(It&, const It&, Attr&) {
94  return false;
95  }
96  template <typename It, typename Attr>
97  static bool parse_inf(It&, const It&, Attr&) {
98  return false;
99  }
100  };
101 
102  /// Parses (signed) integers
103  template<typename T>
104  struct IntegerParser: qi::int_parser<T,10,1,-1> {};
105 
106  /// Parses decimals, including floating point and scientific notation
107  template<typename T>
108  struct DecimalParser: qi::real_parser<T, RationalPolicies<T>> {};
109 
110  /// Parses rationals, being two decimals separated by a slash
111  template<typename T, typename Iterator = std::string::const_iterator>
112  struct RationalParser: public qi::grammar<Iterator, T(), Skipper> {
113  RationalParser(): RationalParser::base_type(main, "rational") {
114  main = (number >> -(qi::lit('/') >> number))[qi::_val = px::bind(&RationalParser::makeRational, px::ref(*this), qi::_1, qi::_2)];
115  }
117  qi::rule<Iterator, T(), Skipper> main;
118  T makeRational(const T& a, const boost::optional<T>& b) const {
119  if (!b) return a;
120  return a / *b;
121  }
122  };
123 
124  template<typename Parser, typename T>
125  bool parse_impl(const std::string& input, T& output) {
126  auto it = input.begin();
127  if (parse(it, input.end(), Parser(), output)) {
128  return it == input.end();
129  }
130  return false;
131  }
132  template<typename Parser, typename T, typename S>
133  bool parse_impl(const std::string& input, T& output, const S& skipper) {
134  auto it = input.begin();
135  if (phrase_parse(it, input.end(), Parser(), skipper, output)) {
136  return it == input.end();
137  }
138  return false;
139  }
140 
141  template<typename T>
142  bool parseInteger(const std::string& input, T& output) {
143  return parse_impl<DecimalParser<T>>(input, output);
144  }
145  template<typename T>
146  bool parseDecimal(const std::string& input, T& output) {
147  return parse_impl<DecimalParser<T>>(input, output);
148  }
149  template<typename T>
150  bool parseRational(const std::string& input, T& output) {
151  return parse_impl<RationalParser<T>>(input, output, Skipper());
152  }
153 }
154 }
States if a type represents a subset of all integers.
Definition: typetraits.h:219
carl is the main namespace for the library.
cln::cl_I mod(const cln::cl_I &a, const cln::cl_I &b)
Calculate the remainder of the integer division.
Definition: operations.h:445
Interval< Number > exp(const Interval< Number > &i)
Definition: Exponential.h:10
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
T parse(const std::string &n)
Interval< Number > pow(const Interval< Number > &i, Integer exp)
Definition: Power.h:11
bool parseDecimal(const std::string &input, T &output)
Definition: parser.h:146
bool parseRational(const std::string &input, T &output)
Definition: parser.h:150
bool parse_impl(const std::string &input, T &output)
Definition: parser.h:125
qi::space_type Skipper
Definition: parser.h:20
bool parseInteger(const std::string &input, T &output)
Definition: parser.h:142
PositionIteratorType Iterator
Definition: OPBImporter.cpp:23
bool operator()(const Attr &n, std::size_t exp)
Definition: parser.h:25
bool operator()(const Attr &, std::size_t)
Definition: parser.h:32
Specialization of qi::real_policies for our rational types.
Definition: parser.h:42
static constexpr bool T_is_int
Definition: parser.h:43
static bool parse_exp_n(It &first, const It &last, Attr &attr_)
Definition: parser.h:86
static bool parse_dot(It &first, const It &last)
Definition: parser.h:49
static bool parse_frac_n(It &first, const It &last, Attr &attr)
Definition: parser.h:71
static constexpr bool allow_leading_dot
Definition: parser.h:44
static bool parse_nan(It &, const It &, Attr &)
Definition: parser.h:93
static constexpr bool expect_dot
Definition: parser.h:46
static constexpr bool allow_trailing_dot
Definition: parser.h:45
static bool parse_inf(It &, const It &, Attr &)
Definition: parser.h:97
Parses (signed) integers.
Definition: parser.h:104
Parses decimals, including floating point and scientific notation.
Definition: parser.h:108
Parses rationals, being two decimals separated by a slash.
Definition: parser.h:112
DecimalParser< T > number
Definition: parser.h:116
qi::rule< Iterator, T(), Skipper > main
Definition: parser.h:117
T makeRational(const T &a, const boost::optional< T > &b) const
Definition: parser.h:118