You are reading help file online using chmlib.com
|
The code example below illustrates an implementation of a travel grammar, using the ISpGrammarBuilder interface.
An approximation of the XML form is included for each of the following three grammar authoring approaches.
// HRESULT checking code omitted for brevity
SPSTATEHANDLE hStateTravel;
// create (if rule does not already exist) top-level Rule, defaulting to Active
hr = pGrammarBuilder->GetRule(L"Travel", 0, SPRAF_TopLevel | SPRAF_Active, TRUE, &hStateTravel);
{ // Approach 1: list all possible phrases
// This is the most intuitive approach, and it does not sacrifice efficiency
// because the grammar builder will merge shared sub-phrases when possible.
// Internally, SAPI may break the transitions into separate transitions if
// there are common roots (e.g. "fly to Seattle" and "fly to New York").
// There is only one root state, hStateTravel, and the terminal NULL state, and there are 6 unique
// transitions between the root state and the NULL state.
/* XML Approximation:
<RULE NAME="Travel" TOPLEVEL="ACTIVE">
<PHRASE>fly to Seattle</PHRASE>
<PHRASE>fly to New York</PHRASE>
<PHRASE>fly to Washington DC</PHRASE>
<PHRASE>drive to Seattle</PHRASE>
<PHRASE>drive to New York</PHRASE>
<PHRASE>drive to Washington DC</PHRASE>
</RULE>
*/
// create set of peer phrases, each containing complete phrase
// Note: the word delimiter is set as " ", so that the text we attach to the transition can be
// multiple words (e.g. "fly to Seattle" is implicitly "fly" + "to" + "Seattle")
hr = pGrammarBuilder->AddWordTransition(hStateTravel, NULL, L"fly to Seattle", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, NULL, L"fly to New York", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, NULL, L"fly to Washington DC", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, NULL, L"drive to Washington DC", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, NULL, L"drive to New York", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, NULL, L"drive to Washington DC", L" ", SPWT_LEXICAL, 1, NULL);
}
{ // Approach 2: construct the directed-graph using intermediate states
// This approach gives you more control of the grammar layout, and may be
// easier to implement when you have some combinations.
// Using this approach, there is one root state (hStateTravel), one interim state
// (hStateTravel_Second), and the final terminal NULL state. There are three
// unique transitions between the root state and the interim state. And there are
// three more unique transitions between the interim state, and the final NULL state.
// Note that graph includes only 2-transition paths. The user is not capable of saying
// only the first transition or the second transition (e.g. "fly to" is an invalid
// phrase as is "Seattle", but "fly to Seattle" is valid.)
/* XML Approximation:
<RULE NAME="Travel" TOPLEVEL="ACTIVE">
<LIST>
<PHRASE>fly to</PHRASE>
<PHRASE>drive to</PHRASE>
<PHRASE>take train to</PHRASE>
</LIST>
<LIST>
<PHRASE>Seattle</PHRASE>
<PHRASE>New York</PHRASE>
<PHRASE>Washington DC</PHRASE>
</LIST>
</RULE>
*/
SPSTATEHANDLE hStateTravel_Second;
// create a new transition which starts at the root state and ends at a second state
hr = pGrammarBuilder->CreateNewState(hStateTravel, &hStateTravel_Second);
// attach the first part of the phrase to to first transition
hr = pGrammarBuilder->AddWordTransition(hStateTravel, hStateTravel_Second, L"fly to", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, hStateTravel_Second, L"drive to", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel, hStateTravel_Second, L"take train to", L" ", SPWT_LEXICAL, 1, NULL);
// attach the second and final part of the phrase to the last transition (ending with the NULL state)
hr = pGrammarBuilder->AddWordTransition(hStateTravel_Second, NULL, L"Seattle", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel_Second, NULL, L"New York", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateTravel_Second, NULL, L"Washington DC", L" ", SPWT_LEXICAL, 1, NULL);
}
{ // Approach 3: using sub rules
// This approach let you structure the grammars and is useful when building large grammars,
// since it allows for reusable component rules (see also the XML Grammar tag, RULEREF).
// Note that forward-declarations are allowed, since the grammar validation is not performed
// until the XML is compiled or the GrammarBuilder instance is 'Commit'ted.
// The main difference between Approach 2 and Approach 3 is the use of component rules, which
// are combined into one top-level rule. This facilitates the reuse of the component rules
// in other rules (e.g. create a second rule called "Geography" which combines the phrase
// "where is" with the "Dest" rule, allowing the user to say "where is New York", without
// requiring the grammar author/designer to place the same phrase text in multiple places
// of the grammar leading to grammar maintenance problems.
/* XML Approximation:
<RULE NAME="Travel" TOPLEVEL="ACTIVE">
<RULEREF NAME="Method"/>
<RULEREF NAME="Dest"/>
</RULE>
<RULE NAME="Method">
<LIST>
<PHRASE>fly to</PHRASE>
<PHRASE>drive to</PHRASE>
<PHRASE>take train to</PHRASE>
</LIST>
</RULE>
<RULE NAME="Dest" DYNAMIC="TRUE">
<LIST>
<PHRASE>Seattle</PHRASE>
<PHRASE>New York</PHRASE>
<PHRASE>Washington DC</PHRASE>
</LIST>
</RULE>
</RULE>
*/
SPSTATEHANDLE hStateMethod;
SPSTATEHANDLE hStateDest;
// Note the two new rules ("Method" & "Dest") are NOT marked Top-level, since they are
// reused by other top-level rules, and are not by themselves recognizable phrases.
hr = pGrammarBuilder->GetRule(L"Method", 0, 0, TRUE, &hStateMethod);
// Marking the "Dest" rules as Dynamic allows the programmatic grammar author to
// update only the "Dest" rule after the initial ::Commit (e.g. to add more travel
// destinations depending on user history, preferences, or geographic data).
hr = pGrammarBuilder->GetRule(L"Dest", 0, SPRAF_Dynamic, TRUE, &hStateDest);
SPSTATEHANDLE hStateTravel_Second;
// Create an interim state (same as Approach 2)...
hr = pGrammarBuilder->CreateNewState(hStateTravel, &hStateTravel_Second);
// ... then attach rules to the transitions from Root->Interim and Interim->NULL state
hr = pGrammarBuilder->AddRuleTransition(hStateTravel, hStateTravel_Second, hStateMethod, 1, NULL);
hr = pGrammarBuilder->AddRuleTransition(hStateTravel_Second, NULL, hStateDest, 1, NULL);
// Add the set of sibling transitions for travel "method"
hr = pGrammarBuilder->AddWordTransition(hStateMethod, NULL, L"fly to", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateMethod, NULL, L"drive to", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateMethod, NULL, L"take train to", L" ", SPWT_LEXICAL, 1, NULL);
// Add the set of sibling transitions for travel "destinations"
hr = pGrammarBuilder->AddWordTransition(hStateDest, NULL, L"Seattle", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateDest, NULL, L"New York", L" ", SPWT_LEXICAL, 1, NULL);
hr = pGrammarBuilder->AddWordTransition(hStateDest, NULL, L"Washington DC", L" ", SPWT_LEXICAL, 1, NULL);
}
// Must Commit before the grammar changes before using the grammar.
// Note: grammar changes are only given to the engine at synchronize points (see ISpSREngineSite::Synchronize)
hr = pGrammarBuilder->Commit(0);
You are reading help file online using chmlib.com
|