Skip to content

Commit

Permalink
SCI: Handle pronouns in parser
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
wjp committed May 3, 2015
1 parent 30b5497 commit 3d0c691
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
3 changes: 3 additions & 0 deletions engines/sci/engine/kparse.cpp
Expand Up @@ -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) {
Expand All @@ -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
Expand Down
77 changes: 77 additions & 0 deletions engines/sci/parser/vocabulary.cpp
Expand Up @@ -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() {
Expand Down Expand Up @@ -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
12 changes: 12 additions & 0 deletions engines/sci/parser/vocabulary.h
Expand Up @@ -232,6 +232,16 @@ class Vocabulary {
*/
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
Expand Down Expand Up @@ -360,6 +370,8 @@ class Vocabulary {
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 */
Expand Down

0 comments on commit 3d0c691

Please sign in to comment.