Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
setalpha.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALPHABETS_SETALPHA_HH
2 # define VCSN_ALPHABETS_SETALPHA_HH
3 
4 # include <cassert>
5 # include <initializer_list>
6 # include <stdexcept>
7 
8 # include <boost/optional.hpp>
9 
10 # include <vcsn/misc/raise.hh>
11 # include <vcsn/misc/set.hh>
12 # include <vcsn/misc/stream.hh> // eat.
13 # include <vcsn/misc/symbol.hh>
14 
15 namespace vcsn
16 {
17  template <typename L>
18  class set_alphabet: public L
19  {
20  public:
21  using letter_t = typename L::letter_t;
22  using word_t = typename L::word_t;
23  using letters_t = std::set<letter_t>;
26 
27  static std::string sname()
28  {
29  return L::sname();
30  }
31 
32  virtual std::string vname(bool full = true) const
33  {
34  std::string res = sname();
35  if (full)
36  {
37  res += '(';
38  for (letter_t c: alphabet_)
39  res += c;
40  res += ')';
41  }
42  return res;
43  }
44 
45  static set_alphabet make(std::istream& is)
46  {
47  // name: char(abc)
48  // ^^^^ ^^^
49  // | |
50  // | +-- gens
51  // +-- letter_type, currently only "char".
52  eat(is, sname());
53 
54  // The result.
55  set_alphabet res;
56 
57  // This labelset might be open: no initial letter is given, they
58  // will be discovered afterwards.
59  if (is.peek() == '(')
60  {
61  is.ignore();
62  // Previously read character, for intervals.
63  boost::optional<letter_t> prev;
64  bool done = false;
65  while (!done)
66  switch (is.peek())
67  {
68  case EOF:
69  raise("invalid end-of-file");
70  break;
71 
72  case ')':
73  is.ignore();
74  done = true;
75  break;
76  case '-':
77  if (prev == boost::none)
78  goto insert;
79  else
80  {
81  is.ignore();
82  letter_t l2 = L::get_letter(is);
83  for (letter_t l = prev.get(); l <= l2; ++l)
84  res.add_letter(l);
85  prev = boost::none;
86  break;
87  }
88  insert:
89  default:
90  {
91  prev = L::get_letter(is);
92  res.add_letter(prev.get());
93  break;
94  }
95  }
96  }
97  else // is.peek() != '('
98  res.open_ = true;
99  return res;
100  }
101 
102  set_alphabet() = default;
103  set_alphabet(const set_alphabet&) = default;
104  set_alphabet(const std::initializer_list<letter_t>& l)
105  : alphabet_{l}
106  {}
107 
109  : alphabet_{l}
110  {}
111 
115  bool open(bool o) const
116  {
117  std::swap(o, open_);
118  return o;
119  }
120 
122  set_alphabet&
124  {
125  assert(l != this->template special<letter_t>());
126  alphabet_.insert(l);
127  return *this;
128  }
129 
131  bool
132  has(letter_t l) const
133  {
134  if (open_)
135  {
136  // FIXME: OMG...
137  const_cast<set_alphabet&>(*this).add_letter(l);
138  return true;
139  }
140  else
142  }
143 
145  word_t
146  get_word(std::istream& i) const
147  {
148  word_t res;
149  require(!i.bad(),
150  "conv: invalid stream");
151  // Either an empty word: "\e", or a sequence of non-separators.
152  if (i.good() && i.peek() == '\\')
153  {
154  i.ignore();
155  int c = i.get();
156  require(c == 'e',
157  "invalid label: unexpected \\", str_escape(c));
158  }
159  else
160  {
161  // Stop as soon as it might be a special character (such as
162  // delimiters in polynomials).
163  int c;
164  while (i.good()
165  && (c = i.peek()) != EOF
166  && !isspace(c)
167  && c != '+'
168  && c != ','
169  && c != '('
170  && c != ')')
171  {
172  letter_t l = L::get_letter(i);
173  require(has(l), "invalid letter: ", str_escape(l));
174  res = this->concat(res, l);
175  }
176  }
177  return res;
178  }
179 
180  using iterator = typename letters_t::const_iterator;
181  using const_iterator = typename letters_t::const_iterator;
182 
184  {
185  return alphabet_.begin();
186  }
187 
189  {
190  return alphabet_.end();
191  }
192 
194  {
195  return alphabet_.begin();
196  }
197 
199  {
200  return alphabet_.end();
201  }
202 
204  {
205  return alphabet_.find(l);
206  }
207 
208  std::ostream&
209  print_set(std::ostream& o, symbol format = symbol{"text"}) const
210  {
211  if (format == "latex")
212  {
213  o << "\\{";
214  const char *sep = "";
215  for (auto c: *this)
216  {
217  o << sep << c;
218  sep = ", ";
219  }
220  o << "\\}";
221  }
222  else if (format == "text")
223  o << vname(true);
224  else
225  raise("invalid format: ", format);
226  return o;
227  }
228 
230  template <typename L2>
231  friend set_alphabet<L2>
233  {
234  return {intersection(lhs.alphabet_, rhs.alphabet_)};
235  }
236 
238  template <typename L2>
239  friend set_alphabet<L2>
241  {
242  return {get_union(lhs.alphabet_, rhs.alphabet_)};
243  }
244 
245  private:
246  // FIXME: OMG...
248  mutable bool open_ = false;
249  };
250 }
251 
252 #endif // !VCSN_ALPHABETS_SETALPHA_HH
const_iterator cend() const
Definition: setalpha.hh:198
typename letters_t::const_iterator iterator
Definition: setalpha.hh:180
std::ostream & print_set(std::ostream &o, symbol format=symbol{"text"}) const
Definition: setalpha.hh:209
set_alphabet(const letters_t &l)
Definition: setalpha.hh:108
typename L::word_t word_t
Definition: setalpha.hh:22
set_alphabet & add_letter(letter_t l)
Modify this by adding l, and return *this.
Definition: setalpha.hh:123
boost::flyweight< std::string, boost::flyweights::no_tracking > symbol
An internalized string.
Definition: symbol.hh:24
std::string sname()
Definition: name.hh:31
friend set_alphabet< L2 > intersection(const set_alphabet< L2 > &lhs, const set_alphabet< L2 > &rhs)
Compute the intersection with another alphabet.
Definition: setalpha.hh:232
typename letters_t::const_iterator const_iterator
Definition: setalpha.hh:181
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Definition: escape.cc:43
static set_alphabet make(std::istream &is)
Definition: setalpha.hh:45
static std::string sname()
Definition: setalpha.hh:27
word_t get_word(std::istream &i) const
Extract and return the next word from i.
Definition: setalpha.hh:146
letter_t value_type
The type of our values, when seen as a container.
Definition: setalpha.hh:25
letters_t alphabet_
Definition: setalpha.hh:247
const_iterator begin() const
Definition: setalpha.hh:183
friend set_alphabet< L2 > get_union(const set_alphabet< L2 > &lhs, const set_alphabet< L2 > &rhs)
Compute the union with another alphabet.
Definition: setalpha.hh:240
std::set< letter_t > letters_t
Definition: setalpha.hh:23
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:329
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: setalpha.hh:115
const_iterator find(letter_t l) const
Definition: setalpha.hh:203
set_alphabet()=default
const_iterator end() const
Definition: setalpha.hh:188
bool has(letter_t l) const
Whether l is a letter.
Definition: setalpha.hh:132
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
virtual std::string vname(bool full=true) const
Definition: setalpha.hh:32
set_alphabet(const std::initializer_list< letter_t > &l)
Definition: setalpha.hh:104
const_iterator cbegin() const
Definition: setalpha.hh:193
bool has(const std::map< Key, Value, Compare, Alloc > &s, const Key &e)
Definition: map.hh:35
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
typename L::letter_t letter_t
Definition: setalpha.hh:21