aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorFilippos Karapetis2009-09-30 12:17:38 +0000
committerFilippos Karapetis2009-09-30 12:17:38 +0000
commitfd21bb2611b4260a1243ab14c9a0797fb9ba3617 (patch)
tree77974c051b66ba20f2cd0a640cf9e9400af7cc0f /engines/sci
parentab403f484501f1c3f9695a7e4be7a5b8fea246b5 (diff)
downloadscummvm-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
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp79
-rw-r--r--engines/sci/engine/game.cpp11
-rw-r--r--engines/sci/engine/grammar.cpp22
-rw-r--r--engines/sci/engine/kstring.cpp42
-rw-r--r--engines/sci/engine/said.cpp12
-rw-r--r--engines/sci/engine/said.y10
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/engine/state.cpp8
-rw-r--r--engines/sci/engine/state.h17
-rw-r--r--engines/sci/sci.cpp2
-rw-r--r--engines/sci/vocabulary.cpp86
-rw-r--r--engines/sci/vocabulary.h52
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();