Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
genset-labelset.hh
Go to the documentation of this file.
1 #ifndef VCSN_LABELSET_GENSET_LABELSET_HH
2 # define VCSN_LABELSET_GENSET_LABELSET_HH
3 
4 # include <memory>
5 # include <set>
6 
7 # include <boost/optional.hpp>
8 
9 # include <vcsn/core/kind.hh>
10 # include <vcsn/misc/raise.hh>
11 
12 namespace vcsn
13 {
14  namespace detail
15  {
18  template <typename GenSet>
20  {
21  using genset_t = GenSet;
22  using genset_ptr = std::shared_ptr<const genset_t>;
23 
24  using letter_t = typename genset_t::letter_t;
25  using word_t = typename genset_t::word_t;
26  using letters_t = std::set<letter_t>;
27 
29  : gs_{gs}
30  {}
31 
32  genset_labelset(const genset_t& gs = {})
33  : genset_labelset{std::make_shared<const genset_t>(gs)}
34  {}
35 
36  const genset_t& genset() const
37  {
38  return *gs_;
39  }
40 
41  static std::string sname()
42  {
43  return genset_t::sname();
44  }
45 
46  std::string vname(bool full = true) const
47  {
48  return this->genset().vname(full);
49  }
50 
57  std::set<letter_t>
58  convs_(std::istream& i) const
59  {
60  int c = i.get();
61  require(c == '[',
62  "expected '[', found ", str_escape(c));
63  // The last letter we read, for intervals.
64  boost::optional<letter_t> previous;
65  std::set<letter_t> res;
66  while (i.peek() != EOF && i.peek() != ']')
67  {
68  if (i.peek() == '-')
69  {
70  require(previous != boost::none,
71  "bracket cannot begin with '-'");
72  i.ignore();
73  // Handle ranges.
74  if (i.peek() == ']')
75  // [abc-] does not denote an interval.
76  res.insert(letter_t{'-'});
77  else
78  {
79  // [prev - l2].
80  letter_t l2 = genset_t::get_letter(i);
81  require(this->has(l2),
82  "invalid label: unexpected ", str_escape(l2));
83  for (auto i = this->genset().find(previous.get());
84  i != this->genset().end();
85  ++i)
86  {
87  res.insert(*i);
88  if (*i == l2)
89  break;
90  }
91  previous = boost::none;
92  }
93  }
94  else
95  {
96  letter_t l = genset_t::get_letter(i);
97  require(this->has(l),
98  "invalid label: unexpected ", str_escape(l));
99  res.insert(l);
100  previous = l;
101  }
102  }
103  eat(i, ']');
104  return res;
105  }
106 
108 # define DEFINE(Name, Attribute) \
109  template <typename... Args> \
110  Attribute \
111  auto \
112  Name(Args&&... args) const \
113  -> decltype(this->genset().Name(std::forward<Args>(args)...)) \
114  { \
115  return this->genset().Name(std::forward<Args>(args)...); \
116  }
117 
124  DEFINE(equals, ATTRIBUTE_PURE);
125  DEFINE(has, ATTRIBUTE_PURE);
126  DEFINE(is_letter, ATTRIBUTE_PURE);
127  DEFINE(transpose, ATTRIBUTE_PURE);
128 
129 # undef DEFINE
130 
131  private:
132  genset_ptr gs_;
133  };
134  }
135 }
136 
137 #endif // !VCSN_LABELSET_GENSET_LABELSET_HH
ATTRIBUTE_PURE auto transpose(Args &&...args) const -> decltype(this->genset().transpose(std::forward< Args >(args)...))
std::shared_ptr< const genset_t > genset_ptr
auto end(Args &&...args) const -> decltype(this->genset().end(std::forward< Args >(args)...))
auto undelimit(Args &&...args) const -> decltype(this->genset().undelimit(std::forward< Args >(args)...))
auto delimit(Args &&...args) const -> decltype(this->genset().delimit(std::forward< Args >(args)...))
auto begin(Args &&...args) const -> decltype(this->genset().begin(std::forward< Args >(args)...))
auto get_word(Args &&...args) const -> decltype(this->genset().get_word(std::forward< Args >(args)...))
std::set< letter_t > letters_t
std::string sname()
Definition: name.hh:31
typename genset_t::word_t word_t
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Definition: escape.cc:43
This class has no modeling purpose, it only serves to factor code common to letterset, nullableset and wordset.
std::string vname(bool full=true) const
ATTRIBUTE_PURE auto is_letter(Args &&...args) const -> decltype(this->genset().is_letter(std::forward< Args >(args)...))
static std::string sname()
std::set< letter_t > convs_(std::istream &i) const
Read a range of letters.
ATTRIBUTE_PURE auto equals(Args &&...args) const -> decltype(this->genset().equals(std::forward< Args >(args)...))
ATTRIBUTE_PURE auto has(Args &&...args) const -> decltype(this->genset().has(std::forward< Args >(args)...))
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
genset_labelset(const genset_ptr &gs)
genset_labelset(const genset_t &gs={})
typename genset_t::letter_t letter_t
#define DEFINE(Name, Attribute)
Use the implementation from genset.
const genset_t & genset() const
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
ATTRIBUTE_PURE auto find(const std::vector< T, Alloc > &s, const T &e) -> typename std::vector< T, Alloc >::const_iterator
Convenience wrapper around std::find.
Definition: vector.hh:66