Vcsn  2.3
Be Rational
char.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cassert>
4 #include <string>
5 #include <iostream>
6 
7 #include <vcsn/misc/escape.hh>
8 #include <vcsn/misc/format.hh>
9 #include <vcsn/misc/raise.hh>
10 #include <vcsn/misc/stream.hh>
11 #include <vcsn/misc/symbol.hh>
12 
13 namespace vcsn
14 {
17  {
18  public:
19  using letter_t = char;
20  using word_t = std::string;
21 
22  static symbol sname()
23  {
24  static auto res = symbol{"char_letters"};
25  return res;
26  }
27 
29  word_t
30  to_word(const letter_t l) const
31  {
32  return {l};
33  }
34 
36  const word_t&
37  to_word(const word_t& l) const
38  {
39  return l;
40  }
41 
43  word_t
44  mul(const letter_t l, const letter_t r) const
45  {
46  if (l == one_letter())
47  {
48  if (r == one_letter())
49  return {};
50  else
51  return {l};
52  }
53  else if (r == one_letter())
54  return {l};
55  else
56  return {l, r};
57  }
58 
60  word_t
61  mul(const word_t& l, const letter_t r) const
62  {
63  return r == one_letter() ? l : l + r;
64  }
65 
67  word_t
68  mul(const letter_t l, const word_t& r) const
69  {
70  return l == one_letter() ? r : l + r;
71  }
72 
74  word_t
75  mul(const word_t& l, const word_t& r) const
76  {
77  return l + r;
78  }
79 
81  word_t delimit(const word_t& w) const
82  {
83  return mul(mul(special_letter(), w), special_letter());
84  }
85 
87  word_t undelimit(const word_t& w) const
88  {
89  size_t s = w.size();
90  assert(2 <= s);
91  assert(w[0] == special_letter());
92  assert(w[s-1] == special_letter());
93  return w.substr(1, s-2);
94  }
95 
97  static word_t
99  {
100  return {};
101  }
102 
104  static bool
106  {
107  return w.empty();
108  }
109 
111  word_t
112  transpose(const word_t& w) const
113  {
114  // C++11 lacks std::rbegin/rend...
115  return {w.rbegin(), w.rend()};
116  }
117 
119  letter_t
121  {
122  return l;
123  }
124 
126  static bool equal(const letter_t l, const letter_t r)
127  {
128  return l == r;
129  }
130 
132  static bool equal(const word_t& l, const word_t& r)
133  {
134  return l == r;
135  }
136 
138  static bool less(const letter_t l, const letter_t r)
139  {
140  // Be sure to convert the whole 8-bit spectrum.
141  return uint8_t(l) < uint8_t(r);
142  }
143 
145  static bool less(const word_t& l, const word_t& r)
146  {
147  // FIXME: do we need an unsigned comparison?
148  return l < r;
149  }
150 
152  bool is_letter(const letter_t) const
153  {
154  return true;
155  }
156 
158  bool is_letter(const word_t& w) const
159  {
160  return w.size() == 1;
161  }
162 
165  static constexpr letter_t one_letter() { return 0; }
166 
167  private:
175  static constexpr letter_t special_letter() { return -1; }
176 
177  public:
181  static letter_t get_letter(std::istream& i, bool quoted = true)
182  {
183  letter_t res = i.peek();
184  if (quoted && res == '\'')
185  {
186  eat(i, '\'');
187  res = get_char(i);
188  eat(i, '\'');
189  }
190  else
191  res = get_char(i);
192  return res;
193  }
194 
196  std::ostream&
197  print(const letter_t l, std::ostream& o, format fmt = {}) const
198  {
199  if (l == one_letter() || l == special_letter())
200  {}
201  else
202  switch (fmt.kind())
203  {
204  case format::sname:
205  // Escape dash and parens, which are special when parsed
206  // (actually, only the closing paren is special, but treating
207  // them symmetrically is better looking).
208  //
209  // Of course, escape single-quote and backslash, which are
210  // used to escape.
211  str_escape(o, l, "(-)\\'");
212  break;
213 
214  case format::latex:
215  if (l == '\\')
216  o << "\\backslash{}";
217  else
218  str_escape(o, l, "|',[-]<>#");
219  break;
220 
221  case format::raw:
222  o << l;
223  break;
224 
225  case format::text:
226  case format::utf8:
227  if (l == '\\')
228  o << "\\\\";
229  else
230  str_escape(o, l, fmt.meta() ? fmt.meta() : "|',[-]<> ");
231  }
232  return o;
233  }
234 
236  std::ostream&
237  print(const word_t& w, std::ostream& o, format fmt = {}) const
238  {
239  size_t s = w.size();
240 
241  if (s == 0
242  || (s == 1 && w[0] == one_letter()))
243  o << "\\e";
244  else if (s == 1 && w[0] == special_letter())
245  o << '$';
246  else if (fmt == format::raw)
247  o << w;
248  else
249  {
250  if (fmt == format::latex)
251  o << "\\mathit{";
252  o << str_escape(w);
253  if (fmt == format::latex)
254  o << '}';
255  }
256  return o;
257  }
258 
261  template <typename T = letter_t>
262  static T special();
263  };
264 
265  template <>
266  inline
268  char_letters::special<char_letters::letter_t>()
269  {
270  return special_letter();
271  }
272 
273  template <>
274  inline
276  char_letters::special<char_letters::word_t>()
277  {
278  return {special_letter()};
279  }
280 
281 }
word_t to_word(const letter_t l) const
Convert to word.
Definition: char.hh:30
letter_t transpose(letter_t l) const
Mirror label.
Definition: char.hh:120
static constexpr letter_t special_letter()
The reserved letter used to forge the labels for initial and final transitions.
Definition: char.hh:175
const word_t & to_word(const word_t &l) const
Convert to word.
Definition: char.hh:37
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
word_t delimit(const word_t &w) const
Add the special character first and last.
Definition: char.hh:81
std::ostream & str_escape(std::ostream &os, const std::string &str, const char *special=nullptr)
Output a string, escaping special characters.
Definition: escape.cc:51
word_t mul(const letter_t l, const word_t &r) const
Concatenation.
Definition: char.hh:68
static constexpr letter_t one_letter()
The reserved letter used to forge the "one" label (the unit, the identity).
Definition: char.hh:165
word_t mul(const word_t &l, const word_t &r) const
Concatenation.
Definition: char.hh:75
Print as a parsable type string.
Definition: format.hh:26
std::string word_t
Definition: char.hh:20
char get_char(std::istream &i)
Read a single char, with possible -escape support.
Definition: stream.cc:37
static symbol sname()
Definition: char.hh:22
return res
Definition: multiply.hh:398
static T special()
Special character, used to label transitions from pre() and to post().
bool is_letter(const word_t &w) const
Whether is a single-letter word.
Definition: char.hh:158
word_t mul(const word_t &l, const letter_t r) const
Concatenation.
Definition: char.hh:61
static bool less(const word_t &l, const word_t &r)
Whether l < r.
Definition: char.hh:145
Definition: a-star.hh:8
static word_t empty_word()
One.
Definition: char.hh:98
word_t undelimit(const word_t &w) const
Remove first and last characters, that must be "special".
Definition: char.hh:87
An input/output format for valuesets.
Definition: format.hh:13
static bool less(const letter_t l, const letter_t r)
Whether l < r.
Definition: char.hh:138
word_t mul(const letter_t l, const letter_t r) const
Concatenation.
Definition: char.hh:44
Print as is. For instance, don't try to escape labels.
Definition: format.hh:24
Represent alphabets whose "letters" are plain chars.
Definition: char.hh:16
static letter_t get_letter(std::istream &i, bool quoted=true)
Read one letter from i.
Definition: char.hh:181
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
static bool equal(const word_t &l, const word_t &r)
Whether l == r.
Definition: char.hh:132
std::ostream & print(const word_t &w, std::ostream &o, format fmt={}) const
Print a word.
Definition: char.hh:237
static bool is_empty_word(const word_t &w)
Whether is one.
Definition: char.hh:105
Print for LaTeX.
Definition: format.hh:22
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
Print as plain (ASCII) text, escaped.
Definition: format.hh:28
std::ostream & print(const letter_t l, std::ostream &o, format fmt={}) const
Print a letter.
Definition: char.hh:197
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:90
word_t transpose(const word_t &w) const
Mirror label.
Definition: char.hh:112
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
static bool equal(const letter_t l, const letter_t r)
Whether l == r.
Definition: char.hh:126
bool is_letter(const letter_t) const
Whether is a letter.
Definition: char.hh:152