📄 answerparser.cpp
字号:
// This sets all of the application.lastresult$ array when <instance> contains // a complex result. // bool NLSMLSetVars(AnswerTranslator & translator, SimpleLogger & log, int nbest, const XMLCh * confidence, const XMLCh * utterance, const XMLCh * mode, const DOMNode * interp) { std::basic_ostringstream<VXIchar> out; out << L"application.lastresult$[" << nbest << L"]"; translator.EvaluateExpression(out.str() + L" = new Object();"); // Set everything but interpretation. NLSMLSetSomeVars(out.str(), translator, confidence, utterance, mode); // Set 'interpretation'. vxistring path = out.str() + L".interpretation"; return NLSMLSetInterp(translator, log, path, interp); } // This function set up lastresult$ n best // static int SetUpNBestList(int *nbest, bool *isAmbigous, SimpleLogger & log, AnswerTranslator & translator, AnswerHolder & ans) { // if there is an instance of DOMElement type // setting these instance int index = 0; if( ans.instanceStrList.empty() ) { AnswerHolder::DOMLIST::iterator pos; for(pos = ans.instanceDomList.begin(); pos != ans.instanceDomList.end(); ++pos, ++index) { *nbest += index; if (index > 0) *isAmbigous = true; if (log.IsLogging(2)) { log.StartDiagnostic(2) << L"SetUpNBestList(" << *nbest << L", " << XMLChToVXIchar(ans.grammarid).c_str() << L")"; log.EndDiagnostic(); } if (!NLSMLSetVars(translator, log, *nbest, ans.confidence, ans.utterance.c_str(), ans.inputmode, (*pos))) { log.LogDiagnostic(0, L"AnswerParser: <instance> element " L"processing failed"); return -1; } } } else { // Use the input text(utterance) as instance AnswerHolder::STRLIST::iterator pos; for(pos = ans.instanceStrList.begin(); pos != ans.instanceStrList.end(); ++pos, ++index) { *nbest += index; if (index > 0) *isAmbigous = true; if (log.IsLogging(2)) { log.StartDiagnostic(2) << L"SetUpNBestList(" << *nbest << L", " << XMLChToVXIchar(ans.grammarid).c_str() << L")"; log.EndDiagnostic(); } NLSMLSetVars(translator, *nbest, ans.confidence, ans.utterance.c_str(), ans.inputmode, (*pos).c_str()); } } ++(*nbest); return 0; } // This function converts an NLSML result into ECMAScript. // int AnswerParser::ProcessNLSML(SimpleLogger & log, AnswerTranslator & translator, GrammarManager & gm, int maxnbest, vxistring & bestmatch) { DOMNode * doc = nlsmlParser->getDocument(); if (doc == NULL || !doc->hasChildNodes()) { log.LogDiagnostic(0, L"AnswerParser::ProcessNLSML - " L"Document parse failed"); return -1; } // (1) <result> element DOMElement * result = NULL; DOMNode * temp = NULL; for (temp = doc->getFirstChild(); temp != NULL; temp = temp->getNextSibling()) { switch (temp->getNodeType()) { case DOMNode::ELEMENT_NODE: if (result == NULL) result = reinterpret_cast<DOMElement *>(temp); else { log.LogDiagnostic(0,L"AnswerParser: document must have a single root"); return -1; } break; case DOMNode::TEXT_NODE: log.LogDiagnostic(0, L"AnswerParser: PCDATA not allowed after <xml>"); return -1; default: continue; } } if (result == NULL || !Compare(result->getNodeName(), NODE_RESULT)) { log.LogDiagnostic(0, L"AnswerParser: document must have a single " L"root named 'result'"); return -1; } const XMLCh * resultGrammar = result->getAttribute(ATTR_GRAMMAR); // (2) <interpretation> elements int nbest = -1; ANSWERHOLDERMAP answerMap; for (DOMNode * temp2 = result->getFirstChild(); temp2 != NULL; temp2 = temp2->getNextSibling()) { switch (temp2->getNodeType()) { case DOMNode::ELEMENT_NODE: break; case DOMNode::TEXT_NODE: // check for white space if (IsAllWhiteSpace(temp2->getNodeValue())) continue; log.LogDiagnostic(0, L"AnswerParser: PCDATA not allowed after <result>"); return -1; default: continue; } DOMElement * interpretation = reinterpret_cast<DOMElement *>(temp2); // (2.1) Is this an interpretation element? if (!Compare(interpretation->getNodeName(), NODE_INTERPRETATION)) { log.LogDiagnostic(0, L"AnswerParser: only <interpretation> elements may " L"follow <result>"); return -1; } // (2.2) Get the grammar attribute. const XMLCh * grammar = interpretation->getAttribute(ATTR_GRAMMAR); if (grammar == NULL || grammar[0] == 0) grammar = resultGrammar; // (2.3) Get the confidence attribute. const XMLCh * interpretationConfidence = interpretation->getAttribute(ATTR_CONFIDENCE); // (3) <input> element. // (3.1) Find the <input> element. There can be only one. DOMElement * input = NULL; for (temp = interpretation->getFirstChild(); temp != NULL; temp = temp->getNextSibling()) { switch (temp->getNodeType()) { case DOMNode::TEXT_NODE: // check for white space if( IsAllWhiteSpace(temp->getNodeValue())) continue; log.LogDiagnostic(0, L"AnswerParser: PCDATA not allowed after " L"<interpretation>"); return -1; case DOMNode::ELEMENT_NODE: if (Compare(temp->getNodeName(), NODE_INSTANCE)) continue; if (!Compare(temp->getNodeName(), NODE_INPUT)) { log.LogDiagnostic(0, L"AnswerParser: Only <input> and <instance> " L"elements are allowed in an <interpretation>"); return -1; } if (input != NULL) { log.LogDiagnostic(0, L"AnswerParser: Only one <input> element is " L"allowed in an <interpretation>"); return -1; } input = reinterpret_cast<DOMElement *>(temp); break; default: continue; } } // (3.2) Look at the data inside of <input>. Is this an event? xmlcharstring inputText; for (temp = input->getFirstChild(); temp != NULL; temp = temp->getNextSibling()) { short type = temp->getNodeType(); switch (type) { case DOMNode::CDATA_SECTION_NODE: case DOMNode::TEXT_NODE: inputText += temp->getNodeValue(); break; case DOMNode::ELEMENT_NODE: // NOTE: The nbest count here is one less than the array value. The // value is not incremented until the <instance> element is // processed. Thus, the checks are against -1 NOT 0. // if (Compare(temp->getNodeName(), NODE_NOINPUT)) { if (nbest == -1) return 1; return 0; // Ignore this and subsequent interpretations. } if (Compare(temp->getNodeName(), NODE_NOMATCH)) { if (nbest == -1) return 2; return 0; // Ignore this and subsequent interpretations. } log.LogDiagnostic(0, L"AnswerParser: Only <noinput> and <nomatch> " L"elements or PCDATA is allowed in an <input>"); return -1; default: continue; } } if (inputText.empty()) { log.LogDiagnostic(0, L"AnswerParser: <input> element may not be empty"); return -1; } if (grammar == NULL) { log.LogDiagnostic(0, L"AnswerParser: the grammar attribute must be " L"defined in either <result> or <interpretation>"); return -1; } // (3.3) Get the confidence. const XMLCh * confidence = input->getAttribute(ATTR_CONFIDENCE); if (confidence == NULL || confidence[0] == 0) confidence = interpretationConfidence; if (confidence == NULL || confidence[0] == 0) confidence = DEFAULT_CONFIDENCE; // (3.3.1) convert confidence score to float VXIflt32 vConfidence = 0.5; std::basic_stringstream<VXIchar> confStream(XMLChToVXIchar(confidence).c_str()); confStream >> vConfidence; // (3.4) Get the input mode. const XMLCh * mode = input->getAttribute(ATTR_MODE); if (mode == NULL || mode[0] == 0) mode = DEFAULT_MODE; // (3.5) Determine precedence of this grammar // (3.5.1) retrieve the grammar for this interpretation // create the answer info. AnswerHolder newanswer(inputText.c_str(), mode, grammar, confidence, gm); // find this answer grammar VXMLElement answerElement; if (!gm.FindMatchedElement(XMLChToVXIchar(newanswer.grammarid).c_str(), answerElement, newanswer.grammarInfo) || answerElement == 0) { // No match found! log.LogError(433); return 2; } // find the current confidence in answer map ANSWERHOLDERMAP::iterator mit = answerMap.find(vConfidence); AnswerHolder *newAnswerPtr = NULL; // insert answer with confidence sorted in order if( mit == answerMap.end()) { // this score is first one in this list, create it ANSWERHOLDERVECTOR newlist; newlist.push_back(newanswer); answerMap[vConfidence] = newlist; newAnswerPtr = &(answerMap[vConfidence].back()); } else { (*mit).second.push_back(newanswer); newAnswerPtr = &((*mit).second.back()); } // (4) Look at each <instance>. // // At this point, we have DOMStrings with the 'grammar' name, 'confidence' // score, input 'mode', and 'inputText'. We have already verified that // only <input> and <instance> nodes exist at this level. bool hasInstance = false; for (DOMNode * temp3 = interpretation->getFirstChild(); temp3 != NULL; temp3 = temp3->getNextSibling()) { if (temp3->getNodeType() != DOMNode::ELEMENT_NODE) continue; if (!Compare(temp3->getNodeName(), NODE_INSTANCE)) continue; hasInstance = true; ++nbest; // (4.2) Process the instance // (4.2.1) Does the instance have data? DOMElement * instance = reinterpret_cast<DOMElement *>(temp3); bool hasInstanceData = false; for (DOMNode * temp4 = instance->getFirstChild(); temp4 != NULL && !hasInstanceData; temp4 = temp4->getNextSibling()) { short type = temp4->getNodeType(); switch (type) { case DOMNode::CDATA_SECTION_NODE: case DOMNode::TEXT_NODE: case DOMNode::ELEMENT_NODE: newAnswerPtr->SetInstance(instance); hasInstanceData = true; break; default: continue; } } // (4.2.2) If the contents were empty - use input text as interpretation. if (!hasInstanceData) { newAnswerPtr->SetInstance(inputText); } } // (4.2.3) If <instance> did not appear - use input text as interpretation. if (!hasInstance) { newAnswerPtr->SetInstance(inputText); } } // Setting up the lastresult$ structure ANSWERHOLDERMAP::iterator it = answerMap.begin(); if( it == answerMap.end() ) { // something is wrong, return error log.LogDiagnostic(0, L"AnswerParser: the result structure is corrupted"); return -1; } else { // go through the vector and sort its precedence using selection sort for( it = answerMap.begin(); it != answerMap.end(); ++it ) { ANSWERHOLDERVECTOR & a = (*it).second; int vsize = a.size(); if( vsize <= 1 ) continue; for(int i = 0; i < vsize; i++ ) { int min = i; for( int j = i+1; j < vsize; j++) if (a[j] < a[min]) min = j; AnswerHolder t = a[min]; a[min] = a[i]; a[i] = t; } } // go through the vector and setup lastresult structure int nbestIndex = 0; bool done = false, isAmbigous = false; for( it = answerMap.begin(); !done && it != answerMap.end(); ++it ) { ANSWERHOLDERVECTOR & a = (*it).second; int vsize = a.size(); for( int i = 0; !done && i < vsize; i++) { if( nbestIndex == 0 ) { // create the result structure at first element translator.EvaluateExpression(L"application.lastresult$ = " L"new Array();"); bestmatch = XMLChToVXIchar(a[i].grammarid).c_str(); } if( SetUpNBestList(&nbestIndex, &isAmbigous, log, translator, a[i]) < 0 ) return -1; // check for maxnbest, if there is ambiguity, ignore maxnbest // and setup appropriate nbest list if( isAmbigous && nbestIndex > maxnbest-1 ) done = true; else if( nbestIndex > maxnbest -1 ) done = true; } } } return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -