1/*---------------------------------------------------------------------------*
2 *  SR_Grammar.h  *
3 *                                                                           *
4 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20#ifndef __SR_GRAMMAR_H
21#define __SR_GRAMMAR_H
22
23
24
25#include "ESR_ReturnCode.h"
26#include "pstdio.h"
27#include "ptypes.h"
28#include "SR_GrammarPrefix.h"
29#include "SR_NametagDefs.h"
30#include "SR_Vocabulary.h"
31#include "SR_AcousticModels.h"
32#include "SR_Recognizer.h"
33#include "SR_SemanticResult.h"
34
35/* forward decl needed because of SR_Recognizer.h <-> SR_Grammar.h include loop */
36struct SR_Recognizer_t;
37
38/**
39 * @addtogroup SR_GrammarModule SR_Grammar API functions
40 * Contains recognition grammar.
41 *
42 * A grammar consists of a list of rules.
43 *
44 * A rule consists of a list of words and slots. For example:
45 * MY_RULE = "My name is $name" where "name" is a slot
46 *
47 * Words, Nametags may be added or removed from slots.
48 * Upon adding and removing words, the grammar needs to be recompiled for the changes to
49 * take place. However, the original CompiledGrammar remains valid even if compilation never
50 * takes place.
51 *
52 * Two types of slots exist: word slots and nametag slots
53 *
54 * @{
55 */
56
57/**
58 * Grammar dispatch function. Used for symantic processing.
59 *
60 * @param functionName Name of function that was invoked
61 * @param argv Argument values passed to function
62 * @param argc Number of arguments passed to function
63 * @param value Dispatch value (specified using SR_GrammarSetDispatchValue)
64 * @param result Result of function operation. Caller passes in this buffer, function fills it.
65 * @param resultSize Size of result buffer. If the passed in buffer was not large enough to hold
66 *                   the result, this value is updated with the required length.
67 */
68typedef ESR_ReturnCode(*SR_GrammarDispatchFunction)(LCHAR* functionName, LCHAR** argv, size_t argc, void* value, LCHAR* result, size_t* resultSize);
69
70/**
71 * Contains recognition grammar.
72 *
73 * A grammar consists of a list of rules.
74 *
75 * A rule consists of a list of words and slots. For example:
76 * MY_RULE = "My name is $name" where "name" is a slot
77 *
78 * Words, Nametags may be added or removed from slots.
79 * Upon adding and removing words, the grammar needs to be recompiled for the changes to
80 * take place. However, the original CompiledGrammar remains valid even if compilation never
81 * takes place.
82 *
83 * Two types of slots exist: word slots and nametag slots
84 */
85typedef struct SR_Grammar_t
86{
87  /**
88   * Compiles the grammar.
89   * In the case of a precompiled grammar, the function compiles those portions of the grammar
90   * that were dynamically added since the last compilation.
91   *
92   * @param self SR_Grammar handle
93  * @return ESR_SUCCESS if compilation succeeded, ESR_FATAL_ERROR otherwise.
94   */
95  ESR_ReturnCode(*compile)(struct SR_Grammar_t* self);
96
97  /**
98  * Saves a compiled grammar to a file.
99  *
100  * @param self SR_Grammar handle
101  * @param filename File to write grammar into
102  * @return ESR_INVALID_ARGUMENT if self or filename are null; ESR_INVALID_STATE if could not save the grammar
103  */
104  ESR_ReturnCode(*save)(struct SR_Grammar_t* self, const LCHAR* filename);
105
106  /**
107   * Indicates if a transcription is a valid result of a Grammar rule.
108   *
109   * @param self SR_Grammar handle
110   * @param transcription Transcription value
111   * @param result [in/out] Array of semantic results to be populated
112   * @param resultCount [in/out] Length of result array
113  * @return ESR_INVALID_ARGUMENT if self or transcription are null; ESR_INVALID_STATE if an internal error has occured.
114   */
115  ESR_ReturnCode(*checkParse)(struct SR_Grammar_t* self, const LCHAR* transcription, SR_SemanticResult** result, size_t* resultCount);
116
117  /**
118   * Adds word to rule slot.
119   *
120   * @param self SR_Grammar handle
121   * @param slot Slot name
122   * @param word Word to be added to the slot
123   * @param pronunciation Word pronunciation (optional). Pass NULL to omit.
124   * @param weight value to associate with word when adding to grammar; use to determine cost when parsing
125   * @param tag eScript semantic expression (tag) for the word
126   * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_STATE if the vocabulary is missing,
127   * if OSI logging fails; ESR_OUT_OF_MEMORY if word cannot be added to the grammar
128   * (addWords=X is too small); ESR_NOT_SUPPORTED if homonyms are added to the grammar
129   */
130  ESR_ReturnCode(*addWordToSlot)(struct SR_Grammar_t* self, const LCHAR* slot, const LCHAR* word,
131		const LCHAR* pronunciation, int weight, const LCHAR* tag);
132
133  /**
134   * Removes all elements from all slots.
135   *
136   * @param self SR_Grammar handle
137   * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_STATE if resetting the slots or OSI logging fails
138   */
139  ESR_ReturnCode(*resetAllSlots)(struct SR_Grammar_t* self);
140
141  /**
142   * Adds nametag to rule slot.
143   *
144   * @param self SR_Grammar handle
145   * @param slot Slot name
146   * @param nametag Nametag to be added to the grammar
147   * @param weight value to associate with nametag when adding to grammar; use to determine cost when parsing
148   * @param tag eScript semantic expression (tag) for the nametag
149   * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_STATE if the grammar is active,
150   * if the vocabulary is missing, if OSI logging fails; ESR_OUT_OF_MEMORY if word cannot be added to
151   * the grammar (addWords=X is too small); ESR_NOT_SUPPORTED if homonyms are added to the grammar
152   */
153  ESR_ReturnCode(*addNametagToSlot)(struct SR_Grammar_t* self, const LCHAR* slot,
154    const SR_Nametag* nametag, int weight, const LCHAR* tag);
155
156  /**
157   * Sets user dispatch function (used for parsed callback, etc)
158   *
159   * @param self SR_Grammar handle
160   * @param name The name of the function which will trigger this callback when encountered during grammar parsing.
161   * @param userData The user data to be referenced in the callback implementation later on.
162   * @param function The dispatch function
163   * @return ESR_INVALID_ARGUMENT if self is null; ESR_SUCCESS
164   */
165  ESR_ReturnCode(*setDispatchFunction)(struct SR_Grammar_t* self, const LCHAR* name, void* userData, SR_GrammarDispatchFunction function);
166
167  /**
168   * Sets grammar parameter, overriding session defaults.
169   *
170   * @param self SR_Grammar handle
171   * @param key Parameter name
172   * @param value Parameter value
173  * @return ESR_INVALID_ARGUMENT if self is null; ESR_NOT_IMPLEMENTED
174   */
175  ESR_ReturnCode(*setParameter)(struct SR_Grammar_t* self, const LCHAR* key, void* value);
176
177  /**
178   * Sets grammar parameters.
179   * This is a convenience function.
180   *
181   * @param self SR_Grammar handle
182   * @param key Parameter name
183   * @param value Parameter value
184  * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_RESULT_TYPE if the property is already set and its type is size_t
185   */
186  ESR_ReturnCode(*setSize_tParameter)(struct SR_Grammar_t* self, const LCHAR* key, size_t value);
187
188  /**
189   * Returns grammar parameter value.
190   *
191   * @param self SR_Grammar handle
192   * @param key Parameter name
193   * @param value Parameter value
194  * @return ESR_INVALID_ARGUMENT if self is null; ESR_NOT_IMPLEMENTED
195   */
196  ESR_ReturnCode(*getParameter)(struct SR_Grammar_t* self, const LCHAR* key, void** value);
197
198  /**
199   * Return copy of unsigned int grammar parameter.
200   * This is a convenience function.
201   *
202   * @param self SR_Grammar handle
203   * @param key Parameter name
204   * @param value [out] Used to hold the parameter value
205   * @param len [in/out] Length of value argument. If the return code is ESR_BUFFER_OVERFLOW,
206   *            the required length is returned in this variable.
207  * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_RESULT_TYPE if the property type is not size_t; ESR_NO_MATCH_ERROR if property is not set
208   */
209  ESR_ReturnCode(*getSize_tParameter)(struct SR_Grammar_t* self, const LCHAR* key, size_t* value);
210
211  /**
212   * Configures a vocabulary with the grammar.
213   *
214   * @param self SR_Grammar handle
215   * @param vocabulary The vocabulary to associate with
216  * @return ESR_INVALID_ARGUMENT if self or vocabulary are null
217   */
218  ESR_ReturnCode(*setupVocabulary)(struct SR_Grammar_t *self, SR_Vocabulary *vocabulary);
219
220  /**
221   * Associates Recognizer with the grammar.
222   *
223   * @param self SR_Grammar handle
224   * @param recognizer The recognizer to associate
225   * @return ESR_INVALID_ARGUMENT if self or recognizer are null
226   */
227  // ESR_ReturnCode(*setupModels)(struct SR_Grammar_t* self, SR_AcousticModels* models);
228  ESR_ReturnCode(*setupRecognizer)(struct SR_Grammar_t* self, struct SR_Recognizer_t* recognizer);
229  /**
230   * Dissociates Recognizer with the grammar.
231   *
232   * @param self SR_Grammar handle
233   * @return ESR_INVALID_ARGUMENT if self is null
234   */
235  ESR_ReturnCode(*unsetupRecognizer)(struct SR_Grammar_t* self);
236
237  /**
238   * Returns AcousticModels associated with the grammar.
239   *
240   * @param self SR_Grammar handle
241   * @param models Associated models
242  * @return ESR_INVALID_ARGUMENT if self or models are null
243   */
244  // ESR_ReturnCode(*getModels)(struct SR_Grammar_t* self, SR_AcousticModels** models);
245
246  /**
247   * Destroys a grammar.
248   *
249   * @param self SR_Grammar handle
250  * @return ESR_INVALID_ARGUMENT if self is null, ESR_INVALID_STATE if OSI logging fails
251   */
252  ESR_ReturnCode(*destroy)(struct SR_Grammar_t* self);
253}
254SR_Grammar;
255
256/**
257 * @name Grammar compilation
258 *
259 * Categories:
260 * - Initialization
261 * - Compile from expressions (not supported by SREC) or load pre-compiled grammars
262 * - Dynamic modification; slots
263 * - Support functions (isExtant, etc)
264 * - Use in recognition; activation
265 *
266 * IMPORTANT NOTE: There are two main approaches to grammar activation in a recognizer.
267 * - 1. Load a pre-compiler grammar setup. This is not just the set of expressions but is also
268 *      an image of the actual model components network that fully describes the recognizer
269 *      task. This type of Grammar can be extended with single arcs at pre-defined points
270 *      called slots.
271 *
272 * - 2. Create a network dynamically from a set of regular expressions.
273 *
274 * SREC supports 1. but not 2. CREC supports 2 but not 1. Both approaches are covered by
275 * this interface. Pre-compiled grammars inherently refer to models. It is therefore
276 * important to ensure consistency of model usage between all activated grammars. This can
277 * be done prior to grammar rule activation in the Recognizer
278 * (see SR_RecognizerCheckGrammarConsistency()).
279 *
280 * A Grammar may consist of one or more rules. Rules are given as expressions (this interface is
281 * independent of the format). A rule may contain other rules. Before a rule can be used in
282 * recognition it must be compiled (or loaded), setup by a recognizer and activated.
283 * -  The Grammar_CompileRule() step combines all sub-rule expressions into a single underlying
284 *    member of Grammar.
285 * -  The Recognizer_ActivateRule() step simply raises a flat to make a compiled rule available
286 *    for recognition.
287 *
288 * Once a Grammar is setup by a recognizer it is not permissible to modify its rules  Thus, in
289 * order to be able to support a combination of a static rule and one that requires changing, it
290 * is most efficient to separate these rules into two Grammar objects.
291 *
292 * NOTE: The modification/setup constraint ensures consistency between the rule definitions
293 * in the Grammar and the setup rules. It would be possible to remove this constraint and
294 * allow rules that had no dependents to be modified while the grammar was setup. This makes
295 * the API freer but also less consistent and more susceptible to error. There would be no
296 * footprint cost with having two grammars in place of one grammar with two rules unless the
297 * rules overlapped. If there was overlap then it might have been possible to minimize the
298 * shared parts
299 * @{
300 */
301
302/**
303 * Compiles the grammar.
304 * In the case of a precompiled grammar, the function compiles those portions of the grammar
305 * that were dynamically added since the last compilation.
306 *
307 * @param self SR_Grammar handle
308 * @return ESR_INVALID_ARGUMENT if self is null; ESR_SUCCESS if compilation succeeded, ESR_FATAL_ERROR otherwise.
309 */
310SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarCompile(SR_Grammar* self);
311/**
312 * @}
313 *
314 * @name Special "Slot"-based Grammar functions
315 *
316 * Slots are points in a pre-compiled grammar where a simple extension of the grammar may
317 * be made. They support the insertion of words or nametags into a pr-defined position in
318 * the Grammar. Slots are first declared in an expression which is compiled and saved for
319 * re-loading. The names of these slots are used in a similar way as rule names.
320 *
321 * @{
322 */
323/**
324 * Adds word to rule slot.
325 *
326 * @param self SR_Grammar handle
327 * @param slot Slot name
328 * @param word Word to be added to the slot
329 * @param pronunciation Word pronunciation (optional). Pass NULL to omit.
330 * @param weight value to associate with word when adding to grammar; use to determine cost when parsing
331 * @param tag eScript semantic expression for the word. In other words, eScript will execute
332 *            "MEANING=<tag>"
333 * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_STATE if the grammar is active,
334 * if the vocabulary is missing, if OSI logging fails; ESR_OUT_OF_MEMORY if word cannot be added to
335 * the grammar (addWords=X is too small); ESR_NOT_SUPPORTED if homonyms are added to the grammar
336 */
337SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAddWordToSlot(SR_Grammar* self, const LCHAR* slot,
338																												const LCHAR* word, const LCHAR* pronunciation,
339																												int weight, const LCHAR* tag);
340/**
341 * Removes all elements from all slots.
342 *
343 * @param self SR_Grammar handle
344 * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_STATE if resetting the slots or
345 * OSI logging fails
346 */
347SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarResetAllSlots(SR_Grammar* self);
348/**
349 * Adds word to rule slot.
350 *
351 * @param self SR_Grammar handle
352 * @param slot Slot name
353 * @param nametag Nametag to be added to the slot
354 * @param weight value to associate with nametag when adding to grammar; use to determine cost when parsing
355 * @param tag eScript semantic expression (tag) for the nametag
356 * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_STATE if the grammar is active, if the
357 * vocabulary is missing, if OSI logging fails; ESR_OUT_OF_MEMORY if word cannot be added to the
358 * grammar (addWords=X is too small); ESR_NOT_SUPPORTED if homonyms are added to the grammar
359 */
360SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAddNametagToSlot(SR_Grammar* self, const LCHAR* slot,
361const struct SR_Nametag_t* nametag, int weight, const LCHAR* tag);
362/**
363 * @}
364 *
365 * @name Grammar Setup functions
366 *
367 * The Grammar object needs an association with several objects:
368 * - A Grammar object must use one and only one Vocabulary object.
369 * - A Grammar object may use one and only one Nametags object. (The Nametags object can
370 *   however be used by more than one Grammar. A Nametags collection object must be used
371 *   before nametags can be added to Grammar slots.)
372 *
373 * @see Nametags_Add() and associated functions for Nametags management.
374 *
375 * @{
376 */
377
378/**
379 * Configures a vocabulary with the grammar.
380 *
381 * @param self SR_Grammar handle
382 * @param vocabulary The vocabulary to associate with
383 * @return ESR_INVALID_ARGUMENT if self or vocabulary are null
384 */
385SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSetupVocabulary(SR_Grammar *self, SR_Vocabulary *vocabulary);
386/**
387 * Associates Grammar with a Recognizer (eg. such that word additions can take place).
388 *
389 * @param self SR_Grammar handle
390 * @param models The recognizer to associate
391 * @return ESR_INVALID_ARGUMENT if self or recognizer are null
392 */
393// SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSetupModels(SR_Grammar* self, SR_AcousticModels* models);
394SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSetupRecognizer(SR_Grammar* self, struct SR_Recognizer_t* recognizer);
395/**
396 * Dissociate Grammar from a Recognizer.
397 *
398 * @param self SR_Grammar handle
399 * @return ESR_INVALID_ARGUMENT if self is null
400 */
401SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarUnsetupRecognizer(SR_Grammar* self);
402/**
403 * Returns AcousticModels associated with a Grammar.
404 *
405 * @param self SR_Grammar handle
406 * @param models Associated models
407 * @return ESR_INVALID_ARGUMENT if self or models are null
408 */
409// SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarGetModels(SR_Grammar* self, SR_AcousticModels** models);
410
411/**
412 * @}
413 *
414 * @name  Basic Grammar functions
415 *
416 * @{
417 */
418
419/**
420 * Create a new grammar.
421 *
422 * @param self SR_Grammar handle
423 */
424SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarCreate(SR_Grammar** self);
425/**
426 * Destroys a grammar.
427 *
428 * @param self SR_Grammar handle
429 * @return ESR_INVALID_ARGUMENT if self is null, ESR_INVALID_STATE if OSI logging fails
430 */
431SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarDestroy(SR_Grammar* self);
432/**
433 * Loads a compiled grammar from a file or an image. If the filename has extention .g2g
434 * then it will be loaded as an image. Otherwise, provide only a basename (i.e. without
435 * file extensions), and a set of text-based grammar files will be loaded.
436 *
437 * @param filename File to read grammar from
438 * @param self SR_Grammar handle
439 * @return ESR_INVALID_ARGUMENT if self or the value it points to are null. If the filename load property
440 * (i.e. addWords=X) is unknown; ESR_OUT_OF_MEMORY if system is out of memory; ESR_READ_ERROR if grammar file be read
441 */
442SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarLoad(const LCHAR* filename, SR_Grammar** self);
443/**
444 * Saves a compiled grammar to a file.
445 *
446 * @param self SR_Grammar handle
447 * @param filename File to write grammar into
448 * @return ESR_INVALID_ARGUMENT if self or filename are null; ESR_INVALID_STATE if could not save the grammar
449 */
450SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSave(SR_Grammar* self, const LCHAR* filename);
451/**
452 * Sets user dispatch function (used for parsed callback, etc)
453 *
454 * @param self SR_Grammar handle
455 * @param name The name of the function which will trigger this callback when encountered during grammar parsing.
456 * @param userData The user data to be referenced in the callback implementation later on.
457 * @param function The dispatch function
458 * @return ESR_SUCCESS
459 */
460SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSetDispatchFunction(SR_Grammar* self, const LCHAR* name, void* userData, SR_GrammarDispatchFunction function);
461/**
462 * Sets grammar parameter, overriding session defaults.
463 *
464 * @param self SR_Grammar handle
465 * @param key Parameter name
466 * @param value Parameter value
467 * @return ESR_NOT_IMPLEMENTED
468 */
469SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSetParameter(SR_Grammar* self, const LCHAR* key, void* value);
470/**
471 * Sets grammar parameters.
472 * This is a convenience function.
473 *
474 * @param self SR_Grammar handle
475 * @param key Parameter name
476 * @param value Parameter value
477 * @return ESR_INVALID_RESULT_TYPE if the property is already set and its type is size_t
478 */
479SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarSetSize_tParameter(SR_Grammar* self, const LCHAR* key, size_t value);
480/**
481 * Returns grammar parameter value.
482 *
483 * @param self SR_Grammar handle
484 * @param key Parameter name
485 * @param value Parameter value
486 * @return ESR_NOT_IMPLEMENTED
487 */
488SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarGetParameter(SR_Grammar* self, const LCHAR* key, void** value);
489/**
490 * Return copy of unsigned int grammar parameter.
491 * This is a convenience function.
492 *
493 * @param self SR_Grammar handle
494 * @param key Parameter name
495 * @param value [out] Used to hold the parameter value
496 * @return ESR_INVALID_ARGUMENT if self is null; ESR_INVALID_RESULT_TYPE if the property type is not size_t; ESR_NO_MATCH_ERROR if property is not set
497 */
498SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarGetSize_tParameter(SR_Grammar* self, const LCHAR* key, size_t* value);
499/**
500 * Checks if transcription is parsable by the grammar.
501 *
502 * @param self SR_Grammar handle
503 * @param transcription transcription to be checked
504 * @param result should be NULL
505 * @param resultCount used to return the number of valid parses
506 * @return ESR_INVALID_ARGUMENT if self, transcription are null; ESR_INVALID_STATE if an internal error has occured.
507 */
508SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarCheckParse(SR_Grammar* self, const LCHAR* transcription, SR_SemanticResult** result, size_t* resultCount);
509/**
510 * @}
511 */
512
513/**
514 * @}
515 */
516
517SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAllowOnly(SR_Grammar* self, const char* transcription);
518SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAllowAll(SR_Grammar* self);
519
520#endif /* __SR_GRAMMAR_H */
521