Vcsn  2.1
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  /*------------------------.
15  | lazy_automaton_editor. |
16  `------------------------*/
17 
18  void
20  {
21  if (!w.get().empty())
22  {
23  weighted_ = true;
24  if (!real_
25  && w.get().find('.') != std::string::npos)
26  real_ = true;
27  }
28  }
29 
30  void
32  {
33  initial_states_.emplace_back(s, w);
35  }
36 
37  void
39  {
40  final_states_.emplace_back(s, w);
42  }
43 
44  namespace
45  {
46  using labelset_type = lazy_automaton_editor::labelset_type;
47 
48  labelset_type type(lazy_automaton_editor::string_t lbl)
49  {
50  if (lbl.get().empty())
51  return labelset_type::empty;
52  else if (lbl == "\\e")
53  return labelset_type::lan;
54  else if (1 < lbl.get().size())
55  return labelset_type::law;
56  else
57  return labelset_type::lal;
58  }
59 
60  std::string to_string(labelset_type l)
61  {
62  switch (l)
63  {
64  case labelset_type::empty: return {};
65  case labelset_type::lal: return "lal<char>";
66  case labelset_type::lan: return "lan<char>";
67  case labelset_type::law: return "law<char>";
68  }
70  }
71 
73  std::string quote(lazy_automaton_editor::string_t s)
74  {
75  if (s == "\\e"
76  || s.get().size() == 1 && std::isalnum(s.get()[0]))
77  return s;
78  else
79  {
80  // Backslash backslashes and quotes.
81  static auto re = std::regex{"['\\\\]"};
82  return ("'"
83  + std::regex_replace(s.get(), re, "\\$&")
84  + "'");
85  }
86  }
87  }
88 
90  void
92  string_t dst,
93  string_t lbl1,
94  string_t lbl2,
96  {
97  input_type_ = std::max(input_type_, type(lbl1));
98 
99  if (lbl2.get().empty())
100  lbl1 = quote(lbl1);
101  else
102  {
103  // Turn into a multiple-tape label.
104  output_type_ = std::max(output_type_, type(lbl2));
105  lbl1 = quote(lbl1) + "|" + quote(lbl2);
106  }
107  transitions_.emplace_back(src, dst, lbl1, weight);
108 
109  register_weight_(weight);
110  }
111 
113  void
115  string_t dst,
116  string_t lbl,
118  {
119  add_transition(src, dst, lbl, string_t{}, weight);
120  }
121 
122  bool
124  {
125  std::swap(open_, o);
126  return o;
127  }
128 
129  void
131  {
132  transitions_.clear();
133  final_states_.clear();
134  initial_states_.clear();
135  }
136 
138  {
139  // If there are no transitions (e.g., standard("\e")), consider
140  // the labelset is a plain lal.
141  auto res
144  : input_type_);
146  res = "lat<" + res + "," + to_string(output_type_) + '>';
147  res += ", ";
148  switch (weightset_type_)
149  {
151  res += "log";
152  break;
154  res += (real_ ? "r"
155  : weighted_ ? "z"
156  : "b");
157  break;
159  res += (real_ ? "rmin"
160  : weighted_ ? "zmin"
161  : "b");
162  break;
163  }
164  return res;
165  }
166 
168  {
169  auto c = vcsn::dyn::make_context(ctx.empty() ? result_context() : ctx);
170  auto edit = vcsn::dyn::make_automaton_editor(c);
171  edit->open(open_);
172 
173  for (auto t: transitions_)
174  edit->add_transition(std::get<0>(t), std::get<1>(t),
175  std::get<2>(t), std::get<3>(t));
176 
177  for (auto p: initial_states_)
178  edit->add_initial(p.first, p.second);
179 
180  for (auto p: final_states_)
181  edit->add_final(p.first, p.second);
182  return edit->result();
183  }
184 }
bool open_
Whether the labelset is open.
weightset_type weightset_type_
The weightset scale.
dyn::automaton result(const std::string &ctx={})
Return the built automaton.
labelset_type
Labelset types, increasing generality.
void register_weight_(string_t w)
Record that this weight was seen.
bool weighted_
Whether we saw a non-empty weight.
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:197
labelset_type output_type_
Labelset type for output tape.
void add_initial(string_t s, string_t w=string_t{})
Add s as an initial state.
void add_final(string_t s, string_t w=string_t{})
Add s as a final state.
automaton_editor * make_automaton_editor(const context &ctx)
Build an automatonset from its context.
labelset_type input_type_
Labelset type for input tape.
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:80
std::shared_ptr< const detail::weight_base > weight
Definition: fwd.hh:86
void reset()
Get ready to build another automaton.
std::string result_context() const
Return the context that was inferred.
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
std::vector< transition_t > transitions_
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.
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.
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
context make_context(const std::string &name)
Build a context from its name.
Definition: others.cc:97
automaton_editor::string_t string_t
A hash-cons'ed string type.
std::vector< std::pair< string_t, string_t > > initial_states_
The collected initial states: (State, Weight).
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:13
bool real_
Whether we saw a period in a the weight.