1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: jpr@google.com (Jake Ratkiewicz)
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// This file defines the registration mechanism for new operations.
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// These operations are designed to enable scripts to work with FST classes
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// at a high level.
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// If you have a new arc type and want these operations to work with FSTs
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// with that arc type, see below for the registration steps
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you must take.
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// These methods are only recommended for use in high-level scripting
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// applications. Most users should use the lower-level templated versions
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// corresponding to these.
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// If you have a new arc type you'd like these operations to work with,
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// use the REGISTER_FST_OPERATIONS macro defined in fstcsript.h
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// If you have a custom operation you'd like to define, you need four
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// components. In the following, assume you want to create a new operation
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// with the signature
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//    void Foo(const FstClass &ifst, MutableFstClass *ofst);
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  You need:
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  1) A way to bundle the args that your new Foo operation will take, as
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     a single struct. The template structs in arg-packs.h provide a handy
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     way to do this. In Foo's case, that might look like this:
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       typedef args::Package<const FstClass &,
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//                             MutableFstClass *> FooArgs;
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     Note: this package of args is going to be passed by non-const pointer.
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  2) A function template that is able to perform Foo, given the args and
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     arc type. Yours might look like this:
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       template<class Arc>
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       void Foo(FooArgs *args) {
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//          // Pull out the actual, arc-templated FSTs
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//          const Fst<Arc> &ifst = args->arg1.GetFst<Arc>();
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//          MutableFst<Arc> *ofst = args->arg2->GetMutableFst<Arc>();
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//          // actually perform foo on ifst and ofst...
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       }
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  3) a client-facing function for your operation. This would look like
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     the following:
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     void Foo(const FstClass &ifst, MutableFstClass *ofst) {
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       // Check that the arc types of the FSTs match
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       if (!ArcTypesMatch(ifst, *ofst, "Foo")) return;
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       // package the args
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       FooArgs args(ifst, ofst);
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       // Finally, call the operation
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       Apply<Operation<FooArgs> >("Foo", ifst->ArcType(), &args);
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     }
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  The Apply<> function template takes care of the link between 2 and 3,
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  provided you also have:
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  4) A registration for your new operation, on the arc types you care about.
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     This can be provided easily by the REGISTER_FST_OPERATION macro in
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     operations.h:
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       REGISTER_FST_OPERATION(Foo, StdArc, FooArgs);
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       REGISTER_FST_OPERATION(Foo, MyArc, FooArgs);
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//       // .. etc
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  That's it! Now when you call Foo(const FstClass &, MutableFstClass *),
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  it dispatches (in #3) via the Apply<> function to the correct
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  instantiation of the template function in #2.
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_SCRIPT_SCRIPT_IMPL_H_
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_SCRIPT_SCRIPT_IMPL_H_
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// This file contains general-purpose templates which are used in the
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// implementation of the operations.
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <utility>
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::pair; using std::make_pair;
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <string>
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/script/fst-class.h>
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/generic-register.h>
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/script/arg-packs.h>
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/types.h>
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace script {
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// A generic register for operations with various kinds of signatures.
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Needed since every function signature requires a new registration class.
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The pair<string, string> is understood to be the operation name and arc
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// type; subclasses (or typedefs) need only provide the operation signature.
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class OperationSignature>
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass GenericOperationRegister
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    : public GenericRegister<pair<string, string>,
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                             OperationSignature,
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                             GenericOperationRegister<OperationSignature> > {
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public:
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  void RegisterOperation(const string &operation_name,
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                         const string &arc_type,
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                         OperationSignature op) {
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    this->SetEntry(make_pair(operation_name, arc_type), op);
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  OperationSignature GetOperation(
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      const string &operation_name, const string &arc_type) {
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return this->GetEntry(make_pair(operation_name, arc_type));
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson protected:
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  virtual string ConvertKeyToSoFilename(
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      const pair<string, string>& key) const {
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Just use the old-style FST for now.
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    string legal_type(key.second);  // the arc type
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    ConvertToLegalCSymbol(&legal_type);
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return legal_type + "-arc.so";
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Operation package - everything you need to register a new type of operation
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The ArgPack should be the type that's passed into each wrapped function -
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// for instance, it might be a struct containing all the args.
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// It's always passed by pointer, so const members should be used to enforce
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// constness where it's needed. Return values should be implemented as a
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// member of ArgPack as well.
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class ArgPack>
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct Operation {
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef ArgPack Args;
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef void (*OpType)(ArgPack *args);
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // The register (hash) type
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef GenericOperationRegister<OpType> Register;
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // The register-er type
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef GenericRegisterer<Register> Registerer;
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Macro for registering new types of operations.
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define REGISTER_FST_OPERATION(Op, Arc, ArgPack)                        \
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  static fst::script::Operation<ArgPack>::Registerer                \
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  arc_dispatched_operation_ ## ArgPack ## Op ## Arc ## _registerer(     \
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      make_pair(#Op, Arc::Type()), Op<Arc>)
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Template function to apply an operation by name
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class OpReg>
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid Apply(const string &op_name, const string &arc_type,
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson           typename OpReg::Args *args) {
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typename OpReg::Register *reg = OpReg::Register::GetRegister();
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typename OpReg::OpType op = reg->GetOperation(op_name, arc_type);
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (op == 0) {
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    FSTERROR() << "No operation found for \"" << op_name << "\" on "
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson               << "arc type " << arc_type;
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return;
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  op(args);
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Helper that logs to ERROR if the arc types of a and b don't match.
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The op_name is also printed.
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonbool ArcTypesMatch(const FstClass &a, const FstClass &b,
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson                   const string &op_name);
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace script
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_SCRIPT_SCRIPT_IMPL_H_
207