1// print.h
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Copyright 2005-2010 Google, Inc.
16// Author: riley@google.com (Michael Riley)
17//
18// \file
19// Stand-alone class to print out binary FSTs in the AT&T format,
20// helper class for fstprint.cc
21
22#ifndef FST_SCRIPT_PRINT_IMPL_H_
23#define FST_SCRIPT_PRINT_IMPL_H_
24
25#include <sstream>
26#include <string>
27
28#include <fst/fst.h>
29#include <fst/util.h>
30
31DECLARE_string(fst_field_separator);
32
33namespace fst {
34
35// Print a binary Fst in textual format, helper class for fstprint.cc
36// WARNING: Stand-alone use of this class not recommended, most code should
37// read/write using the binary format which is much more efficient.
38template <class A> class FstPrinter {
39 public:
40  typedef A Arc;
41  typedef typename A::StateId StateId;
42  typedef typename A::Label Label;
43  typedef typename A::Weight Weight;
44
45  FstPrinter(const Fst<A> &fst,
46             const SymbolTable *isyms,
47             const SymbolTable *osyms,
48             const SymbolTable *ssyms,
49             bool accep,
50             bool show_weight_one)
51      : fst_(fst), isyms_(isyms), osyms_(osyms), ssyms_(ssyms),
52        accep_(accep && fst.Properties(kAcceptor, true)), ostrm_(0),
53        show_weight_one_(show_weight_one) {}
54
55  // Print Fst to an output stream
56  void Print(ostream *ostrm, const string &dest) {
57    ostrm_ = ostrm;
58    dest_ = dest;
59    StateId start = fst_.Start();
60    if (start == kNoStateId)
61      return;
62    // initial state first
63    PrintState(start);
64    for (StateIterator< Fst<A> > siter(fst_);
65         !siter.Done();
66         siter.Next()) {
67      StateId s = siter.Value();
68      if (s != start)
69        PrintState(s);
70    }
71  }
72
73 private:
74  // Maximum line length in text file.
75  static const int kLineLen = 8096;
76
77  void PrintId(int64 id, const SymbolTable *syms,
78               const char *name) const {
79    if (syms) {
80      string symbol = syms->Find(id);
81      if (symbol == "") {
82        FSTERROR() << "FstPrinter: Integer " << id
83                   << " is not mapped to any textual symbol"
84                   << ", symbol table = " << syms->Name()
85                   << ", destination = " << dest_;
86        symbol = "?";
87      }
88      *ostrm_ << symbol;
89    } else {
90      *ostrm_ << id;
91    }
92  }
93
94  void PrintStateId(StateId s) const {
95     PrintId(s, ssyms_, "state ID");
96  }
97
98  void PrintILabel(Label l) const {
99     PrintId(l, isyms_, "arc input label");
100  }
101
102  void PrintOLabel(Label l) const {
103     PrintId(l, osyms_, "arc output label");
104  }
105
106  void PrintState(StateId s) const {
107    bool output = false;
108    for (ArcIterator< Fst<A> > aiter(fst_, s);
109         !aiter.Done();
110         aiter.Next()) {
111      Arc arc = aiter.Value();
112      PrintStateId(s);
113      *ostrm_ << FLAGS_fst_field_separator[0];
114      PrintStateId(arc.nextstate);
115      *ostrm_ << FLAGS_fst_field_separator[0];
116      PrintILabel(arc.ilabel);
117      if (!accep_) {
118        *ostrm_ << FLAGS_fst_field_separator[0];
119        PrintOLabel(arc.olabel);
120      }
121      if (show_weight_one_ || arc.weight != Weight::One())
122        *ostrm_ << FLAGS_fst_field_separator[0] << arc.weight;
123      *ostrm_ << "\n";
124      output = true;
125    }
126    Weight final = fst_.Final(s);
127    if (final != Weight::Zero() || !output) {
128      PrintStateId(s);
129      if (show_weight_one_ || final != Weight::One()) {
130        *ostrm_ << FLAGS_fst_field_separator[0] << final;
131      }
132      *ostrm_ << "\n";
133    }
134  }
135
136  const Fst<A> &fst_;
137  const SymbolTable *isyms_;     // ilabel symbol table
138  const SymbolTable *osyms_;     // olabel symbol table
139  const SymbolTable *ssyms_;     // slabel symbol table
140  bool accep_;                   // print as acceptor when possible
141  ostream *ostrm_;               // text FST destination
142  string dest_;                  // text FST destination name
143  bool show_weight_one_;         // print weights equal to Weight::One()
144  DISALLOW_COPY_AND_ASSIGN(FstPrinter);
145};
146
147}  // namespace fst
148
149#endif  // FST_SCRIPT_PRINT_IMPL_H_
150