From 3d0c691694ddcf00a5bfc347626d38625f057dee Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 3 May 2015 17:17:25 +0200 Subject: SCI: Handle pronouns in parser When parsing a sentence, its type 0x142 word (presumably the object) is now stored. Any pronouns (type 0x080) are then automatically replaced by this stored word. --- engines/sci/engine/kparse.cpp | 3 ++ engines/sci/parser/vocabulary.cpp | 77 +++++++++++++++++++++++++++++++++++++++ engines/sci/parser/vocabulary.h | 12 ++++++ 3 files changed, 92 insertions(+) (limited to 'engines/sci') diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index aa89b963cc..f85f33e3e8 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -117,6 +117,8 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { } #endif + voc->replacePronouns(words); + int syntax_fail = voc->parseGNF(words); if (syntax_fail) { @@ -130,6 +132,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { } else { voc->parserIsValid = true; + voc->storePronounReference(); writeSelectorValue(segMan, event, SELECTOR(claimed), 0); #ifdef DEBUG_PARSER diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index 000b037b44..828a57abeb 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -74,6 +74,8 @@ Vocabulary::Vocabulary(ResourceManager *resMan, bool foreign) : _resMan(resMan), parser_event = NULL_REG; parserIsValid = false; + + _pronounReference = 0x1000; // Non-existent word } Vocabulary::~Vocabulary() { @@ -738,4 +740,79 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c return oldPos; } + +// FIXME: Duplicated from said.cpp +static int node_major(ParseTreeNode* node) { + assert(node->type == kParseTreeBranchNode); + assert(node->left->type == kParseTreeLeafNode); + return node->left->value; +} +static bool node_is_terminal(ParseTreeNode* node) { + return (node->right->right && + node->right->right->type != kParseTreeBranchNode); +} +static int node_terminal_value(ParseTreeNode* node) { + assert(node_is_terminal(node)); + return node->right->right->value; +} + +static ParseTreeNode* scanForMajor(ParseTreeNode *tree, int major) { + assert(tree); + + if (node_is_terminal(tree)) { + if (node_major(tree) == major) + return tree; + else + return 0; + } + + ParseTreeNode* ptr = tree->right; + + // Scan children + while (ptr->right) { + ptr = ptr->right; + + if (node_major(ptr->left) == major) + return ptr->left; + } + + if (major == 0x141) + return 0; + + // If not found, go into a 0x141 and try again + tree = scanForMajor(tree, 0x141); + if (!tree) + return 0; + return scanForMajor(tree, major); +} + +bool Vocabulary::storePronounReference() { + assert(parserIsValid); + + ParseTreeNode *ptr = scanForMajor(_parserNodes, 0x142); // 0x142 = object? + + while (ptr && !node_is_terminal(ptr)) + ptr = scanForMajor(ptr, 0x141); + + if (!ptr) + return false; + + _pronounReference = node_terminal_value(ptr); + + debugC(kDebugLevelParser, "Stored pronoun reference: %x", _pronounReference); + return true; +} + +void Vocabulary::replacePronouns(ResultWordListList &words) { + if (_pronounReference == 0x1000) + return; + + for (ResultWordListList::iterator i = words.begin(); i != words.end(); ++i) + for (ResultWordList::iterator j = i->begin(); j != i->end(); ++j) + if (j->_class & (VOCAB_CLASS_PRONOUN << 4)) { + j->_class = VOCAB_CLASS_NOUN << 4; + j->_group = _pronounReference; + } +} + } // End of namespace Sci diff --git a/engines/sci/parser/vocabulary.h b/engines/sci/parser/vocabulary.h index 09499946cb..f4adee6e55 100644 --- a/engines/sci/parser/vocabulary.h +++ b/engines/sci/parser/vocabulary.h @@ -232,6 +232,16 @@ public: */ int parseGNF(const ResultWordListList &words, bool verbose = false); + /** + * Find and store reference for future pronouns + */ + bool storePronounReference(); + + /** + * Replace pronouns by stored reference + */ + void replacePronouns(ResultWordListList &words); + /** * Constructs the Greibach Normal Form of the grammar supplied in 'branches'. * @param verbose Set to true for debugging. If true, the list is @@ -360,6 +370,8 @@ private: SynonymList _synonyms; /**< The list of synonyms */ Common::Array > _altInputs; + int _pronounReference; + public: // Accessed by said() ParseTreeNode _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */ -- cgit v1.2.3