Vcsn  2.8
Be Rational
edit-automaton.cc
Go to the documentation of this file.
1 #include <cctype>
2 #include <regex>
3 
5 #include <vcsn/dyn/algos.hh>
6 #include <vcsn/dyn/automaton.hh>
7 #include <vcsn/misc/builtins.hh>
8 
9 namespace vcsn
10 {
11 
12  namespace
13  {
14  using labelset_type = lazy_automaton_editor::labelset_type;
15 
16  labelset_type type(lazy_automaton_editor::string_t lbl)
17  {
18  if (lbl.get().empty())
19  return labelset_type::empty;
20  else if (lbl == "\\e")
21  return labelset_type::lan;
22  else if (1 < lbl.get().size())
23  return labelset_type::law;
24  else
25  return labelset_type::lal;
26  }
27 
28  std::string to_string(labelset_type l)
29  {
30  switch (l)
31  {
32  case labelset_type::empty: return {};
33  case labelset_type::lal: return "lal<char>";
34  case labelset_type::lan: return "lan<char>";
35  case labelset_type::law: return "law<char>";
36  }
38  }
39 
42  {
43  if (s == "\\e"
44  || s.get().size() == 1 && std::isalnum(s.get()[0]))
45  return s;
46  else
47  {
48  // Backslash backslashes and quotes.
49  static auto re = std::regex{"['\\\\]"};
50  return ("'"
51  + std::regex_replace(s.get(), re, "\\$&")
52  + "'");
53  }
54  }
55 
56  std::string weight(const std::string& w)
57  {
58  return w.empty() ? std::string{} : "<" + w + ">";
59 
60  }
61  }
62 
63 
64  /*------------------------.
65  | lazy_automaton_editor. |
66  `------------------------*/
67 
68  void
70  {
71  if (!w.get().empty())
72  {
73  weighted_ = true;
74  if (!real_
75  && w.get().find('.') != std::string::npos)
76  real_ = true;
77  }
78  }
79 
80  void
82  {
83  initial_states_.emplace_back(s, w);
85  }
86 
87  void
89  {
90  final_states_.emplace_back(s, w);
92  }
93 
94 
95 
97  void
99  string_t dst,
100  string_t lbl1,
101  string_t lbl2,
103  {
104  input_type_ = std::max(input_type_, type(lbl1));
105 
106  if (lbl2.get().empty())
107  lbl1 = quote(lbl1);
108  else
109  {
110  // Turn into a multiple-tape label.
111  output_type_ = std::max(output_type_, type(lbl2));
112  lbl1 = quote(lbl1) + "|" + quote(lbl2);
113  }
114  transitions_.emplace_back(src, dst, lbl1, weight);
115 
116  register_weight_(weight);
117  }
118 
120  void
122  string_t dst,
123  string_t lbl,
125  {
126  add_transition(src, dst, lbl, string_t{}, weight);
127  }
128 
129  bool
131  {
132  std::swap(open_, o);
133  return o;
134  }
135 
136  void
138  {
139  transitions_.clear();
140  final_states_.clear();
141  initial_states_.clear();
142  }
143 
145  {
146  // If there are no transitions (e.g., standard("\e")), consider
147  // the labelset is a plain lal.
148  auto res
151  : input_type_);
153  res = "lat<" + res + "," + to_string(output_type_) + '>';
154  res += ", ";
155  switch (weightset_type_)
156  {
158  res += "log";
159  break;
161  res += (real_ ? "r"
162  : weighted_ ? "z"
163  : "b");
164  break;
166  res += (real_ ? "rmin"
167  : weighted_ ? "zmin"
168  : "b");
169  break;
170  }
171  return res;
172  }
173 
175  {
176  auto c = vcsn::dyn::make_context(ctx.empty() ? result_context() : ctx);
177  auto edit = vcsn::dyn::make_automaton_editor(c);
178  edit->open(open_);
179 
180  for (auto t: transitions_)
181  try
182  {
183  edit->add_transition(std::get<0>(t), std::get<1>(t),
184  std::get<2>(t), std::get<3>(t));
185  }
186  catch (const std::runtime_error& e)
187  {
188  raise(e, " while adding transition: (", std::get<0>(t), ", ",
189  weight(std::get<3>(t)), std::get<2>(t), ", ",
190  std::get<1>(t), ')');
191  }
192 
193  for (auto p: initial_states_)
194  try
195  {
196  edit->add_initial(p.first, p.second);
197  }
198  catch (const std::runtime_error& e)
199  {
200  raise(e, " while setting initial state: ", weight(p.second),
201  p.first);
202  }
203 
204  for (auto p: final_states_)
205  try
206  {
207  edit->add_final(p.first, p.second);
208  }
209  catch (const std::runtime_error& e)
210  {
211  raise(e, " while setting final state: ", weight(p.second), p.first);
212  }
213 
214  return edit->result();
215  }
216 }
A dyn automaton.
Definition: automaton.hh:17
void add_final(string_t s, string_t w=string_t{})
Add s as a final state.
dyn::automaton result(const std::string &ctx={})
Return the built automaton.
std::vector< transition_t > transitions_
void add_initial(string_t s, string_t w=string_t{})
Add s as an initial state.
bool real_
Whether we saw a period in a the weight.
context make_context(const std::string &name)
Build a context from its name.
Definition: others.cc:96
bool open_
Whether the labelset is open.
std::vector< std::pair< string_t, string_t > > initial_states_
The collected initial states: (State, Weight).
void register_weight_(string_t w)
Record that this weight was seen.
bool weighted_
Whether we saw a non-empty weight.
std::string quote(const std::string &s)
Turn a label into a parsable label: escape special characters.
Definition: trie.hh:23
labelset_type
Labelset types, increasing generality.
std::string result_context() const
Return the context that was inferred.
Definition: a-star.hh:8
std::vector< std::pair< string_t, string_t > > final_states_
The collected final states: (State, Weight).
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:238
void reset()
Get ready to build another automaton.
void swap(config::value &first, config::value &second)
weightset_type weightset_type_
The weightset scale.
bool open(bool o)
Whether unknown letters should be added, or rejected.
void add_transition(string_t src, string_t dst, string_t lbl, string_t w=string_t{})
Add an acceptor transition from src to dst, labeled by lbl.
labelset_type input_type_
Labelset type for input tape.
automaton_editor::string_t string_t
A hash-cons&#39;ed string type.
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
automaton_editor * make_automaton_editor(const context &ctx)
Build an automaton editor from its context.
labelset_type output_type_
Labelset type for output tape.
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:13
value_impl< detail::weight_tag > weight
Definition: fwd.hh:34
return res
Definition: multiply.hh:399