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