📄 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;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -