// lookahead-matcher.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 // Classes to add lookahead to FST matchers, useful e.g. for improving // composition efficiency with certain inputs. #ifndef FST_LIB_LOOKAHEAD_MATCHER_H__ #define FST_LIB_LOOKAHEAD_MATCHER_H__ #include <fst/add-on.h> #include <fst/const-fst.h> #include <fst/fst.h> #include <fst/label-reachable.h> #include <fst/matcher.h> DECLARE_string(save_relabel_ipairs); DECLARE_string(save_relabel_opairs); namespace fst { // LOOKAHEAD MATCHERS - these have the interface of Matchers (see // matcher.h) and these additional methods: // // template <class F> // class LookAheadMatcher { // public: // typedef F FST; // typedef F::Arc Arc; // typedef typename Arc::StateId StateId; // typedef typename Arc::Label Label; // typedef typename Arc::Weight Weight; // // // Required constructors. // LookAheadMatcher(const F &fst, MatchType match_type); // // If safe=true, the copy is thread-safe (except the lookahead Fst is // // preserved). See Fst<>::Cop() for further doc. // LookAheadMatcher(const LookAheadMatcher &matcher, bool safe = false); // // Below are methods for looking ahead for a match to a label and // more generally, to a rational set. Each returns false if there is // definitely not a match and returns true if there possibly is a // match. // // LABEL LOOKAHEAD: Can 'label' be read from the current matcher state // // after possibly following epsilon transitions? // bool LookAheadLabel(Label label) const; // // // RATIONAL LOOKAHEAD: The next methods allow looking ahead for an // // arbitrary rational set of strings, specified by an FST and a state // // from which to begin the matching. If the lookahead FST is a // // transducer, this looks on the side different from the matcher // // 'match_type' (cf. composition). // // // Are there paths P from 's' in the lookahead FST that can be read from // // the cur. matcher state? // bool LookAheadFst(const Fst<Arc>& fst, StateId s); // // // Gives an estimate of the combined weight of the paths P in the // // lookahead and matcher FSTs for the last call to LookAheadFst. // // A trivial implementation returns Weight::One(). Non-trivial // // implementations are useful for weight-pushing in composition. // Weight LookAheadWeight() const; // // // Is there is a single non-epsilon arc found in the lookahead FST // // that begins P (after possibly following any epsilons) in the last // // call LookAheadFst? If so, return true and copy it to '*arc', o.w. // // return false. A trivial implementation returns false. Non-trivial // // implementations are useful for label-pushing in composition. // bool LookAheadPrefix(Arc *arc); // // // Optionally pre-specifies the lookahead FST that will be passed // // to LookAheadFst() for possible precomputation. If copy is true, // // then 'fst' is a copy of the FST used in the previous call to // // this method (useful to avoid unnecessary updates). // void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false); // // }; // // LOOK-AHEAD FLAGS (see also kMatcherFlags in matcher.h): // // Matcher is a lookahead matcher when 'match_type' is MATCH_INPUT. const uint32 kInputLookAheadMatcher = 0x00000010; // Matcher is a lookahead matcher when 'match_type' is MATCH_OUTPUT. const uint32 kOutputLookAheadMatcher = 0x00000020; // A non-trivial implementation of LookAheadWeight() method defined and // should be used? const uint32 kLookAheadWeight = 0x00000040; // A non-trivial implementation of LookAheadPrefix() method defined and // should be used? const uint32 kLookAheadPrefix = 0x00000080; // Look-ahead of matcher FST non-epsilon arcs? const uint32 kLookAheadNonEpsilons = 0x00000100; // Look-ahead of matcher FST epsilon arcs? const uint32 kLookAheadEpsilons = 0x00000200; // Ignore epsilon paths for the lookahead prefix? Note this gives // correct results in composition only with an appropriate composition // filter since it depends on the filter blocking the ignored paths. const uint32 kLookAheadNonEpsilonPrefix = 0x00000400; // For LabelLookAheadMatcher, save relabeling data to file const uint32 kLookAheadKeepRelabelData = 0x00000800; // Flags used for lookahead matchers. const uint32 kLookAheadFlags = 0x00000ff0; // LookAhead Matcher interface, templated on the Arc definition; used // for lookahead matcher specializations that are returned by the // InitMatcher() Fst method. template <class A> class LookAheadMatcherBase : public MatcherBase<A> { public: typedef A Arc; typedef typename A::StateId StateId; typedef typename A::Label Label; typedef typename A::Weight Weight; LookAheadMatcherBase() : weight_(Weight::One()), prefix_arc_(kNoLabel, kNoLabel, Weight::One(), kNoStateId) {} virtual ~LookAheadMatcherBase() {} bool LookAheadLabel(Label label) const { return LookAheadLabel_(label); } bool LookAheadFst(const Fst<Arc> &fst, StateId s) { return LookAheadFst_(fst, s); } Weight LookAheadWeight() const { return weight_; } bool LookAheadPrefix(Arc *arc) const { if (prefix_arc_.nextstate != kNoStateId) { *arc = prefix_arc_; return true; } else { return false; } } virtual void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) = 0; protected: void SetLookAheadWeight(const Weight &w) { weight_ = w; } void SetLookAheadPrefix(const Arc &arc) { prefix_arc_ = arc; } void ClearLookAheadPrefix() { prefix_arc_.nextstate = kNoStateId; } private: virtual bool LookAheadLabel_(Label label) const = 0; virtual bool LookAheadFst_(const Fst<Arc> &fst, StateId s) = 0; // This must set l.a. weight and // prefix if non-trivial. Weight weight_; // Look-ahead weight Arc prefix_arc_; // Look-ahead prefix arc }; // Don't really lookahead, just declare future looks good regardless. template <class M> class TrivialLookAheadMatcher : public LookAheadMatcherBase<typename M::FST::Arc> { public: typedef typename M::FST FST; typedef typename M::Arc Arc; typedef typename Arc::StateId StateId; typedef typename Arc::Label Label; typedef typename Arc::Weight Weight; TrivialLookAheadMatcher(const FST &fst, MatchType match_type) : matcher_(fst, match_type) {} TrivialLookAheadMatcher(const TrivialLookAheadMatcher<M> &lmatcher, bool safe = false) : matcher_(lmatcher.matcher_, safe) {} // General matcher methods TrivialLookAheadMatcher<M> *Copy(bool safe = false) const { return new TrivialLookAheadMatcher<M>(*this, safe); } MatchType Type(bool test) const { return matcher_.Type(test); } void SetState(StateId s) { return matcher_.SetState(s); } bool Find(Label label) { return matcher_.Find(label); } bool Done() const { return matcher_.Done(); } const Arc& Value() const { return matcher_.Value(); } void Next() { matcher_.Next(); } virtual const FST &GetFst() const { return matcher_.GetFst(); } uint64 Properties(uint64 props) const { return matcher_.Properties(props); } uint32 Flags() const { return matcher_.Flags() | kInputLookAheadMatcher | kOutputLookAheadMatcher; } // Look-ahead methods. bool LookAheadLabel(Label label) const { return true; } bool LookAheadFst(const Fst<Arc> &fst, StateId s) {return true; } Weight LookAheadWeight() const { return Weight::One(); } bool LookAheadPrefix(Arc *arc) const { return false; } void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) {} private: // This allows base class virtual access to non-virtual derived- // class members of the same name. It makes the derived class more // efficient to use but unsafe to further derive. virtual void SetState_(StateId s) { SetState(s); } virtual bool Find_(Label label) { return Find(label); } virtual bool Done_() const { return Done(); } virtual const Arc& Value_() const { return Value(); } virtual void Next_() { Next(); } bool LookAheadLabel_(Label l) const { return LookAheadLabel(l); } bool LookAheadFst_(const Fst<Arc> &fst, StateId s) { return LookAheadFst(fst, s); } Weight LookAheadWeight_() const { return LookAheadWeight(); } bool LookAheadPrefix_(Arc *arc) const { return LookAheadPrefix(arc); } M matcher_; }; // Look-ahead of one transition. Template argument F accepts flags to // control behavior. template <class M, uint32 F = kLookAheadNonEpsilons | kLookAheadEpsilons | kLookAheadWeight | kLookAheadPrefix> class ArcLookAheadMatcher : public LookAheadMatcherBase<typename M::FST::Arc> { public: typedef typename M::FST FST; typedef typename M::Arc Arc; typedef typename Arc::StateId StateId; typedef typename Arc::Label Label; typedef typename Arc::Weight Weight; typedef NullAddOn MatcherData; using LookAheadMatcherBase<Arc>::LookAheadWeight; using LookAheadMatcherBase<Arc>::SetLookAheadPrefix; using LookAheadMatcherBase<Arc>::SetLookAheadWeight; using LookAheadMatcherBase<Arc>::ClearLookAheadPrefix; ArcLookAheadMatcher(const FST &fst, MatchType match_type, MatcherData *data = 0) : matcher_(fst, match_type), fst_(matcher_.GetFst()), lfst_(0), s_(kNoStateId) {} ArcLookAheadMatcher(const ArcLookAheadMatcher<M, F> &lmatcher, bool safe = false) : matcher_(lmatcher.matcher_, safe), fst_(matcher_.GetFst()), lfst_(lmatcher.lfst_), s_(kNoStateId) {} // General matcher methods ArcLookAheadMatcher<M, F> *Copy(bool safe = false) const { return new ArcLookAheadMatcher<M, F>(*this, safe); } MatchType Type(bool test) const { return matcher_.Type(test); } void SetState(StateId s) { s_ = s; matcher_.SetState(s); } bool Find(Label label) { return matcher_.Find(label); } bool Done() const { return matcher_.Done(); } const Arc& Value() const { return matcher_.Value(); } void Next() { matcher_.Next(); } const FST &GetFst() const { return fst_; } uint64 Properties(uint64 props) const { return matcher_.Properties(props); } uint32 Flags() const { return matcher_.Flags() | kInputLookAheadMatcher | kOutputLookAheadMatcher | F; } // Writable matcher methods MatcherData *GetData() const { return 0; } // Look-ahead methods. bool LookAheadLabel(Label label) const { return matcher_.Find(label); } // Checks if there is a matching (possibly super-final) transition // at (s_, s). bool LookAheadFst(const Fst<Arc> &fst, StateId s); void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) { lfst_ = &fst; } private: // This allows base class virtual access to non-virtual derived- // class members of the same name. It makes the derived class more // efficient to use but unsafe to further derive. virtual void SetState_(StateId s) { SetState(s); } virtual bool Find_(Label label) { return Find(label); } virtual bool Done_() const { return Done(); } virtual const Arc& Value_() const { return Value(); } virtual void Next_() { Next(); } bool LookAheadLabel_(Label l) const { return LookAheadLabel(l); } bool LookAheadFst_(const Fst<Arc> &fst, StateId s) { return LookAheadFst(fst, s); } mutable M matcher_; const FST &fst_; // Matcher FST const Fst<Arc> *lfst_; // Look-ahead FST StateId s_; // Matcher state }; template <class M, uint32 F> bool ArcLookAheadMatcher<M, F>::LookAheadFst(const Fst<Arc> &fst, StateId s) { if (&fst != lfst_) InitLookAheadFst(fst); bool ret = false; ssize_t nprefix = 0; if (F & kLookAheadWeight) SetLookAheadWeight(Weight::Zero()); if (F & kLookAheadPrefix) ClearLookAheadPrefix(); if (fst_.Final(s_) != Weight::Zero() && lfst_->Final(s) != Weight::Zero()) { if (!(F & (kLookAheadWeight | kLookAheadPrefix))) return true; ++nprefix; if (F & kLookAheadWeight) SetLookAheadWeight(Plus(LookAheadWeight(), Times(fst_.Final(s_), lfst_->Final(s)))); ret = true; } if (matcher_.Find(kNoLabel)) { if (!(F & (kLookAheadWeight | kLookAheadPrefix))) return true; ++nprefix; if (F & kLookAheadWeight) for (; !matcher_.Done(); matcher_.Next()) SetLookAheadWeight(Plus(LookAheadWeight(), matcher_.Value().weight)); ret = true; } for (ArcIterator< Fst<Arc> > aiter(*lfst_, s); !aiter.Done(); aiter.Next()) { const Arc &arc = aiter.Value(); Label label = kNoLabel; switch (matcher_.Type(false)) { case MATCH_INPUT: label = arc.olabel; break; case MATCH_OUTPUT: label = arc.ilabel; break; default: FSTERROR() << "ArcLookAheadMatcher::LookAheadFst: bad match type"; return true; } if (label == 0) { if (!(F & (kLookAheadWeight | kLookAheadPrefix))) return true; if (!(F & kLookAheadNonEpsilonPrefix)) ++nprefix; if (F & kLookAheadWeight) SetLookAheadWeight(Plus(LookAheadWeight(), arc.weight)); ret = true; } else if (matcher_.Find(label)) { if (!(F & (kLookAheadWeight | kLookAheadPrefix))) return true; for (; !matcher_.Done(); matcher_.Next()) { ++nprefix; if (F & kLookAheadWeight) SetLookAheadWeight(Plus(LookAheadWeight(), Times(arc.weight, matcher_.Value().weight))); if ((F & kLookAheadPrefix) && nprefix == 1) SetLookAheadPrefix(arc); } ret = true; } } if (F & kLookAheadPrefix) { if (nprefix == 1) SetLookAheadWeight(Weight::One()); // Avoids double counting. else ClearLookAheadPrefix(); } return ret; } // Template argument F accepts flags to control behavior. // It must include precisely one of KInputLookAheadMatcher or // KOutputLookAheadMatcher. template <class M, uint32 F = kLookAheadEpsilons | kLookAheadWeight | kLookAheadPrefix | kLookAheadNonEpsilonPrefix | kLookAheadKeepRelabelData, class S = DefaultAccumulator<typename M::Arc> > class LabelLookAheadMatcher : public LookAheadMatcherBase<typename M::FST::Arc> { public: typedef typename M::FST FST; typedef typename M::Arc Arc; typedef typename Arc::StateId StateId; typedef typename Arc::Label Label; typedef typename Arc::Weight Weight; typedef LabelReachableData<Label> MatcherData; using LookAheadMatcherBase<Arc>::LookAheadWeight; using LookAheadMatcherBase<Arc>::SetLookAheadPrefix; using LookAheadMatcherBase<Arc>::SetLookAheadWeight; using LookAheadMatcherBase<Arc>::ClearLookAheadPrefix; LabelLookAheadMatcher(const FST &fst, MatchType match_type, MatcherData *data = 0, S *s = 0) : matcher_(fst, match_type), lfst_(0), label_reachable_(0), s_(kNoStateId), error_(false) { if (!(F & (kInputLookAheadMatcher | kOutputLookAheadMatcher))) { FSTERROR() << "LabelLookaheadMatcher: bad matcher flags: " << F; error_ = true; } bool reach_input = match_type == MATCH_INPUT; if (data) { if (reach_input == data->ReachInput()) label_reachable_ = new LabelReachable<Arc, S>(data, s); } else if ((reach_input && (F & kInputLookAheadMatcher)) || (!reach_input && (F & kOutputLookAheadMatcher))) { label_reachable_ = new LabelReachable<Arc, S>( fst, reach_input, s, F & kLookAheadKeepRelabelData); } } LabelLookAheadMatcher(const LabelLookAheadMatcher<M, F, S> &lmatcher, bool safe = false) : matcher_(lmatcher.matcher_, safe), lfst_(lmatcher.lfst_), label_reachable_( lmatcher.label_reachable_ ? new LabelReachable<Arc, S>(*lmatcher.label_reachable_) : 0), s_(kNoStateId), error_(lmatcher.error_) {} ~LabelLookAheadMatcher() { delete label_reachable_; } // General matcher methods LabelLookAheadMatcher<M, F, S> *Copy(bool safe = false) const { return new LabelLookAheadMatcher<M, F, S>(*this, safe); } MatchType Type(bool test) const { return matcher_.Type(test); } void SetState(StateId s) { if (s_ == s) return; s_ = s; match_set_state_ = false; reach_set_state_ = false; } bool Find(Label label) { if (!match_set_state_) { matcher_.SetState(s_); match_set_state_ = true; } return matcher_.Find(label); } bool Done() const { return matcher_.Done(); } const Arc& Value() const { return matcher_.Value(); } void Next() { matcher_.Next(); } const FST &GetFst() const { return matcher_.GetFst(); } uint64 Properties(uint64 inprops) const { uint64 outprops = matcher_.Properties(inprops); if (error_ || (label_reachable_ && label_reachable_->Error())) outprops |= kError; return outprops; } uint32 Flags() const { if (label_reachable_ && label_reachable_->GetData()->ReachInput()) return matcher_.Flags() | F | kInputLookAheadMatcher; else if (label_reachable_ && !label_reachable_->GetData()->ReachInput()) return matcher_.Flags() | F | kOutputLookAheadMatcher; else return matcher_.Flags(); } // Writable matcher methods MatcherData *GetData() const { return label_reachable_ ? label_reachable_->GetData() : 0; }; // Look-ahead methods. bool LookAheadLabel(Label label) const { if (label == 0) return true; if (label_reachable_) { if (!reach_set_state_) { label_reachable_->SetState(s_); reach_set_state_ = true; } return label_reachable_->Reach(label); } else { return true; } } // Checks if there is a matching (possibly super-final) transition // at (s_, s). template <class L> bool LookAheadFst(const L &fst, StateId s); void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) { lfst_ = &fst; if (label_reachable_) label_reachable_->ReachInit(fst, copy); } template <class L> void InitLookAheadFst(const L& fst, bool copy = false) { lfst_ = static_cast<const Fst<Arc> *>(&fst); if (label_reachable_) label_reachable_->ReachInit(fst, copy); } private: // This allows base class virtual access to non-virtual derived- // class members of the same name. It makes the derived class more // efficient to use but unsafe to further derive. virtual void SetState_(StateId s) { SetState(s); } virtual bool Find_(Label label) { return Find(label); } virtual bool Done_() const { return Done(); } virtual const Arc& Value_() const { return Value(); } virtual void Next_() { Next(); } bool LookAheadLabel_(Label l) const { return LookAheadLabel(l); } bool LookAheadFst_(const Fst<Arc> &fst, StateId s) { return LookAheadFst(fst, s); } mutable M matcher_; const Fst<Arc> *lfst_; // Look-ahead FST LabelReachable<Arc, S> *label_reachable_; // Label reachability info StateId s_; // Matcher state bool match_set_state_; // matcher_.SetState called? mutable bool reach_set_state_; // reachable_.SetState called? bool error_; }; template <class M, uint32 F, class S> template <class L> inline bool LabelLookAheadMatcher<M, F, S>::LookAheadFst(const L &fst, StateId s) { if (static_cast<const Fst<Arc> *>(&fst) != lfst_) InitLookAheadFst(fst); SetLookAheadWeight(Weight::One()); ClearLookAheadPrefix(); if (!label_reachable_) return true; label_reachable_->SetState(s_, s); reach_set_state_ = true; bool compute_weight = F & kLookAheadWeight; bool compute_prefix = F & kLookAheadPrefix; bool reach_input = Type(false) == MATCH_OUTPUT; ArcIterator<L> aiter(fst, s); bool reach_arc = label_reachable_->Reach(&aiter, 0, internal::NumArcs(*lfst_, s), reach_input, compute_weight); Weight lfinal = internal::Final(*lfst_, s); bool reach_final = lfinal != Weight::Zero() && label_reachable_->ReachFinal(); if (reach_arc) { ssize_t begin = label_reachable_->ReachBegin(); ssize_t end = label_reachable_->ReachEnd(); if (compute_prefix && end - begin == 1 && !reach_final) { aiter.Seek(begin); SetLookAheadPrefix(aiter.Value()); compute_weight = false; } else if (compute_weight) { SetLookAheadWeight(label_reachable_->ReachWeight()); } } if (reach_final && compute_weight) SetLookAheadWeight(reach_arc ? Plus(LookAheadWeight(), lfinal) : lfinal); return reach_arc || reach_final; } // Label-lookahead relabeling class. template <class A> class LabelLookAheadRelabeler { public: typedef typename A::Label Label; typedef LabelReachableData<Label> MatcherData; typedef AddOnPair<MatcherData, MatcherData> D; // Relabels matcher Fst - initialization function object. template <typename I> LabelLookAheadRelabeler(I **impl); // Relabels arbitrary Fst. Class L should be a label-lookahead Fst. template <class L> static void Relabel(MutableFst<A> *fst, const L &mfst, bool relabel_input) { typename L::Impl *impl = mfst.GetImpl(); D *data = impl->GetAddOn(); LabelReachable<A> reachable(data->First() ? data->First() : data->Second()); reachable.Relabel(fst, relabel_input); } // Returns relabeling pairs (cf. relabel.h::Relabel()). // Class L should be a label-lookahead Fst. // If 'avoid_collisions' is true, extra pairs are added to // ensure no collisions when relabeling automata that have // labels unseen here. template <class L> static void RelabelPairs(const L &mfst, vector<pair<Label, Label> > *pairs, bool avoid_collisions = false) { typename L::Impl *impl = mfst.GetImpl(); D *data = impl->GetAddOn(); LabelReachable<A> reachable(data->First() ? data->First() : data->Second()); reachable.RelabelPairs(pairs, avoid_collisions); } }; template <class A> template <typename I> inline LabelLookAheadRelabeler<A>::LabelLookAheadRelabeler(I **impl) { Fst<A> &fst = (*impl)->GetFst(); D *data = (*impl)->GetAddOn(); const string name = (*impl)->Type(); bool is_mutable = fst.Properties(kMutable, false); MutableFst<A> *mfst = 0; if (is_mutable) { mfst = static_cast<MutableFst<A> *>(&fst); } else { mfst = new VectorFst<A>(fst); data->IncrRefCount(); delete *impl; } if (data->First()) { // reach_input LabelReachable<A> reachable(data->First()); reachable.Relabel(mfst, true); if (!FLAGS_save_relabel_ipairs.empty()) { vector<pair<Label, Label> > pairs; reachable.RelabelPairs(&pairs, true); WriteLabelPairs(FLAGS_save_relabel_ipairs, pairs); } } else { LabelReachable<A> reachable(data->Second()); reachable.Relabel(mfst, false); if (!FLAGS_save_relabel_opairs.empty()) { vector<pair<Label, Label> > pairs; reachable.RelabelPairs(&pairs, true); WriteLabelPairs(FLAGS_save_relabel_opairs, pairs); } } if (!is_mutable) { *impl = new I(*mfst, name); (*impl)->SetAddOn(data); delete mfst; data->DecrRefCount(); } } // Generic lookahead matcher, templated on the FST definition // - a wrapper around pointer to specific one. template <class F> class LookAheadMatcher { public: typedef F FST; typedef typename F::Arc Arc; typedef typename Arc::StateId StateId; typedef typename Arc::Label Label; typedef typename Arc::Weight Weight; typedef LookAheadMatcherBase<Arc> LBase; LookAheadMatcher(const F &fst, MatchType match_type) { base_ = fst.InitMatcher(match_type); if (!base_) base_ = new SortedMatcher<F>(fst, match_type); lookahead_ = false; } LookAheadMatcher(const LookAheadMatcher<F> &matcher, bool safe = false) { base_ = matcher.base_->Copy(safe); lookahead_ = matcher.lookahead_; } ~LookAheadMatcher() { delete base_; } // General matcher methods LookAheadMatcher<F> *Copy(bool safe = false) const { return new LookAheadMatcher<F>(*this, safe); } MatchType Type(bool test) const { return base_->Type(test); } void SetState(StateId s) { base_->SetState(s); } bool Find(Label label) { return base_->Find(label); } bool Done() const { return base_->Done(); } const Arc& Value() const { return base_->Value(); } void Next() { base_->Next(); } const F &GetFst() const { return static_cast<const F &>(base_->GetFst()); } uint64 Properties(uint64 props) const { return base_->Properties(props); } uint32 Flags() const { return base_->Flags(); } // Look-ahead methods bool LookAheadLabel(Label label) const { if (LookAheadCheck()) { LBase *lbase = static_cast<LBase *>(base_); return lbase->LookAheadLabel(label); } else { return true; } } bool LookAheadFst(const Fst<Arc> &fst, StateId s) { if (LookAheadCheck()) { LBase *lbase = static_cast<LBase *>(base_); return lbase->LookAheadFst(fst, s); } else { return true; } } Weight LookAheadWeight() const { if (LookAheadCheck()) { LBase *lbase = static_cast<LBase *>(base_); return lbase->LookAheadWeight(); } else { return Weight::One(); } } bool LookAheadPrefix(Arc *arc) const { if (LookAheadCheck()) { LBase *lbase = static_cast<LBase *>(base_); return lbase->LookAheadPrefix(arc); } else { return false; } } void InitLookAheadFst(const Fst<Arc>& fst, bool copy = false) { if (LookAheadCheck()) { LBase *lbase = static_cast<LBase *>(base_); lbase->InitLookAheadFst(fst, copy); } } private: bool LookAheadCheck() const { if (!lookahead_) { lookahead_ = base_->Flags() & (kInputLookAheadMatcher | kOutputLookAheadMatcher); if (!lookahead_) { FSTERROR() << "LookAheadMatcher: No look-ahead matcher defined"; } } return lookahead_; } MatcherBase<Arc> *base_; mutable bool lookahead_; void operator=(const LookAheadMatcher<Arc> &); // disallow }; } // namespace fst #endif // FST_LIB_LOOKAHEAD_MATCHER_H__