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