a6559b792d38b0eb93ae500dc3d52a6730384a32
[platform/upstream/openfst.git] / src / include / fst / script / print-impl.h
1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
3 //
4 // Stand-alone class to print out binary FSTs in the AT&T format, a helper
5 // class for fstprint.cc.
6
7 #ifndef FST_SCRIPT_PRINT_IMPL_H_
8 #define FST_SCRIPT_PRINT_IMPL_H_
9
10 #include <ostream>
11 #include <sstream>
12 #include <string>
13
14 #include <fst/fstlib.h>
15 #include <fst/util.h>
16
17 DECLARE_string(fst_field_separator);
18
19 namespace fst {
20
21 // Print a binary FST in textual format (helper class for fstprint.cc).
22 // WARNING: Stand-alone use of this class not recommended, most code should
23 // read/write using the binary format which is much more efficient.
24 template <class Arc>
25 class FstPrinter {
26  public:
27   using StateId = typename Arc::StateId;
28   using Label = typename Arc::Label;
29   using Weight = typename Arc::Weight;
30
31   FstPrinter(const Fst<Arc> &fst, const SymbolTable *isyms,
32              const SymbolTable *osyms, const SymbolTable *ssyms, bool accep,
33              bool show_weight_one, const string &field_separator,
34              const string &missing_symbol = "")
35       : fst_(fst),
36         isyms_(isyms),
37         osyms_(osyms),
38         ssyms_(ssyms),
39         accep_(accep && fst.Properties(kAcceptor, true)),
40         ostrm_(nullptr),
41         show_weight_one_(show_weight_one),
42         sep_(field_separator),
43         missing_symbol_(missing_symbol) {}
44
45   // Prints FST to an output stream.
46   void Print(std::ostream *ostrm, const string &dest) {
47     ostrm_ = ostrm;
48     dest_ = dest;
49     const auto start = fst_.Start();
50     if (start == kNoStateId) return;
51     // Initial state first.
52     PrintState(start);
53     for (StateIterator<Fst<Arc>> siter(fst_); !siter.Done(); siter.Next()) {
54       const auto s = siter.Value();
55       if (s != start) PrintState(s);
56     }
57   }
58
59  private:
60   void PrintId(StateId id, const SymbolTable *syms, const char *name) const {
61     if (syms) {
62       string symbol = syms->Find(id);
63       if (symbol == "") {
64         if (missing_symbol_ == "") {
65           FSTERROR() << "FstPrinter: Integer " << id
66                      << " is not mapped to any textual symbol"
67                      << ", symbol table = " << syms->Name()
68                      << ", destination = " << dest_;
69           symbol = "?";
70         } else {
71           symbol = missing_symbol_;
72         }
73       }
74       *ostrm_ << symbol;
75     } else {
76       *ostrm_ << id;
77     }
78   }
79
80   void PrintStateId(StateId s) const { PrintId(s, ssyms_, "state ID"); }
81
82   void PrintILabel(Label l) const { PrintId(l, isyms_, "arc input label"); }
83
84   void PrintOLabel(Label l) const { PrintId(l, osyms_, "arc output label"); }
85
86   void PrintState(StateId s) const {
87     bool output = false;
88     for (ArcIterator<Fst<Arc>> aiter(fst_, s); !aiter.Done(); aiter.Next()) {
89       const auto &arc = aiter.Value();
90       PrintStateId(s);
91       *ostrm_ << sep_;
92       PrintStateId(arc.nextstate);
93       *ostrm_ << sep_;
94       PrintILabel(arc.ilabel);
95       if (!accep_) {
96         *ostrm_ << sep_;
97         PrintOLabel(arc.olabel);
98       }
99       if (show_weight_one_ || arc.weight != Weight::One())
100         *ostrm_ << sep_ << arc.weight;
101       *ostrm_ << "\n";
102       output = true;
103     }
104     const auto weight = fst_.Final(s);
105     if (weight != Weight::Zero() || !output) {
106       PrintStateId(s);
107       if (show_weight_one_ || weight != Weight::One()) {
108         *ostrm_ << sep_ << weight;
109       }
110       *ostrm_ << "\n";
111     }
112   }
113
114   const Fst<Arc> &fst_;
115   const SymbolTable *isyms_;  // ilabel symbol table.
116   const SymbolTable *osyms_;  // olabel symbol table.
117   const SymbolTable *ssyms_;  // slabel symbol table.
118   bool accep_;                // Print as acceptor when possible?
119   std::ostream *ostrm_;       // Text FST destination.
120   string dest_;               // Text FST destination name.
121   bool show_weight_one_;      // Print weights equal to Weight::One()?
122   string sep_;                // Separator character between fields.
123   string missing_symbol_;     // Symbol to print when lookup fails (default
124                               // "" means raise error).
125                               //
126   FstPrinter(const FstPrinter &) = delete;
127   FstPrinter &operator=(const FstPrinter &) = delete;
128 };
129
130 }  // namespace fst
131
132 #endif  // FST_SCRIPT_PRINT_IMPL_H_