Vcsn  2.1
Be Rational
context-parser.cc
Go to the documentation of this file.
3 
4 #include <vcsn/misc/escape.hh>
5 #include <vcsn/misc/indent.hh>
6 #include <vcsn/misc/raise.hh>
7 
8 namespace vcsn
9 {
10  namespace ast
11  {
12 
15  static void check_eof(std::istream& is, std::shared_ptr<ast_node> res)
16  {
17  if (is.peek() != EOF)
18  {
19  std::ostringstream o;
20  signature_printer printer(o, true);
21  res->accept(printer);
23  "unexpected trailing characters after '",
24  o.str(), "'");
25  }
26  }
27 
28  std::shared_ptr<ast_node> context_parser::parse()
29  {
30  auto res = any_();
31  check_eof(is_, res);
32  return res;
33  }
34 
35  std::shared_ptr<ast_node> context_parser::parse_context()
36  {
37  auto res = context_();
38  check_eof(is_, res);
39  return res;
40  }
41 
42  std::shared_ptr<ast_node> context_parser::any_()
43  {
44  std::string w = word_();
45  auto res = std::shared_ptr<ast_node>{};
46  if (w == "delay_automaton"
47  || w == "determinized_automaton"
48  || w == "detweighted_automaton"
49  || w == "expression_automaton"
50  || w == "filter_automaton"
51  || w == "focus_automaton"
52  || w == "mutable_automaton"
53  || w == "name_automaton"
54  || w == "pair_automaton"
55  || w == "partition_automaton"
56  || w == "permutation_automaton"
57  || w == "product_automaton"
58  || w == "scc_automaton"
59  || w == "synchronized_automaton"
60  || w == "transpose_automaton"
61  || w == "tuple_automaton")
62  res = automaton_(w);
63  else if (w == "context")
64  res = context_(w);
65  else if (w == "expansionset")
66  res = expansionset_();
67  else if (w == "expressionset")
68  res = expressionset_();
69  else if (has(labelsets_, w))
70  res = labelset_(w);
71  else if (w == "lat")
72  res = tupleset_();
73  else if (w == "polynomialset")
74  res = polynomialset_();
75  else if (w == "seriesset")
76  res = seriesset_();
77  else if (w == "std::tuple")
78  res = tuple_();
79  else if (has(weightsets_, w))
80  res = weightset_(w);
81  else
82  // int,
83  // std::integral_constant<unsigned, 2>,
84  // boost::optional<unsigned>,
85  // std::vector<unsigned>,
86  // const std::set<std::pair<std::string, std::string>>,
87  // etc.
88  {
89  if (is_.peek() == '<')
90  w += parameters_();
91  res = std::make_shared<other>(w);
92  }
93  return res;
94  }
95 
96  std::shared_ptr<ast_node>
98  {
99  return labelset_or_weightset_(word_());
100  }
101 
102  std::shared_ptr<ast_node>
104  {
105  if (w == "lat")
106  return tupleset_();
107  else if (w == "expressionset")
108  return expressionset_();
109  else if (w == "seriesset")
110  return seriesset_();
111  else if (has(labelsets_, w))
112  return labelset_(w);
113  else if (has(weightsets_, w))
114  return weightset_(w);
115  else
116  raise("invalid weightset or labelset name: " + w);
117  }
118 
119  std::string context_parser::word_()
120  {
121  std::string res;
122  int c;
123  while (is_.peek() == ' ')
124  is_.get();
125  while ((c = is_.get()) != EOF)
126  if (c == '<' || c == ',' || c == '>' || c == '(')
127  {
128  is_.unget();
129  break;
130  }
131  else
132  res += c;
133  return res;
134  }
135 
137  {
138  std::string res;
139  res += eat(is_, '<');
140  auto nesting = 1;
141  int c;
142  while ((c = is_.peek()) != EOF)
143  {
144  if (c == '<')
145  ++nesting;
146  else if (c == '>' && --nesting == 0)
147  break;
148  res += c;
149  is_.ignore();
150  }
151  res += eat(is_, '>');
152  return res;
153  }
154 
155  std::shared_ptr<const genset>
156  context_parser::genset_(std::string letter_type)
157  {
158  if (letter_type == "char" || letter_type == "string")
159  letter_type += "_letters";
160  std::string gens;
161  if (is_.peek() == '(')
162  {
163  gens += '(';
164  int c = is_.get();
165  while ((c = is_.get()) != EOF && c != ')')
166  {
167  gens += c;
168  if (c == '\\')
169  {
170  c = is_.get();
171  require(c != EOF, "unexpected end of file");
172  gens += c;
173  }
174  }
175  gens += ')';
176  }
177  return std::make_shared<const genset>(letter_type, gens);
178  }
179 
180  std::shared_ptr<const genset> context_parser::genset_()
181  {
182  return genset_(word_());
183  }
184 
185  std::shared_ptr<context> context_parser::context_()
186  {
187  return context_(word_());
188  }
189 
190  std::shared_ptr<context>
192  {
193  bool close = false;
194  if (w == "context")
195  {
196  eat(is_, '<');
197  close = true;
198  w = word_();
199  }
200  auto ls = labelset_(w);
201  eat(is_, ',');
202  while (isspace(is_.peek()))
203  is_.ignore();
204  auto ws = weightset_();
205  if (close)
206  eat(is_, '>');
207  return std::make_shared<context>(ls, ws);
208  }
209 
210  std::shared_ptr<ast_node> context_parser::labelset_()
211  {
212  return labelset_(word_());
213  }
214 
215  std::shared_ptr<ast_node>
216  context_parser::labelset_(const std::string& ls)
217  {
218  if (ls == "lal_char")
219  return std::make_shared<letterset>(genset_("char_letters"));
220  else if (ls == "lan")
221  {
222  // lan<GENSET> => nullableset<letterset<GENSET>>.
223  eat(is_, '<');
224  auto gs = genset_();
225  eat(is_, '>');
226  return
227  std::make_shared<nullableset>(std::make_shared<letterset>(gs));
228  }
229  else if (ls == "lan_char")
230  return std::make_shared<nullableset>(std::make_shared<letterset>
231  (genset_("char_letters")));
232  else if (ls == "lao")
233  return std::make_shared<oneset>();
234  else if (ls == "lat")
235  return tupleset_();
236  else if (ls == "law_char")
237  return std::make_shared<wordset>(genset_("char_letters"));
238  else if (ls == "lal" || ls == "letterset")
239  {
240  eat(is_, '<');
241  auto gs = genset_();
242  eat(is_, '>');
243  return std::make_shared<letterset>(gs);
244  }
245  else if (ls == "law" || ls == "wordset")
246  {
247  eat(is_, '<');
248  auto gs = genset_();
249  eat(is_, '>');
250  return std::make_shared<wordset>(gs);
251  }
252  else if (ls == "nullableset")
253  {
254  eat(is_, '<');
255  auto res = labelset_();
256  eat(is_, '>');
257  if (!res->has_one())
258  res = std::make_shared<nullableset>(res);
259  return res;
260  }
261  else if (ls == "expressionset")
262  return expressionset_();
263  else if (ls == "seriesset")
264  return seriesset_();
265  raise("invalid labelset name: ", str_escape(ls));
266  }
267 
268  std::shared_ptr<ast_node> context_parser::weightset_()
269  {
270  return weightset_(word_());
271  }
272 
273  std::shared_ptr<ast_node>
274  context_parser::weightset_(const std::string& ws)
275  {
276  if (has(weightsets_, ws))
277  return std::make_shared<weightset>(ws);
278  else if (ws == "expressionset")
279  return expressionset_();
280  else if (ws == "seriesset")
281  return seriesset_();
282  else if (ws == "polynomialset")
283  return polynomialset_();
284  else if (ws == "lat")
285  return tupleset_();
286  else
287  raise("invalid weightset name: ", str_escape(ws));
288  }
289 
290  std::shared_ptr<automaton>
292  {
293  std::shared_ptr<automaton> res = nullptr;
294  // focus_automaton<TapeNum, Aut>.
295  if (prefix == "focus_automaton")
296  {
297  eat(is_, '<');
298  res = std::make_shared<automaton>(prefix,
299  std::make_shared<other>(word_()));
300  eat(is_, ',');
301  res->get_content().emplace_back(automaton_(word_()));
302  eat(is_, '>');
303  }
304  // xxx_automaton<Aut>.
305  else if (prefix == "delay_automaton"
306  || prefix == "determinized_automaton"
307  || prefix == "detweighted_automaton"
308  || prefix == "expression_automaton"
309  || prefix == "filter_automaton"
310  || prefix == "name_automaton"
311  || prefix == "pair_automaton"
312  || prefix == "partition_automaton"
313  || prefix == "permutation_automaton"
314  || prefix == "scc_automaton"
315  || prefix == "synchronized_automaton"
316  || prefix == "transpose_automaton")
317  {
318  eat(is_, '<');
319  res = std::make_shared<automaton>(prefix,
320  automaton_(word_()));
321  eat(is_, '>');
322  }
323  // mutable_automaton<Context>.
324  else if (prefix == "mutable_automaton")
325  {
326  eat(is_, '<');
327  res = std::make_shared<automaton>(prefix,
328  context_());
329  eat(is_, '>');
330  }
331  // xxx_automaton<Aut...>.
332  else if (prefix == "product_automaton"
333  || prefix == "tuple_automaton")
334  {
335  eat(is_, '<');
336  res = std::make_shared<automaton>(prefix,
337  automaton_(word_()));
338  while (is_.peek() == ',')
339  {
340  eat(is_, ',');
341  res->get_content().emplace_back(automaton_(word_()));
342  }
343  eat(is_, '>');
344  }
345  else
346  raise("invalid automaton name: ", str_escape(prefix));
347  return res;
348  }
349 
350  std::shared_ptr<tuple>
352  {
353  eat(is_, '<');
354  typename tuple::value_t res;
355  res.emplace_back(any_());
356  while (is_.peek() == ',')
357  {
358  eat(is_, ',');
359  res.emplace_back(any_());
360  }
361  eat(is_, '>');
362  return std::make_shared<tuple>(res);
363  }
364 
365  std::shared_ptr<tupleset>
367  {
368  eat(is_, '<');
369  typename tupleset::value_t res;
370  res.emplace_back(labelset_or_weightset_());
371  while (is_.peek() == ',')
372  {
373  eat(is_, ',');
374  res.emplace_back(labelset_or_weightset_());
375  }
376  eat(is_, '>');
377  return std::make_shared<tupleset>(res);
378  }
379 
380  std::shared_ptr<expressionset>
382  {
383  eat(is_, '<');
384  auto context = context_();
385  eat(is_, '>');
386  auto ids = rat::identities{};
387  if (is_.peek() == '(')
388  {
389  eat(is_, '(');
390  is_ >> ids;
391  eat(is_, ')');
392  }
393  return std::make_shared<expressionset>(context, ids);
394  }
395 
396  std::shared_ptr<expressionset>
398  {
399  eat(is_, '<');
400  auto context = context_();
401  eat(is_, '>');
402  return std::make_shared<expressionset>(context,
404  }
405 
406  std::shared_ptr<expansionset> context_parser::expansionset_()
407  {
408  eat(is_, '<');
409  eat(is_, "expressionset");
410  auto res = std::make_shared<expansionset>(expressionset_());
411  eat(is_, '>');
412  return res;
413  }
414 
415  std::shared_ptr<polynomialset> context_parser::polynomialset_()
416  {
417  eat(is_, '<');
418  auto res = std::make_shared<polynomialset>(context_());
419  eat(is_, '>');
420  return res;
421  }
422  }
423 }
std::shared_ptr< expressionset > expressionset_()
"expressionset" "\<" "\>", possibly followed by identities.
std::set< std::string > labelsets_
The set of weightset names.
std::shared_ptr< ast_node > labelset_or_weightset_()
|
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Definition: escape.cc:43
std::shared_ptr< ast_node > any_()
Accept anything.
std::shared_ptr< const genset > genset_()
A generator set (e.g., char_letters(abc) or char).
std::shared_ptr< const detail::context_base > context
A dyn::context.
Definition: fwd.hh:41
std::shared_ptr< automaton > automaton_(std::string prefix)
"\<" "\>".
static void check_eof(std::istream &is, std::shared_ptr< ast_node > res)
We managed to read res in is, check that is is finished.
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:372
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
std::vector< std::shared_ptr< ast_node >> value_t
Definition: type-ast.hh:61
std::shared_ptr< ast_node > parse_context()
Accept only a valid context.
std::string parameters_()
The next parameters in the stream.
std::shared_ptr< ast_node > labelset_()
.
std::shared_ptr< ast_node > weightset_()
.
std::set< std::string > weightsets_
The set of terminal weightset names.
std::shared_ptr< tuple > tuple_()
"\<" ( ",")* "\>".
Traditional plus distribution. Used for series identities.
Definition: identities.hh:42
std::shared_ptr< tupleset > tupleset_()
"\<" ( | ",")+ "\>".
static identities ids(const driver &d)
Get the identities of the driver.
Definition: parse.cc:87
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
std::shared_ptr< context > context_()
, .
std::vector< std::shared_ptr< ast_node >> value_t
Definition: type-ast.hh:88
An expressionset can implement several different sets of identities on expressions.
Definition: identities.hh:21
std::shared_ptr< ast_node > parse()
Accept anything.
std::shared_ptr< expansionset > expansionset_()
"expansionset" "\<" "\>".
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Definition: deque.hh:13
auto prefix(const Aut &aut) -> decltype(::vcsn::copy(aut))
Definition: prefix.hh:69
ATTRIBUTE_NORETURN void fail_reading(std::istream &is, Args &&...args)
Throw an exception after failing to read from is.
Definition: stream.hh:62
Indentation relative functions.
std::shared_ptr< expressionset > seriesset_()
No optional argument.
std::shared_ptr< polynomialset > polynomialset_()
"polynomialset" "\<" "\>".
std::istringstream & is_
The stream we are parsing.
std::string word_()
The next word in the stream.