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