1 // lookahead-filter.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 (at) google.com (Michael Riley) 17 // 18 // \file 19 // Composition filters to support lookahead matchers, useful for improving 20 // composition efficiency with certain inputs. 21 22 #ifndef FST_LIB_LOOKAHEAD_FILTER_H__ 23 #define FST_LIB_LOOKAHEAD_FILTER_H__ 24 25 #include <vector> 26 using std::vector; 27 28 #include <fst/fst.h> 29 #include <fst/lookahead-matcher.h> 30 31 32 namespace fst { 33 34 // Identifies and verifies the capabilities of the matcher to be used for 35 // lookahead with the composition filters below. This version is passed 36 // the matchers. 37 template <class M1, class M2> 38 MatchType LookAheadMatchType(const M1 &m1, const M2 &m2) { 39 MatchType type1 = m1.Type(false); 40 MatchType type2 = m2.Type(false); 41 if (type1 == MATCH_OUTPUT && 42 m1.Flags() & kOutputLookAheadMatcher) 43 return MATCH_OUTPUT; 44 else if (type2 == MATCH_INPUT && 45 m2.Flags() & kInputLookAheadMatcher) 46 return MATCH_INPUT; 47 else if (m1.Flags() & kOutputLookAheadMatcher && 48 m1.Type(true) == MATCH_OUTPUT) 49 return MATCH_OUTPUT; 50 else if (m2.Flags() & kInputLookAheadMatcher && 51 m2.Type(true) == MATCH_INPUT) 52 return MATCH_INPUT; 53 else 54 return MATCH_NONE; 55 } 56 57 // Identifies and verifies the capabilities of the matcher to be used for 58 // lookahead with the composition filters below. This version uses the 59 // Fst's default matchers. 60 template <class Arc> 61 MatchType LookAheadMatchType(const Fst<Arc> &fst1, const Fst<Arc> &fst2) { 62 LookAheadMatcher< Fst <Arc> > matcher1(fst1, MATCH_OUTPUT); 63 LookAheadMatcher< Fst <Arc> > matcher2(fst2, MATCH_INPUT); 64 return LookAheadMatchType(matcher1, matcher2); 65 } 66 67 // 68 // LookAheadSelector - a helper class for selecting among possibly 69 // distinct FST and matcher types w/o using a common base class. This 70 // lets us avoid virtual function calls. 71 // 72 73 // Stores and returns the appropriate FST and matcher for lookahead. 74 // It is templated on the matcher types. General case has no methods 75 // since not currently supported. 76 template <class M1, class M2, MatchType MT> 77 class LookAheadSelector { 78 }; 79 80 // Stores and returns the appropriate FST and matcher for lookahead. 81 // Specialized for two matchers of same type with the (match) 'type' 82 // arg determining which is used for lookahead. 83 template <class M, MatchType MT> 84 class LookAheadSelector<M, M, MT> { 85 public: 86 typedef typename M::Arc Arc; 87 typedef typename M::FST F; 88 89 LookAheadSelector(M *lmatcher1, M *lmatcher2, MatchType type) 90 : lmatcher1_(lmatcher1->Copy()), 91 lmatcher2_(lmatcher2->Copy()), 92 type_(type) {} 93 94 LookAheadSelector(const LookAheadSelector<M, M, MT> &selector) 95 : lmatcher1_(selector.lmatcher1_->Copy()), 96 lmatcher2_(selector.lmatcher2_->Copy()), 97 type_(selector.type_) {} 98 99 ~LookAheadSelector() { 100 delete lmatcher1_; 101 delete lmatcher2_; 102 } 103 104 const F &GetFst() const { 105 return type_ == MATCH_OUTPUT ? lmatcher2_->GetFst() : 106 lmatcher1_->GetFst(); 107 } 108 109 M *GetMatcher() const { 110 return type_ == MATCH_OUTPUT ? lmatcher1_ : lmatcher2_; 111 } 112 113 private: 114 M *lmatcher1_; 115 M *lmatcher2_; 116 MatchType type_; 117 118 void operator=(const LookAheadSelector<M, M, MT> &); // disallow 119 }; 120 121 // Stores and returns the appropriate FST and matcher for lookahead. 122 // Specialized for lookahead on input labels. 123 template <class M1, class M2> 124 class LookAheadSelector<M1, M2, MATCH_INPUT> { 125 public: 126 typedef typename M1::FST F1; 127 128 LookAheadSelector(M1 *lmatcher1, M2 *lmatcher2, MatchType) 129 : fst_(lmatcher1->GetFst().Copy()), 130 lmatcher_(lmatcher2->Copy()) {} 131 132 LookAheadSelector(const LookAheadSelector<M1, M2, MATCH_INPUT> &selector) 133 : fst_(selector.fst_->Copy()), 134 lmatcher_(selector.lmatcher_->Copy()) {} 135 136 ~LookAheadSelector() { 137 delete lmatcher_; 138 delete fst_; 139 } 140 141 const F1 &GetFst() const { return *fst_; } 142 143 M2 *GetMatcher() const { return lmatcher_; } 144 145 private: 146 const F1 *fst_; 147 M2 *lmatcher_; 148 149 void operator=(const LookAheadSelector<M1, M2, MATCH_INPUT> &); // disallow 150 }; 151 152 153 // Stores and returns the appropriate FST and matcher for lookahead. 154 // Specialized for lookahead on output labels. 155 template <class M1, class M2> 156 class LookAheadSelector<M1, M2, MATCH_OUTPUT> { 157 public: 158 typedef typename M2::FST F2; 159 160 LookAheadSelector(M1 *lmatcher1, M2 *lmatcher2, MatchType) 161 : fst_(lmatcher2->GetFst().Copy()), 162 lmatcher_(lmatcher1->Copy()) {} 163 164 LookAheadSelector(const LookAheadSelector<M1, M2, MATCH_OUTPUT> &selector) 165 : fst_(selector.fst_->Copy()), 166 lmatcher_(selector.lmatcher_->Copy()) {} 167 168 ~LookAheadSelector() { 169 delete lmatcher_; 170 delete fst_; 171 } 172 173 const F2 &GetFst() const { return *fst_; } 174 175 M1 *GetMatcher() const { return lmatcher_; } 176 177 private: 178 const F2 *fst_; 179 M1 *lmatcher_; 180 181 void operator=(const LookAheadSelector<M1, M2, MATCH_OUTPUT> &); // disallow 182 }; 183 184 // This filter uses a lookahead matcher in FilterArc(arc1, arc2) to 185 // examine the future of the composition state (arc1.nextstate, 186 // arc2.nextstate), blocking moving forward when its determined to be 187 // non-coaccessible. It is templated on an underlying filter, 188 // typically the epsilon filter. Which matcher is the lookahead 189 // matcher is determined by the template argument MT unless it is 190 // MATCH_BOTH. In that case, both matcher arguments must be lookahead 191 // matchers of the same type and one will be selected by 192 // LookAheadMatchType() based on their capability. 193 template <class F, 194 class M1 = LookAheadMatcher<typename F::FST1>, 195 class M2 = M1, 196 MatchType MT = MATCH_BOTH> 197 class LookAheadComposeFilter { 198 public: 199 typedef typename F::FST1 FST1; 200 typedef typename F::FST2 FST2; 201 typedef typename F::Arc Arc; 202 typedef typename F::Matcher1 Matcher1; 203 typedef typename F::Matcher2 Matcher2; 204 typedef typename F::FilterState FilterState; 205 typedef LookAheadComposeFilter<F, M1, M2, MT> Filter; 206 207 typedef typename Arc::StateId StateId; 208 typedef typename Arc::Label Label; 209 typedef typename Arc::Weight Weight; 210 211 LookAheadComposeFilter(const FST1 &fst1, const FST2 &fst2, 212 M1 *matcher1, M2 *matcher2) 213 : filter_(fst1, fst2, matcher1, matcher2), 214 lookahead_type_(MT == MATCH_BOTH ? 215 LookAheadMatchType(*filter_.GetMatcher1(), 216 *filter_.GetMatcher2()) : MT), 217 selector_(filter_.GetMatcher1(), filter_.GetMatcher2(), 218 lookahead_type_), 219 flags_(lookahead_type_ == MATCH_OUTPUT ? 220 filter_.GetMatcher1()->Flags() : 221 filter_.GetMatcher2()->Flags()) { 222 if (lookahead_type_ == MATCH_NONE) { 223 FSTERROR() << "LookAheadComposeFilter: 1st argument cannot " 224 << "match/look-ahead on output labels and 2nd argument " 225 << "cannot match/look-ahead on input labels."; 226 } 227 selector_.GetMatcher()->InitLookAheadFst(selector_.GetFst()); 228 } 229 230 LookAheadComposeFilter(const LookAheadComposeFilter<F, M1, M2, MT> &filter, 231 bool safe = false) 232 : filter_(filter.filter_, safe), 233 lookahead_type_(filter.lookahead_type_), 234 selector_(filter_.GetMatcher1(), filter_.GetMatcher2(), 235 lookahead_type_), 236 flags_(filter.flags_) { 237 selector_.GetMatcher()->InitLookAheadFst(selector_.GetFst(), true); 238 } 239 240 FilterState Start() const { 241 return filter_.Start(); 242 } 243 244 void SetState(StateId s1, StateId s2, const FilterState &f) { 245 filter_.SetState(s1, s2, f); 246 } 247 248 FilterState FilterArc(Arc *arc1, Arc *arc2) const { 249 lookahead_arc_ = false; 250 251 const FilterState &f = filter_.FilterArc(arc1, arc2); 252 if (f == FilterState::NoState()) 253 return FilterState::NoState(); 254 255 return LookAheadOutput() ? LookAheadFilterArc(arc1, arc2, f) : 256 LookAheadFilterArc(arc2, arc1, f); 257 } 258 259 void FilterFinal(Weight *weight1, Weight *weight2) const { 260 filter_.FilterFinal(weight1, weight2); 261 } 262 263 // Return resp matchers. Ownership stays with filter. 264 Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); } 265 Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); } 266 267 const LookAheadSelector<Matcher1, Matcher2, MT> &Selector() const { 268 return selector_; 269 } 270 271 uint64 Properties(uint64 inprops) const { 272 uint64 outprops = filter_.Properties(inprops); 273 if (lookahead_type_ == MATCH_NONE) 274 outprops |= kError; 275 return outprops; 276 } 277 278 uint32 LookAheadFlags() const { return flags_; } 279 280 bool LookAheadArc() const { return lookahead_arc_; } 281 282 bool LookAheadOutput() const { 283 if (MT == MATCH_OUTPUT) 284 return true; 285 else if (MT == MATCH_INPUT) 286 return false; 287 else if (lookahead_type_ == MATCH_OUTPUT) 288 return true; 289 else 290 return false; 291 } 292 293 private: 294 FilterState LookAheadFilterArc(Arc *arca, Arc *arcb, 295 const FilterState &f) const { 296 Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel; 297 298 if (labela != 0 && !(flags_ & kLookAheadNonEpsilons)) 299 return f; 300 if (labela == 0 && !(flags_ & kLookAheadEpsilons)) 301 return f; 302 303 lookahead_arc_ = true; 304 selector_.GetMatcher()->SetState(arca->nextstate); 305 306 return selector_.GetMatcher()->LookAheadFst(selector_.GetFst(), 307 arcb->nextstate) ? f : 308 FilterState::NoState(); 309 } 310 311 F filter_; // Underlying filter 312 MatchType lookahead_type_; // Lookahead match type 313 LookAheadSelector<Matcher1, Matcher2, MT> selector_; 314 uint32 flags_; // Lookahead flags 315 mutable bool lookahead_arc_; // Look-ahead performed at last FilterArc()? 316 317 void operator=(const LookAheadComposeFilter<F, M1, M2> &); // disallow 318 }; 319 320 321 // This filter adds weight-pushing to a lookahead composition filter 322 // using the LookAheadWeight() method of matcher argument. It is 323 // templated on an underlying lookahead filter, typically the basic 324 // lookahead filter. Weight-pushing in composition brings weights 325 // forward as much as possible based on the lookahead information. 326 template <class F, 327 class M1 = LookAheadMatcher<typename F::FST1>, 328 class M2 = M1, 329 MatchType MT = MATCH_BOTH> 330 class PushWeightsComposeFilter { 331 public: 332 typedef typename F::FST1 FST1; 333 typedef typename F::FST2 FST2; 334 typedef typename F::Arc Arc; 335 typedef typename F::Matcher1 Matcher1; 336 typedef typename F::Matcher2 Matcher2; 337 typedef typename F::FilterState FilterState1; 338 typedef WeightFilterState<typename Arc::Weight> FilterState2; 339 typedef PairFilterState<FilterState1, FilterState2> FilterState; 340 341 typedef typename Arc::StateId StateId; 342 typedef typename Arc::Label Label; 343 typedef typename Arc::Weight Weight; 344 345 PushWeightsComposeFilter(const FST1 &fst1, const FST2 &fst2, 346 M1 *matcher1, M2 *matcher2) 347 : filter_(fst1, fst2, matcher1, matcher2), 348 f_(FilterState::NoState()) {} 349 350 PushWeightsComposeFilter(const PushWeightsComposeFilter<F, M1, M2, MT> 351 &filter, 352 bool safe = false) 353 : filter_(filter.filter_, safe), 354 f_(FilterState::NoState()) {} 355 356 FilterState Start() const { 357 return FilterState(filter_.Start(), FilterState2(Weight::One())); 358 } 359 360 void SetState(StateId s1, StateId s2, const FilterState &f) { 361 f_ = f; 362 filter_.SetState(s1, s2, f.GetState1()); 363 } 364 365 FilterState FilterArc(Arc *arc1, Arc *arc2) const { 366 const FilterState1 &f1 = filter_.FilterArc(arc1, arc2); 367 if (f1 == FilterState1::NoState()) 368 return FilterState::NoState(); 369 370 if (!(LookAheadFlags() & kLookAheadWeight)) 371 return FilterState(f1, FilterState2(Weight::One())); 372 373 const Weight &lweight = filter_.LookAheadArc() ? 374 Selector().GetMatcher()->LookAheadWeight() : Weight::One(); 375 const FilterState2 &f2 = f_.GetState2(); 376 const Weight &fweight = f2.GetWeight(); 377 378 arc2->weight = Divide(Times(arc2->weight, lweight), fweight); 379 return FilterState(f1, FilterState2(lweight)); 380 } 381 382 void FilterFinal(Weight *weight1, Weight *weight2) const { 383 filter_.FilterFinal(weight1, weight2); 384 if (!(LookAheadFlags() & kLookAheadWeight) || *weight1 == Weight::Zero()) 385 return; 386 387 const FilterState2 &f2 = f_.GetState2(); 388 const Weight &fweight = f2.GetWeight(); 389 *weight1 = Divide(*weight1, fweight); 390 } 391 // Return resp matchers. Ownership states with filter. 392 Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); } 393 Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); } 394 395 const LookAheadSelector<Matcher1, Matcher2, MT> &Selector() const { 396 return filter_.Selector(); 397 } 398 399 uint32 LookAheadFlags() const { return filter_.LookAheadFlags(); } 400 bool LookAheadArc() const { return filter_.LookAheadArc(); } 401 bool LookAheadOutput() const { return filter_.LookAheadOutput(); } 402 403 uint64 Properties(uint64 props) const { 404 return filter_.Properties(props) & kWeightInvariantProperties; 405 } 406 407 private: 408 F filter_; // Underlying filter 409 FilterState f_; // Current filter state 410 411 void operator=(const PushWeightsComposeFilter<F, M1, M2, MT> &); // disallow 412 }; 413 414 // This filter adds label-pushing to a lookahead composition filter 415 // using the LookAheadPrefix() method of the matcher argument. It is 416 // templated on an underlying filter, typically the basic lookahead 417 // or weight-pushing lookahead filter. Label-pushing in composition 418 // matches labels as early as possible based on the lookahead 419 // information. 420 template <class F, 421 class M1 = LookAheadMatcher<typename F::FST1>, 422 class M2 = M1, 423 MatchType MT = MATCH_BOTH> 424 class PushLabelsComposeFilter { 425 public: 426 typedef typename F::FST1 FST1; 427 typedef typename F::FST2 FST2; 428 typedef typename F::Arc Arc; 429 typedef typename Arc::StateId StateId; 430 typedef typename Arc::Label Label; 431 typedef typename Arc::Weight Weight; 432 433 typedef MultiEpsMatcher<typename F::Matcher1> Matcher1; 434 typedef MultiEpsMatcher<typename F::Matcher2> Matcher2; 435 typedef typename F::FilterState FilterState1; 436 typedef IntegerFilterState<typename Arc::Label> FilterState2; 437 typedef PairFilterState<FilterState1, FilterState2> FilterState; 438 439 PushLabelsComposeFilter(const FST1 &fst1, const FST2 &fst2, 440 M1 *matcher1, M2 *matcher2) 441 : filter_(fst1, fst2, matcher1, matcher2), 442 f_(FilterState::NoState()), 443 fst1_(filter_.GetMatcher1()->GetFst()), 444 fst2_(filter_.GetMatcher2()->GetFst()), 445 matcher1_(fst1_, MATCH_OUTPUT, 446 filter_.LookAheadOutput() ? kMultiEpsList : kMultiEpsLoop, 447 filter_.GetMatcher1(), 448 false), 449 matcher2_(fst2_, MATCH_INPUT, 450 filter_.LookAheadOutput() ? kMultiEpsLoop : kMultiEpsList, 451 filter_.GetMatcher2(), 452 false) {} 453 454 PushLabelsComposeFilter(const PushLabelsComposeFilter<F, M1, M2, MT> &filter, 455 bool safe = false) 456 : filter_(filter.filter_, safe), 457 f_(FilterState::NoState()), 458 fst1_(filter_.GetMatcher1()->GetFst()), 459 fst2_(filter_.GetMatcher2()->GetFst()), 460 matcher1_(fst1_, MATCH_OUTPUT, 461 filter_.LookAheadOutput() ? kMultiEpsList : kMultiEpsLoop, 462 filter_.GetMatcher1(), 463 false), 464 matcher2_(fst2_, MATCH_INPUT, 465 filter_.LookAheadOutput() ? kMultiEpsLoop : kMultiEpsList, 466 filter_.GetMatcher2(), 467 false) { 468 } 469 470 FilterState Start() const { 471 return FilterState(filter_.Start(), FilterState2(kNoLabel)); 472 } 473 474 void SetState(StateId s1, StateId s2, const FilterState &f) { 475 f_ = f; 476 filter_.SetState(s1, s2, f.GetState1()); 477 if (!(LookAheadFlags() & kLookAheadPrefix)) 478 return; 479 480 narcsa_ = LookAheadOutput() ? internal::NumArcs(fst1_, s1) 481 : internal::NumArcs(fst2_, s2); 482 483 const FilterState2 &f2 = f_.GetState2(); 484 const Label &flabel = f2.GetState(); 485 486 GetMatcher1()->ClearMultiEpsLabels(); 487 GetMatcher2()->ClearMultiEpsLabels(); 488 if (flabel != kNoLabel) { // Have a lookahead label? 489 GetMatcher1()->AddMultiEpsLabel(flabel); // Yes, make it a multi-epsilon 490 GetMatcher2()->AddMultiEpsLabel(flabel); // label so that it matches the 491 } // implicit epsilon arc to be 492 } // modified below when pushing. 493 494 FilterState FilterArc(Arc *arc1, Arc *arc2) const { 495 if (!(LookAheadFlags() & kLookAheadPrefix)) 496 return FilterState(filter_.FilterArc(arc1, arc2), 497 FilterState2(kNoLabel)); 498 499 const FilterState2 &f2 = f_.GetState2(); 500 const Label &flabel = f2.GetState(); 501 if (flabel != kNoLabel) // Have a lookahead label? 502 return LookAheadOutput() ? PushedLabelFilterArc(arc1, arc2, flabel) : 503 PushedLabelFilterArc(arc2, arc1, flabel); 504 505 const FilterState1 &f1 = filter_.FilterArc(arc1, arc2); 506 if (f1 == FilterState1::NoState()) 507 return FilterState::NoState(); 508 509 if (!filter_.LookAheadArc()) 510 return FilterState(f1, FilterState2(kNoLabel)); 511 512 return LookAheadOutput() ? PushLabelFilterArc(arc1, arc2, f1) : 513 PushLabelFilterArc(arc2, arc1, f1); 514 } 515 516 void FilterFinal(Weight *weight1, Weight *weight2) const { 517 filter_.FilterFinal(weight1, weight2); 518 if (!(LookAheadFlags() & kLookAheadPrefix) || 519 *weight1 == Weight::Zero()) 520 return; 521 522 const FilterState2 &f2 = f_.GetState2(); 523 const Label &flabel = f2.GetState(); 524 if (flabel != kNoLabel) 525 *weight1 = Weight::Zero(); 526 } 527 528 // Return resp matchers. Ownership states with filter. 529 Matcher1 *GetMatcher1() { return &matcher1_; } 530 Matcher2 *GetMatcher2() { return &matcher2_; } 531 532 uint64 Properties(uint64 iprops) const { 533 uint64 oprops = filter_.Properties(iprops); 534 if (LookAheadOutput()) 535 return oprops & kOLabelInvariantProperties; 536 else 537 return oprops & kILabelInvariantProperties; 538 } 539 540 private: 541 const LookAheadSelector<typename F::Matcher1, typename F::Matcher2, MT> 542 &Selector() const { 543 return filter_.Selector(); 544 } 545 546 // Consumes an already pushed label. 547 FilterState PushedLabelFilterArc(Arc *arca, Arc *arcb, 548 Label flabel) const { 549 Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel; 550 const Label &labelb = LookAheadOutput() ? arcb->ilabel : arcb->olabel; 551 552 if (labelb != kNoLabel) { 553 return FilterState::NoState(); // Block non- (multi-) epsilon label 554 } else if (labela == flabel) { 555 labela = 0; // Convert match to multi-eps to eps 556 return Start(); 557 } else if (labela == 0) { 558 if (narcsa_ == 1) 559 return f_; // Take eps; keep state w/ label 560 Selector().GetMatcher()->SetState(arca->nextstate); 561 if (Selector().GetMatcher()->LookAheadLabel(flabel)) 562 return f_; // Take eps; keep state w/ label 563 else 564 return FilterState::NoState(); // Block non-coaccessible path 565 } else { 566 return FilterState::NoState(); // Block mismatch to multi-eps label 567 } 568 } 569 570 // Pushes a label forward when possible. 571 FilterState PushLabelFilterArc(Arc *arca, Arc *arcb, 572 const FilterState1 &f1) const { 573 Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel; 574 const Label &labelb = LookAheadOutput() ? arcb->olabel : arcb->ilabel; 575 576 if (labelb != 0) // No place to push. 577 return FilterState(f1, FilterState2(kNoLabel)); 578 if (labela != 0 && // Wrong lookahead prefix type? 579 LookAheadFlags() & kLookAheadNonEpsilonPrefix) 580 return FilterState(f1, FilterState2(kNoLabel)); 581 582 Arc larc(kNoLabel, kNoLabel, Weight::Zero(), kNoStateId); 583 584 if (Selector().GetMatcher()->LookAheadPrefix(&larc)) { // Have prefix arc? 585 labela = LookAheadOutput() ? larc.ilabel : larc.olabel; 586 arcb->ilabel = larc.ilabel; // Yes, go forward on that arc, 587 arcb->olabel = larc.olabel; // thus pushing the label. 588 arcb->weight = Times(arcb->weight, larc.weight); 589 arcb->nextstate = larc.nextstate; 590 return FilterState(f1, FilterState2(labela)); 591 } else { 592 return FilterState(f1, FilterState2(kNoLabel)); 593 } 594 } 595 596 uint32 LookAheadFlags() const { return filter_.LookAheadFlags(); } 597 bool LookAheadArc() const { return filter_.LookAheadArc(); } 598 bool LookAheadOutput() const { return filter_.LookAheadOutput(); } 599 600 F filter_; // Underlying filter 601 FilterState f_ ; // Current filter state 602 const FST1 &fst1_; 603 const FST2 &fst2_; 604 Matcher1 matcher1_; // Multi-epsilon matcher for fst1 605 Matcher2 matcher2_; // Multi-epsilon matcher for fst2 606 ssize_t narcsa_; // Number of arcs leaving look-ahead match FST 607 608 void operator=(const PushLabelsComposeFilter<F, M1, M2, MT> &); // disallow 609 }; 610 611 // 612 // CONVENIENCE CLASS useful for setting up composition with a default 613 // look-ahead matcher and filter. 614 // 615 616 template <class A, MatchType type> // MATCH_NONE 617 class DefaultLookAhead { 618 public: 619 typedef Matcher< Fst<A> > M; 620 typedef SequenceComposeFilter<M> ComposeFilter; 621 typedef M FstMatcher; 622 }; 623 624 // Specializes for MATCH_INPUT to allow lookahead. 625 template <class A> 626 class DefaultLookAhead<A, MATCH_INPUT> { 627 public: 628 typedef LookAheadMatcher< Fst<A> > M; 629 typedef SequenceComposeFilter<M> SF; 630 typedef LookAheadComposeFilter<SF, M> ComposeFilter; 631 typedef M FstMatcher; 632 }; 633 634 // Specializes for MATCH_OUTPUT to allow lookahead. 635 template <class A> 636 class DefaultLookAhead<A, MATCH_OUTPUT> { 637 public: 638 typedef LookAheadMatcher< Fst<A> > M; 639 typedef AltSequenceComposeFilter<M> SF; 640 typedef LookAheadComposeFilter<SF, M> ComposeFilter; 641 typedef M FstMatcher; 642 }; 643 644 // Specializes for StdArc to allow weight and label pushing. 645 template <> 646 class DefaultLookAhead<StdArc, MATCH_INPUT> { 647 public: 648 typedef StdArc A; 649 typedef LookAheadMatcher< Fst<A> > M; 650 typedef SequenceComposeFilter<M> SF; 651 typedef LookAheadComposeFilter<SF, M> LF; 652 typedef PushWeightsComposeFilter<LF, M> WF; 653 typedef PushLabelsComposeFilter<WF, M> ComposeFilter; 654 typedef M FstMatcher; 655 }; 656 657 // Specializes for StdArc to allow weight and label pushing. 658 template <> 659 class DefaultLookAhead<StdArc, MATCH_OUTPUT> { 660 public: 661 typedef StdArc A; 662 typedef LookAheadMatcher< Fst<A> > M; 663 typedef AltSequenceComposeFilter<M> SF; 664 typedef LookAheadComposeFilter<SF, M> LF; 665 typedef PushWeightsComposeFilter<LF, M> WF; 666 typedef PushLabelsComposeFilter<WF, M> ComposeFilter; 667 typedef M FstMatcher; 668 }; 669 670 // Specializes for LogArc to allow weight and label pushing. 671 template <> 672 class DefaultLookAhead<LogArc, MATCH_INPUT> { 673 public: 674 typedef LogArc A; 675 typedef LookAheadMatcher< Fst<A> > M; 676 typedef SequenceComposeFilter<M> SF; 677 typedef LookAheadComposeFilter<SF, M> LF; 678 typedef PushWeightsComposeFilter<LF, M> WF; 679 typedef PushLabelsComposeFilter<WF, M> ComposeFilter; 680 typedef M FstMatcher; 681 }; 682 683 // Specializes for LogArc to allow weight and label pushing. 684 template <> 685 class DefaultLookAhead<LogArc, MATCH_OUTPUT> { 686 public: 687 typedef LogArc A; 688 typedef LookAheadMatcher< Fst<A> > M; 689 typedef AltSequenceComposeFilter<M> SF; 690 typedef LookAheadComposeFilter<SF, M> LF; 691 typedef PushWeightsComposeFilter<LF, M> WF; 692 typedef PushLabelsComposeFilter<WF, M> ComposeFilter; 693 typedef M FstMatcher; 694 }; 695 696 } // namespace fst 697 698 #endif // FST_LIB_LOOKAHEAD_FILTER_H__ 699