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 */ 36 struct 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 */ 68 typedef 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 */ 85 typedef 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 } 254 SR_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 */ 310 SREC_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 */ 337 SREC_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 */ 347 SREC_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 */ 360 SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAddNametagToSlot(SR_Grammar* self, const LCHAR* slot, 361 const 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 */ 385 SREC_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); 394 SREC_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 */ 401 SREC_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 */ 424 SREC_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 */ 431 SREC_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 */ 442 SREC_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 */ 450 SREC_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 */ 460 SREC_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 */ 469 SREC_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 */ 479 SREC_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 */ 488 SREC_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 */ 498 SREC_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 */ 508 SREC_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 517 SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAllowOnly(SR_Grammar* self, const char* transcription); 518 SREC_GRAMMAR_API ESR_ReturnCode SR_GrammarAllowAll(SR_Grammar* self); 519 520 #endif /* __SR_GRAMMAR_H */ 521