reg_t kParse(EngineState *s, int argc, reg_t *argv) { SegManager *segMan = s->_segMan; reg_t stringpos = argv[0]; Common::String string = s->_segMan->getString(stringpos); char *error; reg_t event = argv[1]; g_sci->checkVocabularySwitch(); Vocabulary *voc = g_sci->getVocabulary(); voc->parser_event = event; reg_t params[2] = { s->_segMan->getParserPtr(), stringpos }; ResultWordListList words; bool res = voc->tokenizeString(words, string.c_str(), &error); voc->parserIsValid = false; /* not valid */ if (res && !words.empty()) { voc->synonymizeTokens(words); s->r_acc = make_reg(0, 1); #ifdef DEBUG_PARSER debugC(kDebugLevelParser, "Parsed to the following blocks:"); for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) { debugCN(2, kDebugLevelParser, " "); for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) { debugCN(2, kDebugLevelParser, "%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); } debugCN(2, kDebugLevelParser, "\n"); } #endif voc->replacePronouns(words); int syntax_fail = voc->parseGNF(words); if (syntax_fail) { s->r_acc = make_reg(0, 1); writeSelectorValue(segMan, event, SELECTOR(claimed), 1); invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), argc, argv, 2, params); /* Issue warning */ debugC(kDebugLevelParser, "Tree building failed"); } else { voc->parserIsValid = true; voc->storePronounReference(); writeSelectorValue(segMan, event, SELECTOR(claimed), 0); #ifdef DEBUG_PARSER voc->dumpParseTree(); #endif } } else { s->r_acc = make_reg(0, 0); writeSelectorValue(segMan, event, SELECTOR(claimed), 1); if (error) { s->_segMan->strcpy(s->_segMan->getParserPtr(), error); debugC(kDebugLevelParser, "Word unknown: %s", error); /* Issue warning: */ invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), argc, argv, 2, params); free(error); return make_reg(0, 1); /* Tell them that it didn't work */ } } return s->r_acc; }
int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { Console *con = g_sci->getSciDebugger(); // Get the start rules: ParseRuleList *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]); ParseRuleList *results = NULL; uint word = 0; const uint words_nr = words.size(); ResultWordListList::const_iterator words_iter; for (words_iter = words.begin(); words_iter != words.end(); ++words_iter, ++word) { ParseRuleList *new_work = NULL; ParseRuleList *reduced_rules = NULL; ParseRuleList *seeker, *subseeker; if (verbose) con->DebugPrintf("Adding word %d...\n", word); seeker = work; while (seeker) { if (seeker->rule->_numSpecials <= (words_nr - word)) { reduced_rules = _vocab_add_rule(reduced_rules, _vsatisfy_rule(seeker->rule, *words_iter)); } seeker = seeker->next; } if (reduced_rules == NULL) { freeRuleList(work); if (verbose) con->DebugPrintf("No results.\n"); return 1; } freeRuleList(work); if (word + 1 < words_nr) { seeker = reduced_rules; while (seeker) { if (seeker->rule->_numSpecials) { int my_id = seeker->rule->_data[seeker->rule->_firstSpecial]; subseeker = _parserRules; while (subseeker) { if (subseeker->rule->_id == my_id) new_work = _vocab_add_rule(new_work, _vinsert(seeker->rule, subseeker->rule)); subseeker = subseeker->next; } } seeker = seeker->next; } freeRuleList(reduced_rules); } else // last word new_work = reduced_rules; work = new_work; if (verbose) con->DebugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work)); if (work == NULL) { if (verbose) con->DebugPrintf("No results.\n"); return 1; } } results = work; if (verbose) { con->DebugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id); results->print(); con->DebugPrintf("\n"); } // now use the first result { int temp, pos; _parserNodes[0].type = kParseTreeBranchNode; _parserNodes[0].left = &_parserNodes[1]; _parserNodes[0].right = &_parserNodes[2]; _parserNodes[1].type = kParseTreeLeafNode; _parserNodes[1].value = 0x141; _parserNodes[1].right = 0; _parserNodes[2].type = kParseTreeBranchNode; _parserNodes[2].left = 0; _parserNodes[2].right = 0; pos = 2; temp = _vbpt_append(_parserNodes, &pos, 2, _parserBranches[0].id); //_vbpt_write_subexpression(nodes, &pos, results[_vocab_rule_list_length(results)].rule, 0, temp); _vbpt_write_subexpression(_parserNodes, &pos, results->rule, 0, temp); } freeRuleList(results); return 0; }