Awali
Another Weighted Automata library
setalpha.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2021 Sylvain Lombardy, Victor Marsault, Jacques Sakarovitch
3 //
4 // Awali is a free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef AWALI_ALPHABETS_SETALPHA_HH
18 # define AWALI_ALPHABETS_SETALPHA_HH
19 
20 # include <initializer_list>
21 # include <stdexcept>
22 # include <cassert>
23 # include <sstream>
24 
25 
26 #include <awali/common/version.hh>
28 #include <awali/common/json/node.cc>
29 #include <awali/sttc/misc/raise.hh>
30 #include <awali/sttc/misc/set.hh>
31 #include <awali/sttc/misc/stream.hh> // eat.
32 
33 namespace awali {
34  namespace sttc {
35 
42  template <typename L>
43  class set_alphabet: public L
44  {
45  public:
46  using letter_t = typename L::letter_t;
47  //using word_t = typename L::word_t;
48  using letters_t = std::set<letter_t>;
51 
52  static std::string sname()
53  {
54  return L::sname();
55  }
56 
57  virtual std::string vname(bool full = true) const
58  {
59  std::ostringstream res;
60  res << sname();
61  if (full)
62  {
63  res << '(';
64  for (letter_t c: alphabet_)
65  L::print(c,res) ;
66  res << ')';
67  }
68  return res.str();
69  }
70 
71  /*
72  static set_alphabet make(std::istream& is)
73  {
74  // name: char(abc)_ratexpset<law_char(xyz)_b>.
75  // ^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
76  // | | weightset
77  // | +-- gens
78  // +-- letter_type
79  std::string letter_type;
80  {
81  char c;
82  while (is >> c)
83  {
84  if (c == '(')
85  {
86  is.unget();
87  break;
88  }
89  letter_type.append(1, c);
90  }
91  }
92  // The list of generators (letters).
93  letters_t gens;
94  // Previously read character.
95  int prev = -1;
96  {
97  sttc::eat(is, '(');
98  char l;
99  while (is >> l && l != ')')
100  switch (l)
101  {
102  case '-':
103  if (prev == -1)
104  goto insert;
105  else
106  {
107  int l2 = is.get();
108  require(l2 != EOF,
109  "unexpected end in character class");
110  if (l2 == '\\')
111  {
112  l2 = is.get();
113  require(l2 != EOF,
114  "unexpected end after escape in character class");
115  }
116  for (l = prev; l <= l2; ++l)
117  gens.insert(l);
118  prev = -1;
119  continue;
120  }
121 
122  case '\\':
123  {
124  int l2 = is.get();
125  require(l2 != EOF,
126  "unexpected end after escape");
127  l = l2;
128  goto insert;
129  }
130 
131  default:
132  insert:
133  gens.insert(l);
134  prev = l;
135  }
136  }
137  return gens;
138  }
139  */
140 
141  set_alphabet() = default;
142  set_alphabet(const set_alphabet&) = default;
143  set_alphabet(const std::initializer_list<letter_t>& l)
144  : alphabet_{l}
145  {}
146 
148  : alphabet_{l}
149  {}
150 
154  bool open(bool o) const
155  {
156  std::swap(o, open_);
157  return o;
158  }
159 
160 
162  set_alphabet&
164  {
165  assert(l != this->special_letter());
166  alphabet_.insert(l);
167  return *this;
168  }
169 
170  set_alphabet&
172  {
173  assert(l != this->special_letter());
174  alphabet_.erase(l);
175  return *this;
176  }
177 
178  unsigned size() const {
179  return alphabet_.size();
180  }
181 
182  set_alphabet&
184  {
185  alphabet_.clear();
186  return *this;
187  }
188 
190  bool
191  has(letter_t l) const
192  {
193  if (open_)
194  {
195  // FIXME: OMG...
196  const_cast<set_alphabet&>(*this).add_letter(l);
197  return true;
198  }
199  else
200  return alphabet_.find(l)!=alphabet_.end();
201  }
202 
203  /*
205  word_t
206  conv(std::istream& i) const
207  {
208  word_t res;
209  require(!i.bad(),
210  "conv: invalid stream");
211  if (i.good() && i.peek() == '\\')
212  {
213  i.ignore();
214  int c = i.peek();
215  if (c != 'e')
216  throw std::domain_error("invalid label: unexpected \\"
217  + str_escape(c));
218  i.ignore();
219  }
220  else
221  {
222  // FIXME: This wrongly assumes that letters are characters.
223  // It will break with integer or string alphabets.
224  int c;
225  while (i.good()
226  && (c = i.peek()) != EOF
227  && c != ','
228  && c != '('
229  && c != ')'
230  && has(c))
231  res = this->concat(res, letter_t(i.get()));
232  }
233  return res;
234  }
235 
236  word_t
237  parse(const std::string& str, size_t& p) const
238  {
239  word_t w = this->empty_word();
240  while (p>0) { //FIXME: this wrongly assumes that there is no delimiter
241  // between letters
242  letter_t l = this->parse_one_letter(str,p);
243  if (this->has(l)) {
244  w = this->concat(l,w);
245  }
246  else {
247  p++;
248  break;
249  }
250  }
251  return w;
252  }
253  */
254 
255  using iterator = typename letters_t::const_iterator;
256  using const_iterator = typename letters_t::const_iterator;
257 
259  {
260  return alphabet_.begin();
261  }
262 
264  {
265  return alphabet_.end();
266  }
267 
269  {
270  return alphabet_.begin();
271  }
272 
274  {
275  return alphabet_.end();
276  }
277 
279  {
280  return alphabet_.find(l);
281  }
282 
283  std::ostream&
284  print_set(std::ostream& o, const std::string& format = "text") const
285  {
286  if (format == "latex")
287  {
288  const char *sep = "\\{";
289  for (auto c: *this)
290  {
291  o << sep;
292  L::print(c, o);
293  sep = ", ";
294  }
295  o << "\\}";
296  }
297  else if (format == "text")
298  o << vname(true);
299  else
300  raise("invalid format: ", format);
301  return o;
302  }
303 
304 
305  template<unsigned version = version::fsm_json>
307  to_json() const {
308  switch (version) {
309  case 0:
310  throw parse_exception("[Set Alpha] Unsupported fsm-json version:"
311  + std::to_string(version));
312  case 1:
313  default:
314  json::object_t* obj = new json::object_t();
315  obj->push_back("letterType", L::to_json());
316  json::array_t* l = new json::array_t();
317  for (auto x: *this)
318  l->push_back(this->template letter_to_json<version>(x));
319  obj->push_back("alphabet", l);
320  return obj;
321  }
322  }
323 
324 
325 
326 
327 // template<unsigned version = version::fsm_json>
328 // json::string_t*
329 // letter_to_json(const letter_t& l) const
330 // {
331 // switch (version) {
332 // case 0:
333 // throw parse_exception("[Set Alpha] Unsupported fsm-json version:"
334 // + std::to_string(version));
335 // case 1:
336 // default:
337 // std::stringstream ss;
338 // ss << l;
339 // return new json::string_t(ss.str());
340 // }
341 // }
342 
344  template <typename L2>
345  friend set_alphabet<L2>
346  intersection(const set_alphabet<L2>& lhs, const set_alphabet<L2>& rhs);
347 
349  template <typename L2>
350  friend set_alphabet<L2>
351  get_union(const set_alphabet<L2>& lhs, const set_alphabet<L2>& rhs);
352  private:
353  // FIXME: OMG...
354  mutable letters_t alphabet_;
355  mutable bool open_ = false;
356  };
357 
358  template <typename L2>
359  set_alphabet<L2>
361  {
362  return {internal::intersection(lhs.alphabet_, rhs.alphabet_)};
363  }
364 
365  template <typename L2>
368  {
369  return {internal::get_union(lhs.alphabet_, rhs.alphabet_)};
370  }
371  }
372 }//end of ns awali::stc
373 
374 #endif // !AWALI_ALPHABETS_SETALPHA_HH
Definition: node.hh:424
array_t * push_back(node_t *p)
Definition: node.hh:365
object_t * push_back(std::string key, node_t *node)
The semiring of complex numbers.
Definition: c.hh:43
objets that represent the alphabets of letters as char
Definition: setalpha.hh:44
set_alphabet(const std::initializer_list< letter_t > &l)
Definition: setalpha.hh:143
json::object_t * to_json() const
Definition: setalpha.hh:307
const_iterator cend() const
Definition: setalpha.hh:273
const_iterator begin() const
Definition: setalpha.hh:258
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: setalpha.hh:154
typename letters_t::const_iterator iterator
Definition: setalpha.hh:255
set_alphabet & clear()
Definition: setalpha.hh:183
const_iterator end() const
Definition: setalpha.hh:263
letter_t value_type
The type of our values, when seen as a container.
Definition: setalpha.hh:50
unsigned size() const
Definition: setalpha.hh:178
typename L::letter_t letter_t
Definition: setalpha.hh:46
std::set< letter_t > letters_t
Definition: setalpha.hh:48
set_alphabet(const letters_t &l)
Definition: setalpha.hh:147
typename letters_t::const_iterator const_iterator
Definition: setalpha.hh:256
std::ostream & print_set(std::ostream &o, const std::string &format="text") const
Definition: setalpha.hh:284
const_iterator cbegin() const
Definition: setalpha.hh:268
set_alphabet & remove_letter(letter_t l)
Definition: setalpha.hh:171
virtual std::string vname(bool full=true) const
Definition: setalpha.hh:57
static std::string sname()
Definition: setalpha.hh:52
friend set_alphabet< L2 > intersection(const set_alphabet< L2 > &lhs, const set_alphabet< L2 > &rhs)
Compute the intersection with another alphabet.
Definition: setalpha.hh:360
bool has(letter_t l) const
Whether l is a letter.
Definition: setalpha.hh:191
set_alphabet(const set_alphabet &)=default
const_iterator find(letter_t l) const
Definition: setalpha.hh:278
set_alphabet & add_letter(letter_t l)
Modify this by adding l, and return *this.
Definition: setalpha.hh:163
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:367
std::ostream & print(const std::tuple< Args... > &args, std::ostream &o)
Definition: tuple.hh:254
std::set< T, Compare, Alloc > intersection(const std::set< T, Compare, Alloc > &set1, const std::set< T, Compare, Alloc > &set2)
The intersection of two sets.
std::set< T, Compare, Alloc > get_union(const std::set< T, Compare, Alloc > &set1, const std::set< T, Compare, Alloc > &set2)
The union of two sets.
std::string to_string(identities i)
set_alphabet< L2 > get_union(const set_alphabet< L2 > &lhs, const set_alphabet< L2 > &rhs)
Definition: setalpha.hh:367
set_alphabet< L2 > intersection(const set_alphabet< L2 > &lhs, const set_alphabet< L2 > &rhs)
Definition: setalpha.hh:360
auto format(const ValueSet &vs, const typename ValueSet::value_t &v, Args &&... args) -> std::string
Format v via vs.print.
Definition: stream.hh:109
static const std::string full
Completely version of Awali as a std::string.
Definition: version.hh:40
Main namespace of Awali.
Definition: ato.hh:22
Exceptions thrown during parsing.
Definition: parse_exception.hh:26