1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// replace.h
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: riley@google.com (Michael Riley)
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Recursively replace Fst arcs with other Fst(s) returning a PDT.
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_EXTENSIONS_PDT_REPLACE_H__
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_EXTENSIONS_PDT_REPLACE_H__
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
245b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin#include <tr1/unordered_map>
255b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkinusing std::tr1::unordered_map;
265b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkinusing std::tr1::unordered_multimap;
275b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/replace.h>
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Hash to paren IDs
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <typename S>
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct ReplaceParenHash {
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t operator()(const pair<size_t, S> &p) const {
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return p.first + p.second * kPrime;
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static const size_t kPrime = 7853;
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <typename S> const size_t ReplaceParenHash<S>::kPrime;
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Builds a pushdown transducer (PDT) from an RTN specification
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// identical to that in fst/lib/replace.h. The result is a PDT
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// encoded as the FST 'ofst' where some transitions are labeled with
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// open or close parentheses. To be interpreted as a PDT, the parens
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// must balance on a path (see PdtExpand()). The open/close
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// parenthesis label pairs are returned in 'parens'.
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc>
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid Replace(const vector<pair<typename Arc::Label,
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             const Fst<Arc>* > >& ifst_array,
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             MutableFst<Arc> *ofst,
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             vector<pair<typename Arc::Label,
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             typename Arc::Label> > *parens,
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             typename Arc::Label root) {
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ofst->DeleteStates();
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  parens->clear();
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  unordered_map<Label, size_t> label2id;
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (size_t i = 0; i < ifst_array.size(); ++i)
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    label2id[ifst_array[i].first] = i;
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label max_label = kNoLabel;
695b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  size_t max_non_term_count = 0;
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
715b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  // Queue of non-terminals to replace
725b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  deque<size_t> non_term_queue;
735b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  // Map of non-terminals to replace to count
745b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  unordered_map<Label, size_t> non_term_map;
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  non_term_queue.push_back(root);
765b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  non_term_map[root] = 1;;
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // PDT state corr. to ith replace FST start state.
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  vector<StateId> fst_start(ifst_array.size(), kNoLabel);
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // PDT state, weight pairs corr. to ith replace FST final state & weights.
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  vector< vector<pair<StateId, Weight> > > fst_final(ifst_array.size());
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Builds single Fst combining all referenced input Fsts. Leaves in the
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // non-termnals for now.  Tabulate the PDT states that correspond to
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // the start and final states of the input Fsts.
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (StateId soff = 0; !non_term_queue.empty(); soff = ofst->NumStates()) {
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Label label = non_term_queue.front();
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    non_term_queue.pop_front();
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size_t fst_id = label2id[label];
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    const Fst<Arc> *ifst = ifst_array[fst_id].second;
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (StateIterator< Fst<Arc> > siter(*ifst);
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson         !siter.Done(); siter.Next()) {
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      StateId is = siter.Value();
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      StateId os = ofst->AddState();
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (is == ifst->Start()) {
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        fst_start[fst_id] = os;
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (label == root)
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->SetStart(os);
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (ifst->Final(is) != Weight::Zero()) {
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (label == root)
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->SetFinal(os, ifst->Final(is));
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        fst_final[fst_id].push_back(make_pair(os, ifst->Final(is)));
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      for (ArcIterator< Fst<Arc> > aiter(*ifst, is);
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson           !aiter.Done(); aiter.Next()) {
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Arc arc = aiter.Value();
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (max_label == kNoLabel || arc.olabel > max_label)
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          max_label = arc.olabel;
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        typename unordered_map<Label, size_t>::const_iterator it =
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            label2id.find(arc.olabel);
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (it != label2id.end()) {
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          size_t nfst_id = it->second;
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (ifst_array[nfst_id].second->Start() == -1)
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            continue;
1175b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin          size_t count = non_term_map[arc.olabel]++;
1185b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin          if (count == 0)
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            non_term_queue.push_back(arc.olabel);
1205b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin          if (count > max_non_term_count)
1215b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin            max_non_term_count = count;
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        arc.nextstate += soff;
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ofst->AddArc(os, arc);
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Changes each non-terminal transition to an open parenthesis
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // transition redirected to the PDT state that corresponds to the
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // start state of the input FST for the non-terminal. Adds close parenthesis
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // transitions from the PDT states corr. to the final states of the
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // input FST for the non-terminal to the former destination state of the
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // non-terminal transition.
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef MutableArcIterator< MutableFst<Arc> > MIter;
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef unordered_map<pair<size_t, StateId >, size_t,
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                   ReplaceParenHash<StateId> > ParenMap;
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Parenthesis pair ID per fst, state pair.
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ParenMap paren_map;
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // # of parenthesis pairs per fst.
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  vector<size_t> nparens(ifst_array.size(), 0);
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Initial open parenthesis label
1455b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  Label first_open_paren = max_label + 1;
1465b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  Label first_close_paren = max_label + max_non_term_count + 1;
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (StateIterator< Fst<Arc> > siter(*ofst);
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson       !siter.Done(); siter.Next()) {
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    StateId os = siter.Value();
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    MIter *aiter = new MIter(ofst, os);
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (size_t n = 0; !aiter->Done(); aiter->Next(), ++n) {
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Arc arc = aiter->Value();
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      typename unordered_map<Label, size_t>::const_iterator lit =
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          label2id.find(arc.olabel);
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (lit != label2id.end()) {
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        size_t nfst_id = lit->second;
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        // Get parentheses. Ensures distinct parenthesis pair per
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        // non-terminal and destination state but otherwise reuses them.
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Label open_paren = kNoLabel, close_paren = kNoLabel;
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        pair<size_t, StateId> paren_key(nfst_id, arc.nextstate);
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        typename ParenMap::const_iterator pit = paren_map.find(paren_key);
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (pit != paren_map.end()) {
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          size_t paren_id = pit->second;
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          open_paren = (*parens)[paren_id].first;
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          close_paren = (*parens)[paren_id].second;
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        } else {
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          size_t paren_id = nparens[nfst_id]++;
1705b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin          open_paren = first_open_paren + paren_id;
1715b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin          close_paren = first_close_paren + paren_id;
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          paren_map[paren_key] = paren_id;
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (paren_id >= parens->size())
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            parens->push_back(make_pair(open_paren, close_paren));
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        // Sets open parenthesis.
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        Arc sarc(open_paren, open_paren, arc.weight, fst_start[nfst_id]);
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        aiter->SetValue(sarc);
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        // Adds close parentheses.
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        for (size_t i = 0; i < fst_final[nfst_id].size(); ++i) {
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          pair<StateId, Weight> &p = fst_final[nfst_id][i];
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          Arc farc(close_paren, close_paren, p.second, arc.nextstate);
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ofst->AddArc(p.first, farc);
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (os == p.first) {  // Invalidated iterator
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            delete aiter;
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            aiter = new MIter(ofst, os);
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            aiter->Seek(n);
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    delete aiter;
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_EXTENSIONS_PDT_REPLACE_H__
202