1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// matcher.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// Classes to allow matching labels leaving FST states.
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_MATCHER_H__
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_MATCHER_H__
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <algorithm>
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <set>
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/mutable-fst.h>  // for all internal FST accessors
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// MATCHERS - these can find and iterate through requested labels at
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// FST states. In the simplest form, these are just some associative
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// map or search keyed on labels. More generally, they may
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// implement matching special labels that represent sets of labels
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// such as 'sigma' (all), 'rho' (rest), or 'phi' (fail).
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The Matcher interface is:
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// template <class F>
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// class Matcher {
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  public:
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef F FST;
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef F::Arc Arc;
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef typename Arc::StateId StateId;
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef typename Arc::Label Label;
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef typename Arc::Weight Weight;
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Required constructors.
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   Matcher(const F &fst, MatchType type);
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // If safe=true, the copy is thread-safe. See Fst<>::Copy()
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // for further doc.
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   Matcher(const Matcher &matcher, bool safe = false);
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // If safe=true, the copy is thread-safe. See Fst<>::Copy()
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // for further doc.
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   Matcher<F> *Copy(bool safe = false) const;
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Returns the match type that can be provided (depending on
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // compatibility of the input FST). It is either
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // the requested match type, MATCH_NONE, or MATCH_UNKNOWN.
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // If 'test' is false, a constant time test is performed, but
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // MATCH_UNKNOWN may be returned. If 'test' is true,
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // a definite answer is returned, but may involve more costly
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // computation (e.g., visiting the Fst).
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   MatchType Type(bool test) const;
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Specifies the current state.
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   void SetState(StateId s);
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // This finds matches to a label at the current state.
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Returns true if a match found. kNoLabel matches any
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // 'non-consuming' transitions, e.g., epsilon transitions,
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // which do not require a matching symbol.
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   bool Find(Label label);
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // These iterate through any matches found:
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   bool Done() const;         // No more matches.
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   const A& Value() const;    // Current arc (when !Done)
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   void Next();               // Advance to next arc (when !Done)
785b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin//   // Initially and after SetState() the iterator methods
795b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin//   // have undefined behavior until Find() is called.
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Return matcher FST.
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   const F& GetFst() const;
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // This specifies the known Fst properties as viewed from this
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // matcher. It takes as argument the input Fst's known properties.
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   uint64 Properties(uint64 props) const;
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// };
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
88dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin//
89dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin// MATCHER FLAGS (see also kLookAheadFlags in lookahead-matcher.h)
90dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin//
91dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin// Matcher prefers being used as the matching side in composition.
92dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkinconst uint32 kPreferMatch  = 0x00000001;
93dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin
94dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin// Matcher needs to be used as the matching side in composition.
95dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkinconst uint32 kRequireMatch = 0x00000002;
96dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Flags used for basic matchers (see also lookahead.h).
98dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkinconst uint32 kMatcherFlags = kPreferMatch | kRequireMatch;
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Matcher interface, templated on the Arc definition; used
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// for matcher specializations that are returned by the
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// InitMatcher Fst method.
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A>
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass MatcherBase {
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef A Arc;
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::StateId StateId;
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Label Label;
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename A::Weight Weight;
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual ~MatcherBase() {}
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual MatcherBase<A> *Copy(bool safe = false) const = 0;
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual MatchType Type(bool test) const = 0;
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) { SetState_(s); }
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Find(Label label) { return Find_(label); }
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const { return Done_(); }
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const A& Value() const { return Value_(); }
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() { Next_(); }
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const Fst<A> &GetFst() const = 0;
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual uint64 Properties(uint64 props) const = 0;
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual uint32 Flags() const { return 0; }
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void SetState_(StateId s) = 0;
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Find_(Label label) = 0;
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Done_() const = 0;
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const A& Value_() const  = 0;
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void Next_()  = 0;
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// A matcher that expects sorted labels on the side to be matched.
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// If match_type == MATCH_INPUT, epsilons match the implicit self loop
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Arc(kNoLabel, 0, Weight::One(), current_state) as well as any
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// actual epsilon transitions. If match_type == MATCH_OUTPUT, then
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Arc(0, kNoLabel, Weight::One(), current_state) is instead matched.
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class F>
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass SortedMatcher : public MatcherBase<typename F::Arc> {
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef F FST;
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename F::Arc Arc;
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Labels >= binary_label will be searched for by binary search,
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // o.w. linear search is used.
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SortedMatcher(const F &fst, MatchType match_type,
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                Label binary_label = 1)
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : fst_(fst.Copy()),
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        s_(kNoStateId),
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        aiter_(0),
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(match_type),
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        binary_label_(binary_label),
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_label_(kNoLabel),
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        narcs_(0),
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        loop_(kNoLabel, 0, Weight::One(), kNoStateId),
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(false) {
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    switch(match_type_) {
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MATCH_INPUT:
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MATCH_NONE:
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      case MATCH_OUTPUT:
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        swap(loop_.ilabel, loop_.olabel);
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      default:
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        FSTERROR() << "SortedMatcher: bad match type";
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_ = MATCH_NONE;
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_ = true;
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SortedMatcher(const SortedMatcher<F> &matcher, bool safe = false)
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : fst_(matcher.fst_->Copy(safe)),
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        s_(kNoStateId),
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        aiter_(0),
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(matcher.match_type_),
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        binary_label_(matcher.binary_label_),
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_label_(kNoLabel),
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        narcs_(0),
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        loop_(matcher.loop_),
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(matcher.error_) {}
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual ~SortedMatcher() {
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (aiter_)
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      delete aiter_;
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    delete fst_;
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual SortedMatcher<F> *Copy(bool safe = false) const {
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new SortedMatcher<F>(*this, safe);
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual MatchType Type(bool test) const {
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_type_ == MATCH_NONE)
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return match_type_;
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 true_prop =  match_type_ == MATCH_INPUT ?
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        kILabelSorted : kOLabelSorted;
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 false_prop = match_type_ == MATCH_INPUT ?
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        kNotILabelSorted : kNotOLabelSorted;
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 props = fst_->Properties(true_prop | false_prop, test);
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (props & true_prop)
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return match_type_;
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (props & false_prop)
207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return MATCH_NONE;
208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return MATCH_UNKNOWN;
210f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) {
213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (s_ == s)
214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return;
215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    s_ = s;
216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_type_ == MATCH_NONE) {
217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "SortedMatcher: bad match type";
218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (aiter_)
221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      delete aiter_;
222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    aiter_ = new ArcIterator<F>(*fst_, s);
223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    aiter_->SetFlags(kArcNoCache, kArcNoCache);
224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    narcs_ = internal::NumArcs(*fst_, s);
225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    loop_.nextstate = s;
226f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
227f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
2285b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  bool Find(Label match_label) {
2295b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    exact_match_ = true;
2305b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    if (error_) {
2315b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      current_loop_ = false;
2325b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      match_label_ = kNoLabel;
2335b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      return false;
2345b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    }
2355b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    current_loop_ = match_label == 0;
2365b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    match_label_ = match_label == kNoLabel ? 0 : match_label;
2375b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    if (Search()) {
2385b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      return true;
2395b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    } else {
2405b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      return current_loop_;
2415b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    }
2425b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  }
2435b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin
2445b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  // Positions matcher to the first position where inserting
2455b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  // match_label would maintain the sort order.
2465b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  void LowerBound(Label match_label) {
2475b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    exact_match_ = false;
2485b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    current_loop_ = false;
2495b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    if (error_) {
2505b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      match_label_ = kNoLabel;
2515b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      return;
2525b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    }
2535b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    match_label_ = match_label;
2545b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    Search();
2555b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  }
256f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
2575b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  // After Find(), returns false if no more exact matches.
2585b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  // After LowerBound(), returns false if no more arcs.
259f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const {
260f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (current_loop_)
261f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return false;
262f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (aiter_->Done())
263f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return true;
2645b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    if (!exact_match_)
2655b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      return false;
266f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    aiter_->SetFlags(
267f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      match_type_ == MATCH_INPUT ? kArcILabelValue : kArcOLabelValue,
268f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      kArcValueFlags);
269f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    Label label = match_type_ == MATCH_INPUT ?
270f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        aiter_->Value().ilabel : aiter_->Value().olabel;
271f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return label != match_label_;
272f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
273f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
274f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Arc& Value() const {
275f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (current_loop_) {
276f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return loop_;
277f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
278f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    aiter_->SetFlags(kArcValueFlags, kArcValueFlags);
279f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return aiter_->Value();
280f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
281f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
282f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() {
283f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (current_loop_)
284f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      current_loop_ = false;
285f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
286f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      aiter_->Next();
287f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
288f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
289f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const F &GetFst() const { return *fst_; }
290f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
291f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual uint64 Properties(uint64 inprops) const {
292f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    uint64 outprops = inprops;
293f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (error_) outprops |= kError;
294f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops;
295f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
296f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
2975b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  size_t Position() const { return aiter_ ? aiter_->Position() : 0; }
2985b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin
299f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
300f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void SetState_(StateId s) { SetState(s); }
301f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Find_(Label label) { return Find(label); }
302f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Done_() const { return Done(); }
303f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const Arc& Value_() const { return Value(); }
304f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void Next_() { Next(); }
305f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3065b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  bool Search();
3075b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin
308f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const F *fst_;
309f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId s_;                     // Current state
310f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcIterator<F> *aiter_;         // Iterator for current state
311f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatchType match_type_;          // Type of match to perform
312f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label binary_label_;            // Least label for binary search
313f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label match_label_;             // Current label to be matched
314f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  size_t narcs_;                  // Current state arc count
315f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Arc loop_;                      // For non-consuming symbols
316f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool current_loop_;             // Current arc is the implicit loop
3175b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  bool exact_match_;              // Exact match or lower bound?
318f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool error_;                    // Error encountered
319f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
320f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const SortedMatcher<F> &);  // Disallow
321f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
322f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3235b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// Returns true iff match to match_label_. Positions arc iterator at
3245b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// lower bound regardless.
325f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class F> inline
3265b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkinbool SortedMatcher<F>::Search() {
327f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  aiter_->SetFlags(
328f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      match_type_ == MATCH_INPUT ? kArcILabelValue : kArcOLabelValue,
329f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      kArcValueFlags);
330f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (match_label_ >= binary_label_) {
331f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Binary search for match.
332f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size_t low = 0;
333f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    size_t high = narcs_;
334f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    while (low < high) {
335f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      size_t mid = (low + high) / 2;
336f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      aiter_->Seek(mid);
337f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Label label = match_type_ == MATCH_INPUT ?
338f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          aiter_->Value().ilabel : aiter_->Value().olabel;
339f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (label > match_label_) {
340f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        high = mid;
341f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else if (label < match_label_) {
342f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        low = mid + 1;
343f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else {
344f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        // find first matching label (when non-determinism)
345f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        for (size_t i = mid; i > low; --i) {
346f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          aiter_->Seek(i - 1);
347f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          label = match_type_ == MATCH_INPUT ? aiter_->Value().ilabel :
348f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson              aiter_->Value().olabel;
349f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (label != match_label_) {
350f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            aiter_->Seek(i);
351f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            return true;
352f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          }
353f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
354f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        return true;
355f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
356f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
3575b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    aiter_->Seek(low);
3585b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    return false;
359f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
360f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Linear search for match.
361f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (aiter_->Reset(); !aiter_->Done(); aiter_->Next()) {
362f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      Label label = match_type_ == MATCH_INPUT ?
363f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          aiter_->Value().ilabel : aiter_->Value().olabel;
364f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (label == match_label_) {
365f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        return true;
366f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
367f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (label > match_label_)
368f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        break;
369f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
3705b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    return false;
371f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
372f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
373f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
374f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
375f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Specifies whether during matching we rewrite both the input and output sides.
376f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonenum MatcherRewriteMode {
377f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MATCHER_REWRITE_AUTO = 0,    // Rewrites both sides iff acceptor.
378f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MATCHER_REWRITE_ALWAYS,
379f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MATCHER_REWRITE_NEVER
380f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
381f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
382f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
383f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// For any requested label that doesn't match at a state, this matcher
384f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// considers all transitions that match the label 'rho_label' (rho =
385f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 'rest').  Each such rho transition found is returned with the
386f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// rho_label rewritten as the requested label (both sides if an
387f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// acceptor, or if 'rewrite_both' is true and both input and output
388f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// labels of the found transition are 'rho_label').  If 'rho_label' is
389f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// kNoLabel, this special matching is not done.  RhoMatcher is
390f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// templated itself on a matcher, which is used to perform the
391f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// underlying matching.  By default, the underlying matcher is
392f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// constructed by RhoMatcher.  The user can instead pass in this
393f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// object; in that case, RhoMatcher takes its ownership.
394f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M>
395f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass RhoMatcher : public MatcherBase<typename M::Arc> {
396f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
397f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::FST FST;
398f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::Arc Arc;
399f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
400f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
401f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
402f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
403f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  RhoMatcher(const FST &fst,
404f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             MatchType match_type,
405f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             Label rho_label = kNoLabel,
406f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             MatcherRewriteMode rewrite_mode = MATCHER_REWRITE_AUTO,
407f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             M *matcher = 0)
408f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(matcher ? matcher : new M(fst, match_type)),
409f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(match_type),
410f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rho_label_(rho_label),
411f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(false) {
412f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_type == MATCH_BOTH) {
413f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "RhoMatcher: bad match type";
414f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      match_type_ = MATCH_NONE;
415f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
416f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
417f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rho_label == 0) {
418f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "RhoMatcher: 0 cannot be used as rho_label";
419f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rho_label_ = kNoLabel;
420f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
421f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
422f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
423f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_mode == MATCHER_REWRITE_AUTO)
424f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = fst.Properties(kAcceptor, true);
425f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (rewrite_mode == MATCHER_REWRITE_ALWAYS)
426f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = true;
427f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
428f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = false;
429f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
430f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
431f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  RhoMatcher(const RhoMatcher<M> &matcher, bool safe = false)
432f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(new M(*matcher.matcher_, safe)),
433f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(matcher.match_type_),
434f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rho_label_(matcher.rho_label_),
435f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rewrite_both_(matcher.rewrite_both_),
436f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(matcher.error_) {}
437f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
438f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual ~RhoMatcher() {
439f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    delete matcher_;
440f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
441f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
442f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual RhoMatcher<M> *Copy(bool safe = false) const {
443f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new RhoMatcher<M>(*this, safe);
444f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
445f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
446f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual MatchType Type(bool test) const { return matcher_->Type(test); }
447f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
448f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) {
449f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->SetState(s);
450f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    has_rho_ = rho_label_ != kNoLabel;
451f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
452f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
453f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Find(Label match_label) {
454f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_label == rho_label_ && rho_label_ != kNoLabel) {
455f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "RhoMatcher::Find: bad label (rho)";
456f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
457f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return false;
458f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
459f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (matcher_->Find(match_label)) {
460f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rho_match_ = kNoLabel;
461f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return true;
462f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else if (has_rho_ && match_label != 0 && match_label != kNoLabel &&
463f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               (has_rho_ = matcher_->Find(rho_label_))) {
464f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rho_match_ = match_label;
465f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return true;
466f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
467f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return false;
468f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
469f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
470f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
471f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const { return matcher_->Done(); }
472f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
473f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Arc& Value() const {
474f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rho_match_ == kNoLabel) {
475f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return matcher_->Value();
476f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
477f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rho_arc_ = matcher_->Value();
478f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (rewrite_both_) {
479f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (rho_arc_.ilabel == rho_label_)
480f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          rho_arc_.ilabel = rho_match_;
481f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (rho_arc_.olabel == rho_label_)
482f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          rho_arc_.olabel = rho_match_;
483f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else if (match_type_ == MATCH_INPUT) {
484f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rho_arc_.ilabel = rho_match_;
485f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else {
486f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rho_arc_.olabel = rho_match_;
487f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
488f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return rho_arc_;
489f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
490f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
491f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
492f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() { matcher_->Next(); }
493f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
494f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const FST &GetFst() const { return matcher_->GetFst(); }
495f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
496f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual uint64 Properties(uint64 props) const;
497f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
498dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  virtual uint32 Flags() const {
499dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (rho_label_ == kNoLabel || match_type_ == MATCH_NONE)
500dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      return matcher_->Flags();
501dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    return matcher_->Flags() | kRequireMatch;
502dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  }
503dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin
504f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
505f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void SetState_(StateId s) { SetState(s); }
506f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Find_(Label label) { return Find(label); }
507f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Done_() const { return Done(); }
508f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const Arc& Value_() const { return Value(); }
509f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void Next_() { Next(); }
510f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
511f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  M *matcher_;
512f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatchType match_type_;  // Type of match requested
513f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label rho_label_;       // Label that represents the rho transition
514f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool rewrite_both_;     // Rewrite both sides when both are 'rho_label_'
515f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool has_rho_;          // Are there possibly rhos at the current state?
516f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label rho_match_;       // Current label that matches rho transition
517f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  mutable Arc rho_arc_;   // Arc to return when rho match
518f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool error_;            // Error encountered
519f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
520f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const RhoMatcher<M> &);  // Disallow
521f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
522f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
523f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M> inline
524f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonuint64 RhoMatcher<M>::Properties(uint64 inprops) const {
525f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 outprops = matcher_->Properties(inprops);
526f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (error_) outprops |= kError;
527f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
528f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (match_type_ == MATCH_NONE) {
529f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops;
530f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_type_ == MATCH_INPUT) {
531f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_both_) {
532f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kODeterministic | kNonODeterministic | kString |
533f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted |
534f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
535f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
536f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kODeterministic | kAcceptor | kString |
537f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted);
538f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
539f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_type_ == MATCH_OUTPUT) {
540f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_both_) {
541f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kIDeterministic | kNonIDeterministic | kString |
542f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted |
543f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
544f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
545f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kIDeterministic | kAcceptor | kString |
546f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
547f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
548f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
549f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Shouldn't ever get here.
550f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "RhoMatcher:: bad match type: " << match_type_;
551f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return 0;
552f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
553f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
554f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
555f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
556f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// For any requested label, this matcher considers all transitions
557f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// that match the label 'sigma_label' (sigma = "any"), and this in
558f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// additions to transitions with the requested label.  Each such sigma
559f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// transition found is returned with the sigma_label rewritten as the
560f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// requested label (both sides if an acceptor, or if 'rewrite_both' is
561f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// true and both input and output labels of the found transition are
562f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 'sigma_label').  If 'sigma_label' is kNoLabel, this special
563f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// matching is not done.  SigmaMatcher is templated itself on a
564f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// matcher, which is used to perform the underlying matching.  By
565f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// default, the underlying matcher is constructed by SigmaMatcher.
566f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The user can instead pass in this object; in that case,
567f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// SigmaMatcher takes its ownership.
568f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M>
569f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass SigmaMatcher : public MatcherBase<typename M::Arc> {
570f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
571f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::FST FST;
572f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::Arc Arc;
573f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
574f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
575f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
576f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
577f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SigmaMatcher(const FST &fst,
578f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               MatchType match_type,
579f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               Label sigma_label = kNoLabel,
580f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               MatcherRewriteMode rewrite_mode = MATCHER_REWRITE_AUTO,
581f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               M *matcher = 0)
582f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(matcher ? matcher : new M(fst, match_type)),
583f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(match_type),
584f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        sigma_label_(sigma_label),
585f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(false) {
586f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_type == MATCH_BOTH) {
587f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "SigmaMatcher: bad match type";
588f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      match_type_ = MATCH_NONE;
589f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
590f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
591f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (sigma_label == 0) {
592f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "SigmaMatcher: 0 cannot be used as sigma_label";
593f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sigma_label_ = kNoLabel;
594f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
595f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
596f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
597f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_mode == MATCHER_REWRITE_AUTO)
598f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = fst.Properties(kAcceptor, true);
599f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (rewrite_mode == MATCHER_REWRITE_ALWAYS)
600f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = true;
601f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
602f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = false;
603f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
604f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
605f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  SigmaMatcher(const SigmaMatcher<M> &matcher, bool safe = false)
606f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(new M(*matcher.matcher_, safe)),
607f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(matcher.match_type_),
608f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        sigma_label_(matcher.sigma_label_),
609f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rewrite_both_(matcher.rewrite_both_),
610f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(matcher.error_) {}
611f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
612f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual ~SigmaMatcher() {
613f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    delete matcher_;
614f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
615f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
616f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual SigmaMatcher<M> *Copy(bool safe = false) const {
617f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new SigmaMatcher<M>(*this, safe);
618f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
619f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
620f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual MatchType Type(bool test) const { return matcher_->Type(test); }
621f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
622f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) {
623f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->SetState(s);
624f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    has_sigma_ =
625f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        sigma_label_ != kNoLabel ? matcher_->Find(sigma_label_) : false;
626f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
627f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
628f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Find(Label match_label) {
629f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    match_label_ = match_label;
630f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_label == sigma_label_ && sigma_label_ != kNoLabel) {
631f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "SigmaMatcher::Find: bad label (sigma)";
632f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
633f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return false;
634f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
635f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (matcher_->Find(match_label)) {
636f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sigma_match_ = kNoLabel;
637f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return true;
638f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else if (has_sigma_ && match_label != 0 && match_label != kNoLabel &&
639f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               matcher_->Find(sigma_label_)) {
640f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sigma_match_ = match_label;
641f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return true;
642f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
643f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return false;
644f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
645f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
646f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
647f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const {
648f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return matcher_->Done();
649f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
650f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
651f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Arc& Value() const {
652f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (sigma_match_ == kNoLabel) {
653f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return matcher_->Value();
654f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
655f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sigma_arc_ = matcher_->Value();
656f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (rewrite_both_) {
657f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (sigma_arc_.ilabel == sigma_label_)
658f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          sigma_arc_.ilabel = sigma_match_;
659f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (sigma_arc_.olabel == sigma_label_)
660f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          sigma_arc_.olabel = sigma_match_;
661f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else if (match_type_ == MATCH_INPUT) {
662f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        sigma_arc_.ilabel = sigma_match_;
663f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      } else {
664f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        sigma_arc_.olabel = sigma_match_;
665f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
666f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return sigma_arc_;
667f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
668f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
669f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
670f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() {
671f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->Next();
672f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (matcher_->Done() && has_sigma_ && (sigma_match_ == kNoLabel) &&
673f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        (match_label_ > 0)) {
674f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      matcher_->Find(sigma_label_);
675f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      sigma_match_ = match_label_;
676f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
677f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
678f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
679f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const FST &GetFst() const { return matcher_->GetFst(); }
680f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
681f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual uint64 Properties(uint64 props) const;
682f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
683dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  virtual uint32 Flags() const {
684dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (sigma_label_ == kNoLabel || match_type_ == MATCH_NONE)
685dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      return matcher_->Flags();
686dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    // kRequireMatch temporarily disabled until issues
687dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    // in //speech/gaudi/annotation/util/denorm are resolved.
688dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    // return matcher_->Flags() | kRequireMatch;
689dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    return matcher_->Flags();
690dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  }
691dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin
692f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonprivate:
693f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void SetState_(StateId s) { SetState(s); }
694f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Find_(Label label) { return Find(label); }
695f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Done_() const { return Done(); }
696f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const Arc& Value_() const { return Value(); }
697f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void Next_() { Next(); }
698f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
699f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  M *matcher_;
700f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatchType match_type_;   // Type of match requested
701f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label sigma_label_;      // Label that represents the sigma transition
702f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool rewrite_both_;      // Rewrite both sides when both are 'sigma_label_'
703f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool has_sigma_;         // Are there sigmas at the current state?
704f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label sigma_match_;      // Current label that matches sigma transition
705f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  mutable Arc sigma_arc_;  // Arc to return when sigma match
706f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label match_label_;      // Label being matched
707f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool error_;             // Error encountered
708f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
709f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const SigmaMatcher<M> &);  // disallow
710f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
711f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
712f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M> inline
713f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonuint64 SigmaMatcher<M>::Properties(uint64 inprops) const {
714f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 outprops = matcher_->Properties(inprops);
715f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (error_) outprops |= kError;
716f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
717f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (match_type_ == MATCH_NONE) {
718f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops;
719f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (rewrite_both_) {
720f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops & ~(kIDeterministic | kNonIDeterministic |
721f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kODeterministic | kNonODeterministic |
722f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kILabelSorted | kNotILabelSorted |
723f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kOLabelSorted | kNotOLabelSorted |
724f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kString);
725f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_type_ == MATCH_INPUT) {
726f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops & ~(kIDeterministic | kNonIDeterministic |
727f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kODeterministic | kNonODeterministic |
728f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kILabelSorted | kNotILabelSorted |
729f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kString | kAcceptor);
730f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_type_ == MATCH_OUTPUT) {
731f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops & ~(kIDeterministic | kNonIDeterministic |
732f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kODeterministic | kNonODeterministic |
733f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kOLabelSorted | kNotOLabelSorted |
734f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                     kString | kAcceptor);
735f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
736f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Shouldn't ever get here.
737f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "SigmaMatcher:: bad match type: " << match_type_;
738f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return 0;
739f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
740f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
741f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
742f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
743f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// For any requested label that doesn't match at a state, this matcher
744f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// considers the *unique* transition that matches the label 'phi_label'
745f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// (phi = 'fail'), and recursively looks for a match at its
746f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// destination.  When 'phi_loop' is true, if no match is found but a
747f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// phi self-loop is found, then the phi transition found is returned
748f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// with the phi_label rewritten as the requested label (both sides if
749f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// an acceptor, or if 'rewrite_both' is true and both input and output
750f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// labels of the found transition are 'phi_label').  If 'phi_label' is
751f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// kNoLabel, this special matching is not done.  PhiMatcher is
752f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// templated itself on a matcher, which is used to perform the
753f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// underlying matching.  By default, the underlying matcher is
754f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// constructed by PhiMatcher. The user can instead pass in this
755f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// object; in that case, PhiMatcher takes its ownership.
756f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Warning: phi non-determinism not supported (for simplicity).
757f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M>
758f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass PhiMatcher : public MatcherBase<typename M::Arc> {
759f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
760f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::FST FST;
761f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::Arc Arc;
762f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
763f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
764f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
765f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
766f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  PhiMatcher(const FST &fst,
767f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             MatchType match_type,
768f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             Label phi_label = kNoLabel,
769f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             bool phi_loop = true,
770f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             MatcherRewriteMode rewrite_mode = MATCHER_REWRITE_AUTO,
771f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             M *matcher = 0)
772f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(matcher ? matcher : new M(fst, match_type)),
773f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(match_type),
774f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        phi_label_(phi_label),
775f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        state_(kNoStateId),
776f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        phi_loop_(phi_loop),
777f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(false) {
778f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_type == MATCH_BOTH) {
779f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "PhiMatcher: bad match type";
780f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      match_type_ = MATCH_NONE;
781f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
782f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
783f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
784f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_mode == MATCHER_REWRITE_AUTO)
785f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = fst.Properties(kAcceptor, true);
786f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else if (rewrite_mode == MATCHER_REWRITE_ALWAYS)
787f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = true;
788f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    else
789f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      rewrite_both_ = false;
790f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson   }
791f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
792f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  PhiMatcher(const PhiMatcher<M> &matcher, bool safe = false)
793f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(new M(*matcher.matcher_, safe)),
794f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        match_type_(matcher.match_type_),
795f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        phi_label_(matcher.phi_label_),
796f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        rewrite_both_(matcher.rewrite_both_),
797f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        state_(kNoStateId),
798f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        phi_loop_(matcher.phi_loop_),
799f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        error_(matcher.error_) {}
800f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
801f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual ~PhiMatcher() {
802f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    delete matcher_;
803f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
804f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
805f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual PhiMatcher<M> *Copy(bool safe = false) const {
806f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new PhiMatcher<M>(*this, safe);
807f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
808f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
809f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual MatchType Type(bool test) const { return matcher_->Type(test); }
810f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
811f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) {
812f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->SetState(s);
813f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    state_ = s;
814f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    has_phi_ = phi_label_ != kNoLabel;
815f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
816f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
817f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Find(Label match_label);
818f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
819f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const { return matcher_->Done(); }
820f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
821f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Arc& Value() const {
822f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if ((phi_match_ == kNoLabel) && (phi_weight_ == Weight::One())) {
823f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return matcher_->Value();
824dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    } else if (phi_match_ == 0) {  // Virtual epsilon loop
825dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      phi_arc_ = Arc(kNoLabel, 0, Weight::One(), state_);
826dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      if (match_type_ == MATCH_OUTPUT)
827dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin        swap(phi_arc_.ilabel, phi_arc_.olabel);
828dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      return phi_arc_;
829f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
830f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      phi_arc_ = matcher_->Value();
831f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      phi_arc_.weight = Times(phi_weight_, phi_arc_.weight);
832dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      if (phi_match_ != kNoLabel) {  // Phi loop match
833f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (rewrite_both_) {
834f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (phi_arc_.ilabel == phi_label_)
835f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            phi_arc_.ilabel = phi_match_;
836f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (phi_arc_.olabel == phi_label_)
837f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson            phi_arc_.olabel = phi_match_;
838f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        } else if (match_type_ == MATCH_INPUT) {
839f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          phi_arc_.ilabel = phi_match_;
840f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        } else {
841f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          phi_arc_.olabel = phi_match_;
842f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
843f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
844f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return phi_arc_;
845f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
846f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
847f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
848f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() { matcher_->Next(); }
849f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
850f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const FST &GetFst() const { return matcher_->GetFst(); }
851f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
852f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual uint64 Properties(uint64 props) const;
853f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
854dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  virtual uint32 Flags() const {
855dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (phi_label_ == kNoLabel || match_type_ == MATCH_NONE)
856dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      return matcher_->Flags();
857dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    return matcher_->Flags() | kRequireMatch;
858dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  }
859dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin
860f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonprivate:
861f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void SetState_(StateId s) { SetState(s); }
862f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Find_(Label label) { return Find(label); }
863f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual bool Done_() const { return Done(); }
864f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual const Arc& Value_() const { return Value(); }
865f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual void Next_() { Next(); }
866f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
867f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  M *matcher_;
868f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatchType match_type_;  // Type of match requested
869f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label phi_label_;       // Label that represents the phi transition
870f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool rewrite_both_;     // Rewrite both sides when both are 'phi_label_'
871f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool has_phi_;          // Are there possibly phis at the current state?
872f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Label phi_match_;       // Current label that matches phi loop
873f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  mutable Arc phi_arc_;   // Arc to return
874f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId state_;         // State where looking for matches
875f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Weight phi_weight_;     // Product of the weights of phi transitions taken
876f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool phi_loop_;         // When true, phi self-loop are allowed and treated
877f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                          // as rho (required for Aho-Corasick)
878f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool error_;             // Error encountered
879f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
880f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const PhiMatcher<M> &);  // disallow
881f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
882f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
883f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M> inline
884f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonbool PhiMatcher<M>::Find(Label match_label) {
885dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  if (match_label == phi_label_ && phi_label_ != kNoLabel && phi_label_ != 0) {
886dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    FSTERROR() << "PhiMatcher::Find: bad label (phi): " << phi_label_;
887f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    error_ = true;
888f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return false;
889f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
890f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  matcher_->SetState(state_);
891f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  phi_match_ = kNoLabel;
892f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  phi_weight_ = Weight::One();
893dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  if (phi_label_ == 0) {          // When 'phi_label_ == 0',
894dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (match_label == kNoLabel)  // there are no more true epsilon arcs,
895dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      return false;
896dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (match_label == 0) {       // but virtual eps loop need to be returned
897dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      if (!matcher_->Find(kNoLabel)) {
898dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin        return matcher_->Find(0);
899dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      } else {
900dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin        phi_match_ = 0;
901dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin        return true;
902dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      }
903dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    }
904dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin  }
905f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (!has_phi_ || match_label == 0 || match_label == kNoLabel)
906f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return matcher_->Find(match_label);
907f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId state = state_;
908f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  while (!matcher_->Find(match_label)) {
909dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    // Look for phi transition (if phi_label_ == 0, we need to look
910dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    // for -1 to avoid getting the virtual self-loop)
911dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (!matcher_->Find(phi_label_ == 0 ? -1 : phi_label_))
912f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return false;
913f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (phi_loop_ && matcher_->Value().nextstate == state) {
914f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      phi_match_ = match_label;
915f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return true;
916f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
917f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    phi_weight_ = Times(phi_weight_, matcher_->Value().weight);
918f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    state = matcher_->Value().nextstate;
919f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->Next();
920f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!matcher_->Done()) {
921f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "PhiMatcher: phi non-determinism not supported";
922f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      error_ = true;
923f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
924f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->SetState(state);
925f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
926f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return true;
927f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
928f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
929f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M> inline
930f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonuint64 PhiMatcher<M>::Properties(uint64 inprops) const {
931f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 outprops = matcher_->Properties(inprops);
932f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (error_) outprops |= kError;
933f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
934f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (match_type_ == MATCH_NONE) {
935f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return outprops;
936f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_type_ == MATCH_INPUT) {
937dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (phi_label_ == 0) {
938dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      outprops &= ~kEpsilons | ~kIEpsilons | ~kOEpsilons;
939dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      outprops |= kNoEpsilons | kNoIEpsilons;
940dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    }
941f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_both_) {
942f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kODeterministic | kNonODeterministic | kString |
943f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted |
944f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
945f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
946f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kODeterministic | kAcceptor | kString |
947f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted |
948f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
949f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
950f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_type_ == MATCH_OUTPUT) {
951dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    if (phi_label_ == 0) {
952dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      outprops &= ~kEpsilons | ~kIEpsilons | ~kOEpsilons;
953dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin      outprops |= kNoEpsilons | kNoOEpsilons;
954dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    }
955f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (rewrite_both_) {
956f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kIDeterministic | kNonIDeterministic | kString |
957f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted |
958f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
959f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
960f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      return outprops & ~(kIDeterministic | kAcceptor | kString |
961f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kILabelSorted | kNotILabelSorted |
962f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                       kOLabelSorted | kNotOLabelSorted);
963f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
964f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
965f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Shouldn't ever get here.
966f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "PhiMatcher:: bad match type: " << match_type_;
967f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return 0;
968f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
969f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
970f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
971f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
972f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
973f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// MULTI-EPS MATCHER FLAGS
974f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
975f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
976f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Return multi-epsilon arcs for Find(kNoLabel).
977f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst uint32 kMultiEpsList =  0x00000001;
978f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
979f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Return a kNolabel loop for Find(multi_eps).
980f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst uint32 kMultiEpsLoop =  0x00000002;
981f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
982f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// MultiEpsMatcher: allows treating multiple non-0 labels as
983f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// non-consuming labels in addition to 0 that is always
984f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// non-consuming. Precise behavior controlled by 'flags' argument. By
985f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// default, the underlying matcher is constructed by
986f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// MultiEpsMatcher. The user can instead pass in this object; in that
987f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// case, MultiEpsMatcher takes its ownership iff 'own_matcher' is
988f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// true.
989f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M>
990f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass MultiEpsMatcher {
991f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
992f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::FST FST;
993f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename M::Arc Arc;
994f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
995f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
996f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
997f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
998f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MultiEpsMatcher(const FST &fst, MatchType match_type,
999f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                  uint32 flags = (kMultiEpsLoop | kMultiEpsList),
1000f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                  M *matcher = 0, bool own_matcher = true)
1001f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(matcher ? matcher : new M(fst, match_type)),
1002f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        flags_(flags),
1003f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        own_matcher_(matcher ?  own_matcher : true) {
1004f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (match_type == MATCH_INPUT) {
1005f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      loop_.ilabel = kNoLabel;
1006f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      loop_.olabel = 0;
1007f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
1008f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      loop_.ilabel = 0;
1009f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      loop_.olabel = kNoLabel;
1010f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
1011f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    loop_.weight = Weight::One();
1012f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    loop_.nextstate = kNoStateId;
1013f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1014f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1015f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MultiEpsMatcher(const MultiEpsMatcher<M> &matcher, bool safe = false)
1016f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      : matcher_(new M(*matcher.matcher_, safe)),
1017f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        flags_(matcher.flags_),
1018f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        own_matcher_(true),
1019f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        multi_eps_labels_(matcher.multi_eps_labels_),
1020f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        loop_(matcher.loop_) {
1021f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    loop_.nextstate = kNoStateId;
1022f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1023f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1024f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ~MultiEpsMatcher() {
1025f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (own_matcher_)
1026f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      delete matcher_;
1027f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1028f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1029f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MultiEpsMatcher<M> *Copy(bool safe = false) const {
1030f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new MultiEpsMatcher<M>(*this, safe);
1031f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1032f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1033f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatchType Type(bool test) const { return matcher_->Type(test); }
1034f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1035f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) {
1036f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    matcher_->SetState(s);
1037f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    loop_.nextstate = s;
1038f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1039f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1040f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Find(Label match_label);
1041f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1042f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const {
1043f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return done_;
1044f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1045f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1046f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Arc& Value() const {
1047f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return current_loop_ ? loop_ : matcher_->Value();
1048f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1049f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1050f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() {
1051f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!current_loop_) {
1052f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      matcher_->Next();
1053f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      done_ = matcher_->Done();
1054f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (done_ && multi_eps_iter_ != multi_eps_labels_.End()) {
1055f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ++multi_eps_iter_;
1056f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        while ((multi_eps_iter_ != multi_eps_labels_.End()) &&
1057f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               !matcher_->Find(*multi_eps_iter_))
1058f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ++multi_eps_iter_;
1059f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (multi_eps_iter_ != multi_eps_labels_.End())
1060f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          done_ = false;
1061f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        else
1062f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          done_ = !matcher_->Find(kNoLabel);
1063f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1064f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
1065f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
1066f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      done_ = true;
1067f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
1068f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1069f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1070f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const FST &GetFst() const { return matcher_->GetFst(); }
1071f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1072f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const { return matcher_->Properties(props); }
1073f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1074f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint32 Flags() const { return matcher_->Flags(); }
1075f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1076f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void AddMultiEpsLabel(Label label) {
1077f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (label == 0) {
1078f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      FSTERROR() << "MultiEpsMatcher: Bad multi-eps label: 0";
1079f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
1080f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      multi_eps_labels_.Insert(label);
1081f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
1082f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1083f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
10845b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  void RemoveMultiEpsLabel(Label label) {
10855b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    if (label == 0) {
10865b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      FSTERROR() << "MultiEpsMatcher: Bad multi-eps label: 0";
10875b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    } else {
10885b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin      multi_eps_labels_.Erase(label);
10895b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin    }
10905b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin  }
10915b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin
1092f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void ClearMultiEpsLabels() {
1093f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    multi_eps_labels_.Clear();
1094f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1095f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1096f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonprivate:
1097f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  M *matcher_;
1098f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint32 flags_;
1099f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool own_matcher_;             // Does this class delete the matcher?
1100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Multi-eps label set
1102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  CompactSet<Label, kNoLabel> multi_eps_labels_;
1103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typename CompactSet<Label, kNoLabel>::const_iterator multi_eps_iter_;
1104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool current_loop_;            // Current arc is the implicit loop
1106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  mutable Arc loop_;             // For non-consuming symbols
1107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool done_;                    // Matching done
1108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const MultiEpsMatcher<M> &);  // Disallow
1110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class M> inline
1113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonbool MultiEpsMatcher<M>::Find(Label match_label) {
1114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  multi_eps_iter_ = multi_eps_labels_.End();
1115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  current_loop_ = false;
1116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool ret;
1117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (match_label == 0) {
1118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ret = matcher_->Find(0);
1119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if (match_label == kNoLabel) {
1120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (flags_ & kMultiEpsList) {
1121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      // return all non-consuming arcs (incl. epsilon)
1122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      multi_eps_iter_ = multi_eps_labels_.Begin();
1123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      while ((multi_eps_iter_ != multi_eps_labels_.End()) &&
1124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             !matcher_->Find(*multi_eps_iter_))
1125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ++multi_eps_iter_;
1126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (multi_eps_iter_ != multi_eps_labels_.End())
1127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ret = true;
1128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      else
1129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        ret = matcher_->Find(kNoLabel);
1130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    } else {
1131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      // return all epsilon arcs
1132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      ret = matcher_->Find(kNoLabel);
1133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
1134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else if ((flags_ & kMultiEpsLoop) &&
1135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson             multi_eps_labels_.Find(match_label) != multi_eps_labels_.End()) {
1136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // return 'implicit' loop
1137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    current_loop_ = true;
1138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ret = true;
1139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  } else {
1140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ret = matcher_->Find(match_label);
1141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  done_ = !ret;
1143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  return ret;
1144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
1145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Generic matcher, templated on the FST definition
1148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// - a wrapper around pointer to specific one.
1149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Here is a typical use: \code
1150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   Matcher<StdFst> matcher(fst, MATCH_INPUT);
1151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   matcher.SetState(state);
1152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   if (matcher.Find(label))
1153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     for (; !matcher.Done(); matcher.Next()) {
1154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       StdArc &arc = matcher.Value();
1155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       ...
1156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     } \endcode
1157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class F>
1158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass Matcher {
1159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
1160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef F FST;
1161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename F::Arc Arc;
1162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
1163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Label Label;
1164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::Weight Weight;
1165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Matcher(const F &fst, MatchType match_type) {
1167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    base_ = fst.InitMatcher(match_type);
1168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!base_)
1169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      base_ = new SortedMatcher<F>(fst, match_type);
1170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Matcher(const Matcher<F> &matcher, bool safe = false) {
1173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    base_ = matcher.base_->Copy(safe);
1174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Takes ownership of the provided matcher
1177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Matcher(MatcherBase<Arc>* base_matcher) { base_ = base_matcher; }
1178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ~Matcher() { delete base_; }
1180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  Matcher<F> *Copy(bool safe = false) const {
1182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return new Matcher<F>(*this, safe);
1183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
1184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatchType Type(bool test) const { return base_->Type(test); }
1186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void SetState(StateId s) { base_->SetState(s); }
1187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Find(Label label) { return base_->Find(label); }
1188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool Done() const { return base_->Done(); }
1189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const Arc& Value() const { return base_->Value(); }
1190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void Next() { base_->Next(); }
1191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  const F &GetFst() const { return static_cast<const F &>(base_->GetFst()); }
1192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint64 Properties(uint64 props) const { return base_->Properties(props); }
1193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  uint32 Flags() const { return base_->Flags() & kMatcherFlags; }
1194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private:
1196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  MatcherBase<Arc> *base_;
1197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void operator=(const Matcher<Arc> &);  // disallow
1199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
1200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
1202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
1205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_MATCHER_H__
1206