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