diff options
Diffstat (limited to 'engines/sci/parser')
-rw-r--r-- | engines/sci/parser/vocabulary.cpp | 77 | ||||
-rw-r--r-- | engines/sci/parser/vocabulary.h | 12 |
2 files changed, 89 insertions, 0 deletions
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 @@ -233,6 +233,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 * freed before the function ends @@ -360,6 +370,8 @@ private: SynonymList _synonyms; /**< The list of synonyms */ Common::Array<Common::List<AltInput> > _altInputs; + int _pronounReference; + public: // Accessed by said() ParseTreeNode _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */ |