| // lookahead-filter.h |
| |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // Copyright 2005-2010 Google, Inc. |
| // Author: riley@google.com (Michael Riley) |
| // |
| // \file |
| // Composition filters to support lookahead matchers, useful for improving |
| // composition efficiency with certain inputs. |
| |
| #ifndef FST_LIB_LOOKAHEAD_FILTER_H__ |
| #define FST_LIB_LOOKAHEAD_FILTER_H__ |
| |
| #include <vector> |
| using std::vector; |
| |
| #include <fst/fst.h> |
| #include <fst/lookahead-matcher.h> |
| |
| |
| namespace fst { |
| |
| // Identifies and verifies the capabilities of the matcher to be used for |
| // lookahead with the composition filters below. This version is passed |
| // the matchers. |
| template <class M1, class M2> |
| MatchType LookAheadMatchType(const M1 &m1, const M2 &m2) { |
| MatchType type1 = m1.Type(false); |
| MatchType type2 = m2.Type(false); |
| if (type1 == MATCH_OUTPUT && |
| m1.Flags() & kOutputLookAheadMatcher) |
| return MATCH_OUTPUT; |
| else if (type2 == MATCH_INPUT && |
| m2.Flags() & kInputLookAheadMatcher) |
| return MATCH_INPUT; |
| else if (m1.Flags() & kOutputLookAheadMatcher && |
| m1.Type(true) == MATCH_OUTPUT) |
| return MATCH_OUTPUT; |
| else if (m2.Flags() & kInputLookAheadMatcher && |
| m2.Type(true) == MATCH_INPUT) |
| return MATCH_INPUT; |
| else |
| return MATCH_NONE; |
| } |
| |
| // Identifies and verifies the capabilities of the matcher to be used for |
| // lookahead with the composition filters below. This version uses the |
| // Fst's default matchers. |
| template <class Arc> |
| MatchType LookAheadMatchType(const Fst<Arc> &fst1, const Fst<Arc> &fst2) { |
| LookAheadMatcher< Fst <Arc> > matcher1(fst1, MATCH_OUTPUT); |
| LookAheadMatcher< Fst <Arc> > matcher2(fst2, MATCH_INPUT); |
| return LookAheadMatchType(matcher1, matcher2); |
| } |
| |
| // |
| // LookAheadSelector - a helper class for selecting among possibly |
| // distinct FST and matcher types w/o using a common base class. This |
| // lets us avoid virtual function calls. |
| // |
| |
| // Stores and returns the appropriate FST and matcher for lookahead. |
| // It is templated on the matcher types. General case has no methods |
| // since not currently supported. |
| template <class M1, class M2, MatchType MT> |
| class LookAheadSelector { |
| }; |
| |
| // Stores and returns the appropriate FST and matcher for lookahead. |
| // Specialized for two matchers of same type with the (match) 'type' |
| // arg determining which is used for lookahead. |
| template <class M, MatchType MT> |
| class LookAheadSelector<M, M, MT> { |
| public: |
| typedef typename M::Arc Arc; |
| typedef typename M::FST F; |
| |
| LookAheadSelector(M *lmatcher1, M *lmatcher2, MatchType type) |
| : lmatcher1_(lmatcher1->Copy()), |
| lmatcher2_(lmatcher2->Copy()), |
| type_(type) {} |
| |
| LookAheadSelector(const LookAheadSelector<M, M, MT> &selector) |
| : lmatcher1_(selector.lmatcher1_->Copy()), |
| lmatcher2_(selector.lmatcher2_->Copy()), |
| type_(selector.type_) {} |
| |
| ~LookAheadSelector() { |
| delete lmatcher1_; |
| delete lmatcher2_; |
| } |
| |
| const F &GetFst() const { |
| return type_ == MATCH_OUTPUT ? lmatcher2_->GetFst() : |
| lmatcher1_->GetFst(); |
| } |
| |
| M *GetMatcher() const { |
| return type_ == MATCH_OUTPUT ? lmatcher1_ : lmatcher2_; |
| } |
| |
| private: |
| M *lmatcher1_; |
| M *lmatcher2_; |
| MatchType type_; |
| |
| void operator=(const LookAheadSelector<M, M, MT> &); // disallow |
| }; |
| |
| // Stores and returns the appropriate FST and matcher for lookahead. |
| // Specialized for lookahead on input labels. |
| template <class M1, class M2> |
| class LookAheadSelector<M1, M2, MATCH_INPUT> { |
| public: |
| typedef typename M1::FST F1; |
| |
| LookAheadSelector(M1 *lmatcher1, M2 *lmatcher2, MatchType) |
| : fst_(lmatcher1->GetFst().Copy()), |
| lmatcher_(lmatcher2->Copy()) {} |
| |
| LookAheadSelector(const LookAheadSelector<M1, M2, MATCH_INPUT> &selector) |
| : fst_(selector.fst_->Copy()), |
| lmatcher_(selector.lmatcher_->Copy()) {} |
| |
| ~LookAheadSelector() { |
| delete lmatcher_; |
| delete fst_; |
| } |
| |
| const F1 &GetFst() const { return *fst_; } |
| |
| M2 *GetMatcher() const { return lmatcher_; } |
| |
| private: |
| const F1 *fst_; |
| M2 *lmatcher_; |
| |
| void operator=(const LookAheadSelector<M1, M2, MATCH_INPUT> &); // disallow |
| }; |
| |
| |
| // Stores and returns the appropriate FST and matcher for lookahead. |
| // Specialized for lookahead on output labels. |
| template <class M1, class M2> |
| class LookAheadSelector<M1, M2, MATCH_OUTPUT> { |
| public: |
| typedef typename M2::FST F2; |
| |
| LookAheadSelector(M1 *lmatcher1, M2 *lmatcher2, MatchType) |
| : fst_(lmatcher2->GetFst().Copy()), |
| lmatcher_(lmatcher1->Copy()) {} |
| |
| LookAheadSelector(const LookAheadSelector<M1, M2, MATCH_OUTPUT> &selector) |
| : fst_(selector.fst_->Copy()), |
| lmatcher_(selector.lmatcher_->Copy()) {} |
| |
| ~LookAheadSelector() { |
| delete lmatcher_; |
| delete fst_; |
| } |
| |
| const F2 &GetFst() const { return *fst_; } |
| |
| M1 *GetMatcher() const { return lmatcher_; } |
| |
| private: |
| const F2 *fst_; |
| M1 *lmatcher_; |
| |
| void operator=(const LookAheadSelector<M1, M2, MATCH_OUTPUT> &); // disallow |
| }; |
| |
| // This filter uses a lookahead matcher in FilterArc(arc1, arc2) to |
| // examine the future of the composition state (arc1.nextstate, |
| // arc2.nextstate), blocking moving forward when its determined to be |
| // non-coaccessible. It is templated on an underlying filter, |
| // typically the epsilon filter. Which matcher is the lookahead |
| // matcher is determined by the template argument MT unless it is |
| // MATCH_BOTH. In that case, both matcher arguments must be lookahead |
| // matchers of the same type and one will be selected by |
| // LookAheadMatchType() based on their capability. |
| template <class F, |
| class M1 = LookAheadMatcher<typename F::FST1>, |
| class M2 = M1, |
| MatchType MT = MATCH_BOTH> |
| class LookAheadComposeFilter { |
| public: |
| typedef typename F::FST1 FST1; |
| typedef typename F::FST2 FST2; |
| typedef typename F::Arc Arc; |
| typedef typename F::Matcher1 Matcher1; |
| typedef typename F::Matcher2 Matcher2; |
| typedef typename F::FilterState FilterState; |
| typedef LookAheadComposeFilter<F, M1, M2, MT> Filter; |
| |
| typedef typename Arc::StateId StateId; |
| typedef typename Arc::Label Label; |
| typedef typename Arc::Weight Weight; |
| |
| LookAheadComposeFilter(const FST1 &fst1, const FST2 &fst2, |
| M1 *matcher1, M2 *matcher2) |
| : filter_(fst1, fst2, matcher1, matcher2), |
| lookahead_type_(MT == MATCH_BOTH ? |
| LookAheadMatchType(*filter_.GetMatcher1(), |
| *filter_.GetMatcher2()) : MT), |
| selector_(filter_.GetMatcher1(), filter_.GetMatcher2(), |
| lookahead_type_), |
| flags_(lookahead_type_ == MATCH_OUTPUT ? |
| filter_.GetMatcher1()->Flags() : |
| filter_.GetMatcher2()->Flags()) { |
| if (lookahead_type_ == MATCH_NONE) { |
| FSTERROR() << "LookAheadComposeFilter: 1st argument cannot " |
| << "match/look-ahead on output labels and 2nd argument " |
| << "cannot match/look-ahead on input labels."; |
| } |
| selector_.GetMatcher()->InitLookAheadFst(selector_.GetFst()); |
| } |
| |
| LookAheadComposeFilter(const LookAheadComposeFilter<F, M1, M2, MT> &filter, |
| bool safe = false) |
| : filter_(filter.filter_, safe), |
| lookahead_type_(filter.lookahead_type_), |
| selector_(filter_.GetMatcher1(), filter_.GetMatcher2(), |
| lookahead_type_), |
| flags_(filter.flags_) { |
| selector_.GetMatcher()->InitLookAheadFst(selector_.GetFst(), true); |
| } |
| |
| FilterState Start() const { |
| return filter_.Start(); |
| } |
| |
| void SetState(StateId s1, StateId s2, const FilterState &f) { |
| filter_.SetState(s1, s2, f); |
| } |
| |
| FilterState FilterArc(Arc *arc1, Arc *arc2) const { |
| lookahead_arc_ = false; |
| |
| const FilterState &f = filter_.FilterArc(arc1, arc2); |
| if (f == FilterState::NoState()) |
| return FilterState::NoState(); |
| |
| return LookAheadOutput() ? LookAheadFilterArc(arc1, arc2, f) : |
| LookAheadFilterArc(arc2, arc1, f); |
| } |
| |
| void FilterFinal(Weight *weight1, Weight *weight2) const { |
| filter_.FilterFinal(weight1, weight2); |
| } |
| |
| // Return resp matchers. Ownership stays with filter. |
| Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); } |
| Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); } |
| |
| const LookAheadSelector<Matcher1, Matcher2, MT> &Selector() const { |
| return selector_; |
| } |
| |
| uint64 Properties(uint64 inprops) const { |
| uint64 outprops = filter_.Properties(inprops); |
| if (lookahead_type_ == MATCH_NONE) |
| outprops |= kError; |
| return outprops; |
| } |
| |
| uint32 LookAheadFlags() const { return flags_; } |
| |
| bool LookAheadArc() const { return lookahead_arc_; } |
| |
| bool LookAheadOutput() const { |
| if (MT == MATCH_OUTPUT) |
| return true; |
| else if (MT == MATCH_INPUT) |
| return false; |
| else if (lookahead_type_ == MATCH_OUTPUT) |
| return true; |
| else |
| return false; |
| } |
| |
| private: |
| FilterState LookAheadFilterArc(Arc *arca, Arc *arcb, |
| const FilterState &f) const { |
| Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel; |
| |
| if (labela != 0 && !(flags_ & kLookAheadNonEpsilons)) |
| return f; |
| if (labela == 0 && !(flags_ & kLookAheadEpsilons)) |
| return f; |
| |
| lookahead_arc_ = true; |
| selector_.GetMatcher()->SetState(arca->nextstate); |
| |
| return selector_.GetMatcher()->LookAheadFst(selector_.GetFst(), |
| arcb->nextstate) ? f : |
| FilterState::NoState(); |
| } |
| |
| F filter_; // Underlying filter |
| MatchType lookahead_type_; // Lookahead match type |
| LookAheadSelector<Matcher1, Matcher2, MT> selector_; |
| uint32 flags_; // Lookahead flags |
| mutable bool lookahead_arc_; // Look-ahead performed at last FilterArc()? |
| |
| void operator=(const LookAheadComposeFilter<F, M1, M2> &); // disallow |
| }; |
| |
| |
| // This filter adds weight-pushing to a lookahead composition filter |
| // using the LookAheadWeight() method of matcher argument. It is |
| // templated on an underlying lookahead filter, typically the basic |
| // lookahead filter. Weight-pushing in composition brings weights |
| // forward as much as possible based on the lookahead information. |
| template <class F, |
| class M1 = LookAheadMatcher<typename F::FST1>, |
| class M2 = M1, |
| MatchType MT = MATCH_BOTH> |
| class PushWeightsComposeFilter { |
| public: |
| typedef typename F::FST1 FST1; |
| typedef typename F::FST2 FST2; |
| typedef typename F::Arc Arc; |
| typedef typename F::Matcher1 Matcher1; |
| typedef typename F::Matcher2 Matcher2; |
| typedef typename F::FilterState FilterState1; |
| typedef WeightFilterState<typename Arc::Weight> FilterState2; |
| typedef PairFilterState<FilterState1, FilterState2> FilterState; |
| |
| typedef typename Arc::StateId StateId; |
| typedef typename Arc::Label Label; |
| typedef typename Arc::Weight Weight; |
| |
| PushWeightsComposeFilter(const FST1 &fst1, const FST2 &fst2, |
| M1 *matcher1, M2 *matcher2) |
| : filter_(fst1, fst2, matcher1, matcher2), |
| f_(FilterState::NoState()) {} |
| |
| PushWeightsComposeFilter(const PushWeightsComposeFilter<F, M1, M2, MT> |
| &filter, |
| bool safe = false) |
| : filter_(filter.filter_, safe), |
| f_(FilterState::NoState()) {} |
| |
| FilterState Start() const { |
| return FilterState(filter_.Start(), FilterState2(Weight::One())); |
| } |
| |
| void SetState(StateId s1, StateId s2, const FilterState &f) { |
| f_ = f; |
| filter_.SetState(s1, s2, f.GetState1()); |
| } |
| |
| FilterState FilterArc(Arc *arc1, Arc *arc2) const { |
| const FilterState1 &f1 = filter_.FilterArc(arc1, arc2); |
| if (f1 == FilterState1::NoState()) |
| return FilterState::NoState(); |
| |
| if (!(LookAheadFlags() & kLookAheadWeight)) |
| return FilterState(f1, FilterState2(Weight::One())); |
| |
| const Weight &lweight = filter_.LookAheadArc() ? |
| Selector().GetMatcher()->LookAheadWeight() : Weight::One(); |
| const FilterState2 &f2 = f_.GetState2(); |
| const Weight &fweight = f2.GetWeight(); |
| |
| arc2->weight = Divide(Times(arc2->weight, lweight), fweight); |
| return FilterState(f1, FilterState2(lweight)); |
| } |
| |
| void FilterFinal(Weight *weight1, Weight *weight2) const { |
| filter_.FilterFinal(weight1, weight2); |
| if (!(LookAheadFlags() & kLookAheadWeight) || *weight1 == Weight::Zero()) |
| return; |
| |
| const FilterState2 &f2 = f_.GetState2(); |
| const Weight &fweight = f2.GetWeight(); |
| *weight1 = Divide(*weight1, fweight); |
| } |
| // Return resp matchers. Ownership states with filter. |
| Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); } |
| Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); } |
| |
| const LookAheadSelector<Matcher1, Matcher2, MT> &Selector() const { |
| return filter_.Selector(); |
| } |
| |
| uint32 LookAheadFlags() const { return filter_.LookAheadFlags(); } |
| bool LookAheadArc() const { return filter_.LookAheadArc(); } |
| bool LookAheadOutput() const { return filter_.LookAheadOutput(); } |
| |
| uint64 Properties(uint64 props) const { |
| return filter_.Properties(props) & kWeightInvariantProperties; |
| } |
| |
| private: |
| F filter_; // Underlying filter |
| FilterState f_; // Current filter state |
| |
| void operator=(const PushWeightsComposeFilter<F, M1, M2, MT> &); // disallow |
| }; |
| |
| // This filter adds label-pushing to a lookahead composition filter |
| // using the LookAheadPrefix() method of the matcher argument. It is |
| // templated on an underlying filter, typically the basic lookahead |
| // or weight-pushing lookahead filter. Label-pushing in composition |
| // matches labels as early as possible based on the lookahead |
| // information. |
| template <class F, |
| class M1 = LookAheadMatcher<typename F::FST1>, |
| class M2 = M1, |
| MatchType MT = MATCH_BOTH> |
| class PushLabelsComposeFilter { |
| public: |
| typedef typename F::FST1 FST1; |
| typedef typename F::FST2 FST2; |
| typedef typename F::Arc Arc; |
| typedef typename Arc::StateId StateId; |
| typedef typename Arc::Label Label; |
| typedef typename Arc::Weight Weight; |
| |
| typedef MultiEpsMatcher<typename F::Matcher1> Matcher1; |
| typedef MultiEpsMatcher<typename F::Matcher2> Matcher2; |
| typedef typename F::FilterState FilterState1; |
| typedef IntegerFilterState<typename Arc::Label> FilterState2; |
| typedef PairFilterState<FilterState1, FilterState2> FilterState; |
| |
| PushLabelsComposeFilter(const FST1 &fst1, const FST2 &fst2, |
| M1 *matcher1, M2 *matcher2) |
| : filter_(fst1, fst2, matcher1, matcher2), |
| f_(FilterState::NoState()), |
| fst1_(filter_.GetMatcher1()->GetFst()), |
| fst2_(filter_.GetMatcher2()->GetFst()), |
| matcher1_(fst1_, MATCH_OUTPUT, |
| filter_.LookAheadOutput() ? kMultiEpsList : kMultiEpsLoop, |
| filter_.GetMatcher1(), |
| false), |
| matcher2_(fst2_, MATCH_INPUT, |
| filter_.LookAheadOutput() ? kMultiEpsLoop : kMultiEpsList, |
| filter_.GetMatcher2(), |
| false) {} |
| |
| PushLabelsComposeFilter(const PushLabelsComposeFilter<F, M1, M2, MT> &filter, |
| bool safe = false) |
| : filter_(filter.filter_, safe), |
| f_(FilterState::NoState()), |
| fst1_(filter_.GetMatcher1()->GetFst()), |
| fst2_(filter_.GetMatcher2()->GetFst()), |
| matcher1_(fst1_, MATCH_OUTPUT, |
| filter_.LookAheadOutput() ? kMultiEpsList : kMultiEpsLoop, |
| filter_.GetMatcher1(), |
| false), |
| matcher2_(fst2_, MATCH_INPUT, |
| filter_.LookAheadOutput() ? kMultiEpsLoop : kMultiEpsList, |
| filter_.GetMatcher2(), |
| false) { |
| } |
| |
| FilterState Start() const { |
| return FilterState(filter_.Start(), FilterState2(kNoLabel)); |
| } |
| |
| void SetState(StateId s1, StateId s2, const FilterState &f) { |
| f_ = f; |
| filter_.SetState(s1, s2, f.GetState1()); |
| if (!(LookAheadFlags() & kLookAheadPrefix)) |
| return; |
| |
| narcsa_ = LookAheadOutput() ? internal::NumArcs(fst1_, s1) |
| : internal::NumArcs(fst2_, s2); |
| |
| const FilterState2 &f2 = f_.GetState2(); |
| const Label &flabel = f2.GetState(); |
| |
| GetMatcher1()->ClearMultiEpsLabels(); |
| GetMatcher2()->ClearMultiEpsLabels(); |
| if (flabel != kNoLabel) { // Have a lookahead label? |
| GetMatcher1()->AddMultiEpsLabel(flabel); // Yes, make it a multi-epsilon |
| GetMatcher2()->AddMultiEpsLabel(flabel); // label so that it matches the |
| } // implicit epsilon arc to be |
| } // modified below when pushing. |
| |
| FilterState FilterArc(Arc *arc1, Arc *arc2) const { |
| if (!(LookAheadFlags() & kLookAheadPrefix)) |
| return FilterState(filter_.FilterArc(arc1, arc2), |
| FilterState2(kNoLabel)); |
| |
| const FilterState2 &f2 = f_.GetState2(); |
| const Label &flabel = f2.GetState(); |
| if (flabel != kNoLabel) // Have a lookahead label? |
| return LookAheadOutput() ? PushedLabelFilterArc(arc1, arc2, flabel) : |
| PushedLabelFilterArc(arc2, arc1, flabel); |
| |
| const FilterState1 &f1 = filter_.FilterArc(arc1, arc2); |
| if (f1 == FilterState1::NoState()) |
| return FilterState::NoState(); |
| |
| if (!filter_.LookAheadArc()) |
| return FilterState(f1, FilterState2(kNoLabel)); |
| |
| return LookAheadOutput() ? PushLabelFilterArc(arc1, arc2, f1) : |
| PushLabelFilterArc(arc2, arc1, f1); |
| } |
| |
| void FilterFinal(Weight *weight1, Weight *weight2) const { |
| filter_.FilterFinal(weight1, weight2); |
| if (!(LookAheadFlags() & kLookAheadPrefix) || |
| *weight1 == Weight::Zero()) |
| return; |
| |
| const FilterState2 &f2 = f_.GetState2(); |
| const Label &flabel = f2.GetState(); |
| if (flabel != kNoLabel) |
| *weight1 = Weight::Zero(); |
| } |
| |
| // Return resp matchers. Ownership states with filter. |
| Matcher1 *GetMatcher1() { return &matcher1_; } |
| Matcher2 *GetMatcher2() { return &matcher2_; } |
| |
| uint64 Properties(uint64 iprops) const { |
| uint64 oprops = filter_.Properties(iprops); |
| if (LookAheadOutput()) |
| return oprops & kOLabelInvariantProperties; |
| else |
| return oprops & kILabelInvariantProperties; |
| } |
| |
| private: |
| const LookAheadSelector<typename F::Matcher1, typename F::Matcher2, MT> |
| &Selector() const { |
| return filter_.Selector(); |
| } |
| |
| // Consumes an already pushed label. |
| FilterState PushedLabelFilterArc(Arc *arca, Arc *arcb, |
| Label flabel) const { |
| Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel; |
| const Label &labelb = LookAheadOutput() ? arcb->ilabel : arcb->olabel; |
| |
| if (labelb != kNoLabel) { |
| return FilterState::NoState(); // Block non- (multi-) epsilon label |
| } else if (labela == flabel) { |
| labela = 0; // Convert match to multi-eps to eps |
| return Start(); |
| } else if (labela == 0) { |
| if (narcsa_ == 1) |
| return f_; // Take eps; keep state w/ label |
| Selector().GetMatcher()->SetState(arca->nextstate); |
| if (Selector().GetMatcher()->LookAheadLabel(flabel)) |
| return f_; // Take eps; keep state w/ label |
| else |
| return FilterState::NoState(); // Block non-coaccessible path |
| } else { |
| return FilterState::NoState(); // Block mismatch to multi-eps label |
| } |
| } |
| |
| // Pushes a label forward when possible. |
| FilterState PushLabelFilterArc(Arc *arca, Arc *arcb, |
| const FilterState1 &f1) const { |
| Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel; |
| const Label &labelb = LookAheadOutput() ? arcb->olabel : arcb->ilabel; |
| |
| if (labelb != 0) // No place to push. |
| return FilterState(f1, FilterState2(kNoLabel)); |
| if (labela != 0 && // Wrong lookahead prefix type? |
| LookAheadFlags() & kLookAheadNonEpsilonPrefix) |
| return FilterState(f1, FilterState2(kNoLabel)); |
| |
| Arc larc(kNoLabel, kNoLabel, Weight::Zero(), kNoStateId); |
| |
| if (Selector().GetMatcher()->LookAheadPrefix(&larc)) { // Have prefix arc? |
| labela = LookAheadOutput() ? larc.ilabel : larc.olabel; |
| arcb->ilabel = larc.ilabel; // Yes, go forward on that arc, |
| arcb->olabel = larc.olabel; // thus pushing the label. |
| arcb->weight = Times(arcb->weight, larc.weight); |
| arcb->nextstate = larc.nextstate; |
| return FilterState(f1, FilterState2(labela)); |
| } else { |
| return FilterState(f1, FilterState2(kNoLabel)); |
| } |
| } |
| |
| uint32 LookAheadFlags() const { return filter_.LookAheadFlags(); } |
| bool LookAheadArc() const { return filter_.LookAheadArc(); } |
| bool LookAheadOutput() const { return filter_.LookAheadOutput(); } |
| |
| F filter_; // Underlying filter |
| FilterState f_ ; // Current filter state |
| const FST1 &fst1_; |
| const FST2 &fst2_; |
| Matcher1 matcher1_; // Multi-epsilon matcher for fst1 |
| Matcher2 matcher2_; // Multi-epsilon matcher for fst2 |
| ssize_t narcsa_; // Number of arcs leaving look-ahead match FST |
| |
| void operator=(const PushLabelsComposeFilter<F, M1, M2, MT> &); // disallow |
| }; |
| |
| // |
| // CONVENIENCE CLASS useful for setting up composition with a default |
| // look-ahead matcher and filter. |
| // |
| |
| template <class A, MatchType type> // MATCH_NONE |
| class DefaultLookAhead { |
| public: |
| typedef Matcher< Fst<A> > M; |
| typedef SequenceComposeFilter<M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| // Specializes for MATCH_INPUT to allow lookahead. |
| template <class A> |
| class DefaultLookAhead<A, MATCH_INPUT> { |
| public: |
| typedef LookAheadMatcher< Fst<A> > M; |
| typedef SequenceComposeFilter<M> SF; |
| typedef LookAheadComposeFilter<SF, M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| // Specializes for MATCH_OUTPUT to allow lookahead. |
| template <class A> |
| class DefaultLookAhead<A, MATCH_OUTPUT> { |
| public: |
| typedef LookAheadMatcher< Fst<A> > M; |
| typedef AltSequenceComposeFilter<M> SF; |
| typedef LookAheadComposeFilter<SF, M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| // Specializes for StdArc to allow weight and label pushing. |
| template <> |
| class DefaultLookAhead<StdArc, MATCH_INPUT> { |
| public: |
| typedef StdArc A; |
| typedef LookAheadMatcher< Fst<A> > M; |
| typedef SequenceComposeFilter<M> SF; |
| typedef LookAheadComposeFilter<SF, M> LF; |
| typedef PushWeightsComposeFilter<LF, M> WF; |
| typedef PushLabelsComposeFilter<WF, M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| // Specializes for StdArc to allow weight and label pushing. |
| template <> |
| class DefaultLookAhead<StdArc, MATCH_OUTPUT> { |
| public: |
| typedef StdArc A; |
| typedef LookAheadMatcher< Fst<A> > M; |
| typedef AltSequenceComposeFilter<M> SF; |
| typedef LookAheadComposeFilter<SF, M> LF; |
| typedef PushWeightsComposeFilter<LF, M> WF; |
| typedef PushLabelsComposeFilter<WF, M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| // Specializes for LogArc to allow weight and label pushing. |
| template <> |
| class DefaultLookAhead<LogArc, MATCH_INPUT> { |
| public: |
| typedef LogArc A; |
| typedef LookAheadMatcher< Fst<A> > M; |
| typedef SequenceComposeFilter<M> SF; |
| typedef LookAheadComposeFilter<SF, M> LF; |
| typedef PushWeightsComposeFilter<LF, M> WF; |
| typedef PushLabelsComposeFilter<WF, M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| // Specializes for LogArc to allow weight and label pushing. |
| template <> |
| class DefaultLookAhead<LogArc, MATCH_OUTPUT> { |
| public: |
| typedef LogArc A; |
| typedef LookAheadMatcher< Fst<A> > M; |
| typedef AltSequenceComposeFilter<M> SF; |
| typedef LookAheadComposeFilter<SF, M> LF; |
| typedef PushWeightsComposeFilter<LF, M> WF; |
| typedef PushLabelsComposeFilter<WF, M> ComposeFilter; |
| typedef M FstMatcher; |
| }; |
| |
| } // namespace fst |
| |
| #endif // FST_LIB_LOOKAHEAD_FILTER_H__ |