diff options
author | Filippos Karapetis | 2009-09-30 12:17:38 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-09-30 12:17:38 +0000 |
commit | fd21bb2611b4260a1243ab14c9a0797fb9ba3617 (patch) | |
tree | 77974c051b66ba20f2cd0a640cf9e9400af7cc0f | |
parent | ab403f484501f1c3f9695a7e4be7a5b8fea246b5 (diff) | |
download | scummvm-rg350-fd21bb2611b4260a1243ab14c9a0797fb9ba3617.tar.gz scummvm-rg350-fd21bb2611b4260a1243ab14c9a0797fb9ba3617.tar.bz2 scummvm-rg350-fd21bb2611b4260a1243ab14c9a0797fb9ba3617.zip |
- Moved the list of synonyms and parser nodes inside the vocabulary class
- Added a convenience member inside the EngineState struct to access the instance of the Vocabulary class
svn-id: r44481
-rw-r--r-- | engines/sci/console.cpp | 79 | ||||
-rw-r--r-- | engines/sci/engine/game.cpp | 11 | ||||
-rw-r--r-- | engines/sci/engine/grammar.cpp | 22 | ||||
-rw-r--r-- | engines/sci/engine/kstring.cpp | 42 | ||||
-rw-r--r-- | engines/sci/engine/said.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/said.y | 10 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 8 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 17 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 2 | ||||
-rw-r--r-- | engines/sci/vocabulary.cpp | 86 | ||||
-rw-r--r-- | engines/sci/vocabulary.h | 52 |
12 files changed, 180 insertions, 163 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e50139b3bc..032264bcaf 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -464,66 +464,6 @@ bool Console::cmdParserWords(int argc, const char **argv) { return true; } -enum { - kParseEndOfInput = 0, - kParseOpeningParenthesis = 1, - kParseClosingParenthesis = 2, - kParseNil = 3, - kParseNumber = 4 -}; - -int parseNodes(EngineState *s, int *i, int *pos, int type, int nr, int argc, const char **argv) { - int nextToken = 0, nextValue = 0, newPos = 0, oldPos = 0; - Console *con = ((SciEngine *)g_engine)->getSciDebugger(); - - if (type == kParseNil) - return 0; - - if (type == kParseNumber) { - s->parser_nodes[*pos += 1].type = kParseTreeLeafNode; - s->parser_nodes[*pos].content.value = nr; - return *pos; - } - if (type == kParseEndOfInput) { - con->DebugPrintf("Unbalanced parentheses\n"); - return -1; - } - if (type == kParseClosingParenthesis) { - con->DebugPrintf("Syntax error at token %d\n", *i); - return -1; - } - - s->parser_nodes[oldPos = ++(*pos)].type = kParseTreeBranchNode; - - for (int j = 0; j <= 1; j++) { - if (*i == argc) { - nextToken = kParseEndOfInput; - } else { - const char *token = argv[(*i)++]; - - if (!strcmp(token, "(")) { - nextToken = kParseOpeningParenthesis; - } else if (!strcmp(token, ")")) { - nextToken = kParseClosingParenthesis; - } else if (!strcmp(token, "nil")) { - nextToken = kParseNil; - } else { - nextValue = strtol(token, NULL, 0); - nextToken = kParseNumber; - } - } - - if ((newPos = s->parser_nodes[oldPos].content.branches[j] = parseNodes(s, i, pos, nextToken, nextValue, argc, argv)) == -1) - return -1; - } - - const char *token = argv[(*i)++]; - if (strcmp(token, ")")) - con->DebugPrintf("Expected ')' at token %d\n", *i); - - return oldPos; -} - bool Console::cmdSetParseNodes(int argc, const char **argv) { if (argc < 2) { DebugPrintf("Sets the contents of all parse nodes.\n"); @@ -549,10 +489,10 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { nextToken = kParseNumber; } - if (parseNodes(_vm->_gamestate, &i, &pos, nextToken, nextValue, argc, argv) == -1) + if (_vm->getVocabulary()->parseNodes(&i, &pos, nextToken, nextValue, argc, argv) == -1) return 1; - vocab_dump_parse_tree("debug-parse-tree", _vm->_gamestate->parser_nodes); + _vm->getVocabulary()->dumpParseTree(); return true; } @@ -971,20 +911,20 @@ bool Console::cmdParse(int argc, const char **argv) { if (res && !words.empty()) { int syntax_fail = 0; - vocab_synonymize_tokens(words, _vm->_gamestate->_synonyms); + _vm->getVocabulary()->synonymizeTokens(words); DebugPrintf("Parsed to the following blocks:\n"); for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i) DebugPrintf(" Type[%04x] Group[%04x]\n", i->_class, i->_group); - if (_vm->getVocabulary()->parseGNF(_vm->_gamestate->parser_nodes, words, true)) + if (_vm->getVocabulary()->parseGNF(words, true)) syntax_fail = 1; // Building a tree failed if (syntax_fail) DebugPrintf("Building a tree failed.\n"); else - vocab_dump_parse_tree("debug-parse-tree", _vm->_gamestate->parser_nodes); + _vm->getVocabulary()->dumpParseTree(); } else { DebugPrintf("Unknown word: '%s'\n", error); @@ -1004,14 +944,7 @@ bool Console::cmdParserNodes(int argc, const char **argv) { int end = MIN<int>(atoi(argv[1]), VOCAB_TREE_NODES); - for (int i = 0; i < end; i++) { - DebugPrintf(" Node %03x: ", i); - if (_vm->_gamestate->parser_nodes[i].type == kParseTreeLeafNode) - DebugPrintf("Leaf: %04x\n", _vm->_gamestate->parser_nodes[i].content.value); - else - DebugPrintf("Branch: ->%04x, ->%04x\n", _vm->_gamestate->parser_nodes[i].content.branches[0], - _vm->_gamestate->parser_nodes[i].content.branches[1]); - } + _vm->getVocabulary()->printParserNodes(end); return true; } diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 6c5680f9fd..23806f1db0 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -413,11 +413,8 @@ int game_init(EngineState *s) { return 1; } - s->parser_valid = 0; // Invalidate parser + s->parserIsValid = false; // Invalidate parser s->parser_event = NULL_REG; // Invalidate parser event - - s->_synonyms.clear(); // No synonyms - if (s->gfx_state && _reset_graphics_input(s)) return 1; @@ -446,10 +443,6 @@ int game_init(EngineState *s) { debug(2, " \"%s\" at %04x:%04x", s->_gameName.c_str(), PRINT_REG(s->game_obj)); - // Mark parse tree as unused - s->parser_nodes[0].type = kParseTreeLeafNode; - s->parser_nodes[0].content.value = 0; - s->_menubar = new Menubar(); // Create menu bar if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) @@ -474,8 +467,6 @@ int game_exit(EngineState *s) { delete s->segMan; s->segMan = 0; - s->_synonyms.clear(); - debug(2, "Freeing miscellaneous data..."); // TODO Free parser segment here diff --git a/engines/sci/engine/grammar.cpp b/engines/sci/engine/grammar.cpp index 26f540a373..89d550dafc 100644 --- a/engines/sci/engine/grammar.cpp +++ b/engines/sci/engine/grammar.cpp @@ -476,7 +476,7 @@ static int _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, parse_r return rulepos; } -int Vocabulary::parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, bool verbose) { +int Vocabulary::parseGNF(const ResultWordList &words, bool verbose) { Console *con = ((SciEngine *)g_engine)->getSciDebugger(); // Get the start rules: parse_rule_list_t *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]); @@ -554,22 +554,22 @@ int Vocabulary::parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, { int temp, pos; - nodes[0].type = kParseTreeBranchNode; - nodes[0].content.branches[0] = 1; - nodes[0].content.branches[1] = 2; + _parserNodes[0].type = kParseTreeBranchNode; + _parserNodes[0].content.branches[0] = 1; + _parserNodes[0].content.branches[1] = 2; - nodes[1].type = kParseTreeLeafNode; - nodes[1].content.value = 0x141; + _parserNodes[1].type = kParseTreeLeafNode; + _parserNodes[1].content.value = 0x141; - nodes[2].type = kParseTreeBranchNode; - nodes[2].content.branches[0] = 0; - nodes[2].content.branches[1] = 0; + _parserNodes[2].type = kParseTreeBranchNode; + _parserNodes[2].content.branches[0] = 0; + _parserNodes[2].content.branches[1] = 0; pos = 2; - temp = _vbpt_append(nodes, &pos, 2, _parserBranches[0].id); + 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(nodes, &pos, results->rule, 0, temp); + _vbpt_write_subexpression(_parserNodes, &pos, results->rule, 0, temp); } freeRuleList(results); diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 81cc2aa707..4980e245ac 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -96,7 +96,7 @@ reg_t kSaid(EngineState *s, int argc, reg_t *argv) { #ifdef DEBUG_PARSER debugC(2, kDebugLevelParser, "Said block:", 0); - ((SciEngine*)g_engine)->getVocabulary()->decipherSaidBlock(said_block); + s->_voc->decipherSaidBlock(said_block); #endif if (s->parser_event.isNull() || (GET_SEL32V(s->parser_event, claimed))) { @@ -134,8 +134,9 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) { List *list; Node *node; int script; + int numSynonyms = 0; - s->_synonyms.clear(); + s->_voc->clearSynonyms(); list = lookup_list(s, GET_SEL32(object, elements)); node = lookup_node(s, list->first); @@ -143,33 +144,31 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) { while (node) { reg_t objpos = node->value; int seg; - int _numSynonyms = 0; script = GET_SEL32V(objpos, number); seg = s->segMan->getScriptSegment(script); if (seg > 0) - _numSynonyms = s->segMan->getScript(seg)->getSynonymsNr(); + numSynonyms = s->segMan->getScript(seg)->getSynonymsNr(); - if (_numSynonyms) { - byte *synonyms; + if (numSynonyms) { + byte *synonyms = s->segMan->getScript(seg)->getSynonyms(); - synonyms = s->segMan->getScript(seg)->getSynonyms(); if (synonyms) { debugC(2, kDebugLevelParser, "Setting %d synonyms for script.%d\n", - _numSynonyms, script); + numSynonyms, script); - if (_numSynonyms > 16384) { + if (numSynonyms > 16384) { error("Segtable corruption: script.%03d has %d synonyms", - script, _numSynonyms); + script, numSynonyms); /* We used to reset the corrupted value here. I really don't think it's appropriate. * Lars */ } else - for (int i = 0; i < _numSynonyms; i++) { + for (int i = 0; i < numSynonyms; i++) { synonym_t tmp; tmp.replaceant = (int16)READ_LE_UINT16(synonyms + i * 4); tmp.replacement = (int16)READ_LE_UINT16(synonyms + i * 4 + 2); - s->_synonyms.push_back(tmp); + s->_voc->addSynonym(tmp); } } else warning("Synonyms of script.%03d were requested, but script is not available", script); @@ -179,7 +178,7 @@ reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) { node = lookup_node(s, node->succ); } - debugC(2, kDebugLevelParser, "A total of %d synonyms are active now.\n", s->_synonyms.size()); + debugC(2, kDebugLevelParser, "A total of %d synonyms are active now.\n", numSynonyms); return s->r_acc; } @@ -193,18 +192,15 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { char *error; ResultWordList words; reg_t event = argv[1]; - Vocabulary *voc = ((SciEngine*)g_engine)->getVocabulary(); + Vocabulary *voc = s->_voc; s->parser_event = event; bool res = voc->tokenizeString(words, string.c_str(), &error); - s->parser_valid = 0; /* not valid */ + s->parserIsValid = false; /* not valid */ if (res && !words.empty()) { - - int syntax_fail = 0; - - vocab_synonymize_tokens(words, s->_synonyms); + s->_voc->synonymizeTokens(words); s->r_acc = make_reg(0, 1); @@ -215,11 +211,9 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, " Type[%04x] Group[%04x]\n", i->_class, i->_group); #endif - if (voc->parseGNF(s->parser_nodes, words)) - syntax_fail = 1; /* Building a tree failed */ + int syntax_fail = voc->parseGNF(words); if (syntax_fail) { - s->r_acc = make_reg(0, 1); PUT_SEL32V(event, claimed, 1); @@ -229,11 +223,11 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, "Tree building failed\n"); } else { - s->parser_valid = 1; + s->parserIsValid = true; PUT_SEL32V(event, claimed, 0); #ifdef DEBUG_PARSER - vocab_dump_parse_tree("Parse-tree", s->parser_nodes); + s->_voc->dumpParseTree(); #endif } diff --git a/engines/sci/engine/said.cpp b/engines/sci/engine/said.cpp index b1d174b30f..32bd1fcf8d 100644 --- a/engines/sci/engine/said.cpp +++ b/engines/sci/engine/said.cpp @@ -2006,7 +2006,7 @@ static said_spec_t said_top_branch(tree_t first) { return 0; } -static int said_parse_spec(EngineState *s, byte *spec) { +static int said_parse_spec(byte *spec) { int nextitem; said_parse_error = NULL; @@ -2441,15 +2441,15 @@ static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *sai /**** Main code ****/ /*******************/ -int said(EngineState *s, byte *spec, int verbose) { +int said(EngineState *s, byte *spec, bool verbose) { int retval; - parse_tree_node_t *parse_tree_ptr = s->parser_nodes; + parse_tree_node_t *parse_tree_ptr = s->_voc->_parserNodes; - if (s->parser_valid) { - if (said_parse_spec(s, spec)) { + if (s->parserIsValid) { + if (said_parse_spec(spec)) { printf("Offending spec was: "); - ((SciEngine*)g_engine)->getVocabulary()->decipherSaidBlock(spec); + s->_voc->decipherSaidBlock(spec); return SAID_NO_MATCH; } diff --git a/engines/sci/engine/said.y b/engines/sci/engine/said.y index e7c225b3e6..02350e0d60 100644 --- a/engines/sci/engine/said.y +++ b/engines/sci/engine/said.y @@ -362,7 +362,7 @@ static said_spec_t said_top_branch(tree_t first) { return 0; } -static int said_parse_spec(EngineState *s, byte *spec) { +static int said_parse_spec(byte *spec) { int nextitem; said_parse_error = NULL; @@ -797,15 +797,15 @@ static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *sai /**** Main code ****/ /*******************/ -int said(EngineState *s, byte *spec, int verbose) { +int said(EngineState *s, byte *spec, bool verbose) { int retval; - parse_tree_node_t *parse_tree_ptr = s->parser_nodes; + parse_tree_node_t *parse_tree_ptr = s->_voc->_parser_nodes; - if (s->parser_valid) { + if (s->parserIsValid) { if (said_parse_spec(s, spec)) { warning("Offending spec was: "); - ((SciEngine*)g_engine)->getVocabulary()->decypherSaidBlock(spec); + s->_voc->decipherSaidBlock(spec); return SAID_NO_MATCH; } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index cf54a61ebd..ae9db4cb67 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -736,7 +736,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. - retval = new EngineState(s->resMan, s->_kernel, s->_flags); + retval = new EngineState(s->resMan, s->_kernel, s->_voc, s->_flags); // Copy some old data retval->gfx_state = s->gfx_state; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index dc66c033dd..10d2a957a8 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -30,8 +30,8 @@ namespace Sci { -EngineState::EngineState(ResourceManager *res, Kernel *kernel, uint32 flags) -: resMan(res), _kernel(kernel), _flags(flags), _dirseeker(this) { +EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, uint32 flags) +: resMan(res), _kernel(kernel), _voc(voc), _flags(flags), _dirseeker(this) { gfx_state = 0; old_screen = 0; @@ -100,9 +100,7 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, uint32 flags) sys_strings = 0; string_frag_segment = 0; - memset(parser_nodes, 0, sizeof(parser_nodes)); - - parser_valid = 0; + parserIsValid = false; game_obj = NULL_REG; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 9aa19b3dd4..cf7e1635d5 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -158,7 +158,7 @@ private: struct EngineState : public Common::Serializable { public: - EngineState(ResourceManager *res, Kernel *kernel, uint32 flags); + EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, uint32 flags); virtual ~EngineState(); virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -167,6 +167,7 @@ public: public: ResourceManager *resMan; /**< The resource manager */ Kernel *_kernel; + Vocabulary *_voc; const uint32 _flags; /**< Specific game flags */ @@ -227,6 +228,11 @@ public: DirSeeker _dirseeker; + /* Parser data: */ + reg_t parser_base; /**< Base address for the parser error reporting mechanism */ + reg_t parser_event; /**< The event passed to Parse() and later used by Said() */ + bool parserIsValid; /**< If something has been correctly parsed */ + /* VM Information */ Common::List<ExecStack> _executionStack; /**< The execution stack */ @@ -245,8 +251,6 @@ public: StackPtr stack_base; /**< Pointer to the least stack element */ StackPtr stack_top; /**< First invalid stack element */ - reg_t parser_base; /**< Base address for the parser error reporting mechanism */ - reg_t parser_event; /**< The event passed to Parse() and later used by Said() */ Script *script_000; /**< script 000, e.g. for globals */ uint16 currentRoomNumber() const; @@ -289,13 +293,6 @@ public: SegmentId string_frag_segment; - /* Parser data: */ - parse_tree_node_t parser_nodes[VOCAB_TREE_NODES]; /**< The parse tree */ - - int parser_valid; /**< If something has been correctly parsed */ - - SynonymList _synonyms; /**< The list of synonyms */ - reg_t game_obj; /**< Pointer to the game object */ SegManager *segMan; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index e185c79fa5..a65351eeb4 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -138,7 +138,7 @@ Common::Error SciEngine::run() { _kernel = new Kernel(_resMan); _vocabulary = new Vocabulary(_resMan); - _gamestate = new EngineState(_resMan, _kernel, flags); + _gamestate = new EngineState(_resMan, _kernel, _vocabulary, flags); if (script_init_engine(_gamestate)) return Common::kUnknownError; diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp index 783941fb11..803c211204 100644 --- a/engines/sci/vocabulary.cpp +++ b/engines/sci/vocabulary.cpp @@ -90,6 +90,13 @@ Vocabulary::Vocabulary(ResourceManager *resMan) : _resMan(resMan) { _parserRules = NULL; _vocabVersion = kVocabularySCI0; + memset(_parserNodes, 0, sizeof(_parserNodes)); + // Mark parse tree as unused + _parserNodes[0].type = kParseTreeLeafNode; + _parserNodes[0].content.value = 0; + + _synonyms.clear(); // No synonyms + debug(2, "Initializing vocabulary"); if (getSciVersion() <= SCI_VERSION_1_EGA && loadParserWords()) { @@ -108,6 +115,7 @@ Vocabulary::~Vocabulary() { _parserWords.clear(); _parserBranches.clear(); freeSuffixes(); + _synonyms.clear(); } bool Vocabulary::loadParserWords() { @@ -543,14 +551,86 @@ void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes) { printf("))\n"); } -void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms) { - if (synonyms.empty()) +void Vocabulary::dumpParseTree() { + //_vocab_recursive_ptree_dump_treelike(nodes, 0, 0); + printf("(setq parse-tree \n'("); + _vocab_recursive_ptree_dump(_parserNodes, 0, 0, 1); + printf("))\n"); +} + +void Vocabulary::synonymizeTokens(ResultWordList &words) { + if (_synonyms.empty()) return; // No synonyms: Nothing to check for (ResultWordList::iterator i = words.begin(); i != words.end(); ++i) - for (SynonymList::const_iterator sync = synonyms.begin(); sync != synonyms.end(); ++sync) + for (SynonymList::const_iterator sync = _synonyms.begin(); sync != _synonyms.end(); ++sync) if (i->_group == sync->replaceant) i->_group = sync->replacement; } +void Vocabulary::printParserNodes(int num) { + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); + + for (int i = 0; i < num; i++) { + con->DebugPrintf(" Node %03x: ", i); + if (_parserNodes[i].type == kParseTreeLeafNode) + con->DebugPrintf("Leaf: %04x\n", _parserNodes[i].content.value); + else + con->DebugPrintf("Branch: ->%04x, ->%04x\n", _parserNodes[i].content.branches[0], + _parserNodes[i].content.branches[1]); + } +} + +int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const char **argv) { + int nextToken = 0, nextValue = 0, newPos = 0, oldPos = 0; + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); + + if (type == kParseNil) + return 0; + + if (type == kParseNumber) { + _parserNodes[*pos += 1].type = kParseTreeLeafNode; + _parserNodes[*pos].content.value = nr; + return *pos; + } + if (type == kParseEndOfInput) { + con->DebugPrintf("Unbalanced parentheses\n"); + return -1; + } + if (type == kParseClosingParenthesis) { + con->DebugPrintf("Syntax error at token %d\n", *i); + return -1; + } + + _parserNodes[oldPos = ++(*pos)].type = kParseTreeBranchNode; + + for (int j = 0; j <= 1; j++) { + if (*i == argc) { + nextToken = kParseEndOfInput; + } else { + const char *token = argv[(*i)++]; + + if (!strcmp(token, "(")) { + nextToken = kParseOpeningParenthesis; + } else if (!strcmp(token, ")")) { + nextToken = kParseClosingParenthesis; + } else if (!strcmp(token, "nil")) { + nextToken = kParseNil; + } else { + nextValue = strtol(token, NULL, 0); + nextToken = kParseNumber; + } + } + + if ((newPos = _parserNodes[oldPos].content.branches[j] = parseNodes(i, pos, nextToken, nextValue, argc, argv)) == -1) + return -1; + } + + const char *token = argv[(*i)++]; + if (strcmp(token, ")")) + con->DebugPrintf("Expected ')' at token %d\n", *i); + + return oldPos; +} + } // End of namespace Sci diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h index 511c8d8223..cc1a991c4c 100644 --- a/engines/sci/vocabulary.h +++ b/engines/sci/vocabulary.h @@ -67,6 +67,14 @@ enum { VOCAB_CLASS_NUMBER = 0x001 }; +enum { + kParseEndOfInput = 0, + kParseOpeningParenthesis = 1, + kParseClosingParenthesis = 2, + kParseNil = 3, + kParseNumber = 4 +}; + #define VOCAB_CLASS_ANYWORD 0xff /* Anywords are ignored by the parser */ @@ -207,17 +215,14 @@ public: bool tokenizeString(ResultWordList &retval, const char *sentence, char **error); /* Builds a parse tree from a list of words, using a set of Greibach Normal Form rules - ** Parameters: (parse_tree_node_t *) nodes: A node list to store the tree in (must have - ** at least VOCAB_TREE_NODES entries) + ** Parameters: ** (const ResultWordList &) words: The words to build the tree from - ** (parse_tree_branch_t *) branche0: The zeroeth original branch of the - ** original CNF parser grammar ** bool verbose: Set to true for debugging ** Returns : 0 on success, 1 if the tree couldn't be built in VOCAB_TREE_NODES nodes ** or if the sentence structure in 'words' is not part of the language ** described by the grammar passed in 'rules'. */ - int parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, bool verbose = false); + int parseGNF(const ResultWordList &words, bool verbose = false); /* Constructs the Greibach Normal Form of the grammar supplied in 'branches' ** bool verbose: Set to true for debugging. @@ -251,6 +256,31 @@ public: uint getParserBranchesSize() const { return _parserBranches.size(); } const parse_tree_branch_t &getParseTreeBranch(int number) const { return _parserBranches[number]; } + /** + * Adds a new synonym to the list + */ + void addSynonym(synonym_t syn) { _synonyms.push_back(syn); } + + /** + * Clears the list of synonyms + */ + void clearSynonyms() { _synonyms.clear(); } + + /** + * Synonymizes a token list + * Parameters: (ResultWordList &) words: The word list to synonymize + */ + void synonymizeTokens(ResultWordList &words); + + void printParserNodes(int num); + + void dumpParseTree(); + + int parseNodes(int *i, int *pos, int type, int nr, int argc, const char **argv); + + // Accessed by said() + parse_tree_node_t _parserNodes[VOCAB_TREE_NODES]; /**< The parse tree */ + private: /** * Loads all words from the main vocabulary. @@ -290,6 +320,7 @@ private: parse_rule_list_t *_parserRules; /**< GNF rules used in the parser algorithm */ Common::Array<parse_tree_branch_t> _parserBranches; WordMap _parserWords; + SynonymList _synonyms; /**< The list of synonyms */ }; /* Prints a parse tree @@ -303,17 +334,10 @@ void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes); /* Builds a parse tree from a spec and compares it to a parse tree ** Parameters: (EngineState *) s: The affected state ** (byte *) spec: Pointer to the spec to build -** (int) verbose: Whether to display the parse tree after building it +** (bool) verbose: Whether to display the parse tree after building it ** Returns : (int) 1 on a match, 0 otherwise */ -int said(EngineState *s, byte *spec, int verbose); - - -/* Synonymizes a token list -** Parameters: (ResultWordList &) words: The word list to synonymize -** (const SynonymList &) synonyms: Synonym list -*/ -void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms); +int said(EngineState *s, byte *spec, bool verbose); int getAllocatedRulesCount(); |