Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
efsm.cc
Go to the documentation of this file.
1 #include <fstream>
2 #include <set>
3 #include <string>
4 
5 #include <lib/vcsn/algos/fwd.hh>
8 #include <vcsn/algos/efsm.hh>
9 #include <vcsn/dyn/algos.hh>
10 #include <vcsn/dyn/automaton.hh>
11 #include <vcsn/misc/symbol.hh>
12 #include <vcsn/misc/regex.hh>
13 
14 namespace vcsn
15 {
16  namespace dyn
17  {
18  namespace
19  {
22  std::string
23  next_here_doc(std::istream& is)
24  {
25  static std::regex re("cat >\\$medir/([a-z]+)\\.[a-z]* <<\\\\EOFSM",
26  std::regex::extended);
27  std::string line;
28  std::smatch res;
29  while (is.good())
30  {
31  std::getline(is, line, '\n');
32  if (std::regex_match(line, res, re))
33  return res[1];
34  }
35  raise("invalid file: missing \"cat\" symbol");
36  }
37 
41  std::string
42  swallow_symbol_table(std::istream& is)
43  {
44  std::string res;
45  std::string line;
46  std::string val;
47  while (is.good())
48  {
49  std::getline(is, line, '\n');
50  std::istringstream ss{line};
51  ss >> res;
52  if (ss.fail())
53  continue;
54  ss >> val;
55  if (ss.fail())
56  raise("invalid file");
57  if (val == "0" || res == "EOFSM")
58  break;
59  }
60 
61  while (line != "EOFSM" && is.good())
62  std::getline(is, line, '\n');
63 
64  require(line == "EOFSM",
65  "invalid file: missing closing EOFSM");
66  return res;
67  }
68  }
69 
70 
71  automaton
72  read_efsm(std::istream& is)
73  {
74  std::string file = "file.efsm";
75  using string_t =
76  boost::flyweight<std::string, boost::flyweights::no_tracking>;
77 
78  // Whether has both isysmbols and osymbols.
79  bool is_transducer = false;
80 
81  // Look for the symbol table.
82  auto isyms = next_here_doc(is);
83  // The single piece of information we need from the symbol
84  // table: the representation of the empty word.
85  std::string ione = swallow_symbol_table(is);
86 
87  // If we had "isymbols", we now expect "osymbols".
88  std::string oone = ione;
89  if (isyms == "isymbols")
90  {
91  is_transducer = true;
92  auto osyms = next_here_doc(is);
93  require(osyms == "osymbols",
94  "invalid file: expected osymbols: ", osyms);
95  oone = swallow_symbol_table(is);
96  }
97 
99  edit.open(true);
100 
101  // The first transition also provides the initial state.
102  bool first = true;
103  auto trans = next_here_doc(is);
104  require(trans == "transitions",
105  "invalid file: expected transitions: ", trans);
106  // Line: Source Dest ILabel [OLabel] [Weight].
107  // Line: FinalState [Weight].
108  std::string line;
109  while (is.good())
110  {
111  std::getline(is, line, '\n');
112  if (line == "EOFSM")
113  break;
114  std::istringstream ss{line};
115  string_t s, d, l1, l2, w;
116  ss >> s >> d >> l1 >> l2 >> w;
117  if (first)
118  edit.add_initial(s);
119  if (l1.get().empty())
120  // FinalState [Weight]
121  edit.add_final(s, d);
122  else
123  {
124  if (l1 == ione)
125  l1 = "\\e";
126  if (is_transducer)
127  {
128  if (l2 == oone)
129  l2 = "\\e";
130  edit.add_transition(s, d, l1, l2, w);
131  }
132  else
133  {
134  // l2 is actually the weight.
135  edit.add_transition(s, d, l1, l2);
136  }
137  }
138  first = false;
139  }
140 
141  require(line == "EOFSM",
142  file, ": bad input format, missing EOFSM");
143  // Flush till EOF.
144  while (is.get() != EOF)
145  continue;
146  return edit.result();
147  }
148 
149 
150  /*------------.
151  | efsm(aut). |
152  `------------*/
153 
154  REGISTER_DEFINE(efsm);
155 
156  std::ostream&
157  efsm(const automaton& aut, std::ostream& out)
158  {
159  detail::efsm_registry().call(aut, out);
160  return out;
161  }
162  }
163 }
bool open(bool o)
Whether unknown letters should be added, or rejected.
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
void add_initial(string_t s, string_t w=string_t{})
Add s as an initial state.
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.
void add_final(string_t s, string_t w=string_t{})
Add s as a final state.
boost::flyweight< std::string, boost::flyweights::no_tracking > string_t
Definition: parse.hh:68
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:329
dyn::automaton result()
Return the built automaton.
std::ostream & efsm(const automaton &aut, std::ostream &out)
Output in Extended FSM format.
Definition: efsm.cc:157
automaton read_efsm(std::istream &is)
Definition: efsm.cc:72
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
Build an automaton with unknown context.