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