Vcsn  2.3a
Be Rational
fado.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>
7 #include <vcsn/dyn/algos.hh>
8 #include <vcsn/dyn/automaton.hh>
9 #include <vcsn/misc/stream.hh>
10 #include <vcsn/misc/symbol.hh>
11 
12 namespace vcsn
13 {
14  namespace dyn
15  {
16 
17  /*-----------------.
18  | read_fado(aut). |
19  `-----------------*/
20  namespace
21  {
23  std::string read_id(std::istream& is)
24  {
25  std::string res;
26  int c;
27  skip_space(is);
28  while ((c = is.get()) != EOF && !isspace(c))
29  {
30  if (c == '#')
31  {
32  is.unget();
33  break;
34  }
35  res += c;
36  }
37  return res;
38  }
39  }
40 
41  automaton
42  read_fado(std::istream& is)
43  {
44  std::string file = "file.fado";
45  using string_t = symbol;
46 
47  // The header (the first line) looks like:
48  //
49  // @NFA 3 4 5 * 0 1 2
50  //
51  // where 0 1 2 are initial states, and 3 4 5 are final states.
52  //
53  // The star is optional, in which case the initial state
54  // is the src state of the first transition.
55 
56  auto edit = vcsn::lazy_automaton_editor{};
57  edit.open(true);
58 
59  // Whether we process initial states / first line.
60  bool init = false;
61  bool first = true;
62  bool is_transducer = false;
63  bool is_dfa = false;
64  std::string line, state;
65  while (is.good())
66  {
67  std::getline(is, line, '\n');
68  std::istringstream ss{line};
69  state = read_id(ss);
70  if (state.empty()) // Empty line or comments
71  continue;
72 
73  if (first)
74  {
75  is_transducer = state == "@Transducer";
76  is_dfa = state == "@DFA";
77  if (!is_transducer && !is_dfa && state != "@NFA")
78  raise(file, ": bad automaton kind in first line: ", state);
79 
80  while (!(state = read_id(ss)).empty())
81  {
82  if (state == "$") // Alphabet declaration
83  break;
84  else if (state == "*")
85  {
86  require(!is_dfa, "fado: invalid '*' for DFA"
87  " in first line");
88  require(!init, "fado: multiple '*' in first line");
89  init = true;
90  }
91  else if (init)
92  edit.add_initial(string_t{state});
93  else
94  edit.add_final(string_t{state});
95  }
96  first = false;
97  }
98  else
99  {
100  // Line: Source InputLabel [OutputLabel] Destination.
101  auto s1 = string_t{state};
102  auto l1 = string_t{read_id(ss)};
103  auto l2 = string_t{read_id(ss)};
104  auto s2 = string_t{read_id(ss)};
105  // First state is our initial state if not declared before by "*".
106  if (!init)
107  {
108  edit.add_initial(s1);
109  init = true;
110  }
111  if (l1 == "@epsilon")
112  {
113  require(!is_dfa, "fado: unexpected '@epsilon' in DFA, in: ",
114  s1, ' ', l1, ' ',
115  l2, s2.get().empty() ? "" : " ",
116  s2);
117  l1 = "\\e";
118  }
119  if (is_transducer)
120  {
121  if (l2 == "@epsilon")
122  l2 = "\\e";
123  edit.add_transition(s1, s2, l1, l2, string_t{});
124  }
125  else
126  {
127  require(s2 == "",
128  "fado: unexpected trailing characters after: ", s1,
129  ' ', l1, ' ', l2);
130  edit.add_transition(s1, l2, l1);
131  }
132  }
133  }
134  return edit.result();
135  }
136  }// dyn::
137 }// vcsn::
void skip_space(std::istream &is)
Ignore spaces.
Definition: stream.cc:163
Definition: a-star.hh:8
return res
Definition: multiply.hh:398
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
symbol string_t
Definition: parse.hh:66
automaton read_fado(std::istream &is)
Definition: fado.cc:42
Build an automaton with unknown context.
bool open(bool o)
Whether unknown letters should be added, or rejected.