d692accd3264d555e8b066b651598403252c40a3
[platform/upstream/openfst.git] / src / bin / fstreplace.cc
1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
3 //
4 // Performs the dynamic replacement of arcs in one FST with another FST,
5 // allowing for the definition of FSTs analogous to RTNs.
6
7 #include <cstring>
8
9 #include <string>
10 #include <vector>
11
12 #include <fst/script/getters.h>
13 #include <fst/script/replace.h>
14
15 DEFINE_string(call_arc_labeling, "input",
16               "Which labels to make non-epsilon on the call arc. "
17               "One of: \"input\" (default), \"output\", \"both\", \"neither\"");
18 DEFINE_string(return_arc_labeling, "neither",
19               "Which labels to make non-epsilon on the return arc. "
20               "One of: \"input\", \"output\", \"both\", \"neither\" (default)");
21 DEFINE_int64(return_label, 0, "Label to put on return arc");
22 DEFINE_bool(epsilon_on_replace, false, "Call/return arcs are epsilon arcs?");
23
24 int main(int argc, char **argv) {
25   namespace s = fst::script;
26   using fst::script::FstClass;
27   using fst::script::VectorFstClass;
28   using fst::ReplaceLabelType;
29
30   string usage = "Recursively replaces FST arcs with other FST(s).\n\n"
31                  "  Usage: ";
32   usage += argv[0];
33   usage += " root.fst rootlabel [rule1.fst label1 ...] [out.fst]\n";
34
35   std::set_new_handler(FailedNewHandler);
36   SET_FLAGS(usage.c_str(), &argc, &argv, true);
37   if (argc < 4) {
38     ShowUsage();
39     return 1;
40   }
41
42   const string in_name = argv[1];
43   const string out_name = argc % 2 == 0 ? argv[argc - 1] : "";
44
45   // Replace takes ownership of the pointer of FST arrays, deleting all such
46   // pointers when the underlying ReplaceFst is destroyed.
47   auto *ifst = FstClass::Read(in_name);
48   if (!ifst) return 1;
49
50   std::vector<s::LabelFstClassPair> pairs;
51   // Note that if the root label is beyond the range of the underlying FST's
52   // labels, truncation will occur.
53   const auto root = atoll(argv[2]);
54   pairs.emplace_back(root, ifst);
55
56   for (auto i = 3; i < argc - 1; i += 2) {
57     ifst = FstClass::Read(argv[i]);
58     if (!ifst) return 1;
59     // Note that if the root label is beyond the range of the underlying FST's
60     // labels, truncation will occur.
61     const auto label = atoll(argv[i + 1]);
62     pairs.emplace_back(label, ifst);
63   }
64
65   ReplaceLabelType call_label_type;
66   if (!s::GetReplaceLabelType(FLAGS_call_arc_labeling, FLAGS_epsilon_on_replace,
67                               &call_label_type)) {
68     LOG(ERROR) << argv[0] << ": Unknown or unsupported call arc replace "
69                << "label type: " << FLAGS_call_arc_labeling;
70   }
71   ReplaceLabelType return_label_type;
72   if (!s::GetReplaceLabelType(FLAGS_return_arc_labeling,
73                               FLAGS_epsilon_on_replace, &return_label_type)) {
74     LOG(ERROR) << argv[0] << ": Unknown or unsupported return arc replace "
75                << "label type: " << FLAGS_return_arc_labeling;
76   }
77
78   s::ReplaceOptions opts(root, call_label_type, return_label_type,
79                          FLAGS_return_label);
80
81   VectorFstClass ofst(ifst->ArcType());
82   s::Replace(pairs, &ofst, opts);
83
84   return !ofst.Write(out_name);
85 }