diff options
| -rw-r--r-- | engines/sci/console.cpp | 117 | ||||
| -rw-r--r-- | engines/sci/console.h | 1 | 
2 files changed, 118 insertions, 0 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 0fec80fe1c..d91f257efe 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -93,6 +93,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),  	DCmd_Register("sentence_fragments",	WRAP_METHOD(Console, cmdSentenceFragments));  	DCmd_Register("parse",				WRAP_METHOD(Console, cmdParse));  	DCmd_Register("set_parse_nodes",	WRAP_METHOD(Console, cmdSetParseNodes)); +	DCmd_Register("said",				WRAP_METHOD(Console, cmdSaid));  	// Resources  	DCmd_Register("diskdump",			WRAP_METHOD(Console, cmdDiskDump));  	DCmd_Register("hexdump",			WRAP_METHOD(Console, cmdHexDump)); @@ -306,6 +307,7 @@ bool Console::cmdHelp(int argc, const char **argv) {  	DebugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n");  	DebugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n");  	DebugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n"); +	DebugPrintf(" said - Match a string against a said spec\n");  	DebugPrintf("\n");  	DebugPrintf("Resources:\n");  	DebugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n"); @@ -1210,6 +1212,121 @@ bool Console::cmdParse(int argc, const char **argv) {  	return true;  } +bool Console::cmdSaid(int argc, const char **argv) { +	if (argc < 2) { +		DebugPrintf("Matches a string against a said spec\n"); +		DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); +		DebugPrintf("<string> is a sequence of actual words.\n"); +		DebugPrintf("<said spec> is a sequence of hex tokens.\n"); +		return true; +	} + +	ResultWordList words; +	char *error; +	char string[1000]; +	byte spec[1000]; + +	int p; +	// Construct the string +	strcpy(string, argv[1]); +	for (p = 2; p < argc && strcmp(argv[p],"&") != 0; p++) { +		strcat(string, " "); +		strcat(string, argv[p]); +	} + +	if (p >= argc-1) { +		DebugPrintf("Matches a string against a said spec\n"); +		DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); +		DebugPrintf("<string> is a sequence of actual words.\n"); +		DebugPrintf("<said spec> is a sequence of hex tokens.\n"); +		return true; +	} + +	// TODO: Maybe turn this into a proper said spec compiler +	unsigned int len = 0; +	for (p++; p < argc; p++) { +		if (strcmp(argv[p], ",") == 0) { +			spec[len++] = 0xf0; +		} else if (strcmp(argv[p], "&") == 0) { +			spec[len++] = 0xf1; +		} else if (strcmp(argv[p], "/") == 0) { +			spec[len++] = 0xf2; +		} else if (strcmp(argv[p], "(") == 0) { +			spec[len++] = 0xf3; +		} else if (strcmp(argv[p], ")") == 0) { +			spec[len++] = 0xf4; +		} else if (strcmp(argv[p], "[") == 0) { +			spec[len++] = 0xf5; +		} else if (strcmp(argv[p], "]") == 0) { +			spec[len++] = 0xf6; +		} else if (strcmp(argv[p], "#") == 0) { +			spec[len++] = 0xf7; +		} else if (strcmp(argv[p], "<") == 0) { +			spec[len++] = 0xf8; +		} else if (strcmp(argv[p], ">") == 0) { +			spec[len++] = 0xf9; +		} else if (strcmp(argv[p], "[<") == 0) { +			spec[len++] = 0xf5; +			spec[len++] = 0xf8; +		} else if (strcmp(argv[p], "[/") == 0) { +			spec[len++] = 0xf5; +			spec[len++] = 0xf2; +		} else if (strcmp(argv[p], "!*") == 0) { +			spec[len++] = 0x0f; +			spec[len++] = 0xfe; +		} else if (strcmp(argv[p], "[!*]") == 0) { +			spec[len++] = 0xf5; +			spec[len++] = 0x0f; +			spec[len++] = 0xfe; +			spec[len++] = 0xf6; +		} else { +			unsigned int s = strtol(argv[p], 0, 16); +			if (s >= 0xf0 && s <= 0xff) { +				spec[len++] = s; +			} else { +				spec[len++] = s >> 8; +				spec[len++] = s & 0xFF; +			} +		} +	} +	spec[len++] = 0xFF; + +	printf("Matching '%s' against:", string); +	_engine->getVocabulary()->decipherSaidBlock(spec); + +	bool res = _engine->getVocabulary()->tokenizeString(words, string, &error); +	if (res && !words.empty()) { +		int syntax_fail = 0; + +		_engine->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 (_engine->getVocabulary()->parseGNF(words, true)) +			syntax_fail = 1; // Building a tree failed + +		if (syntax_fail) +			DebugPrintf("Building a tree failed.\n"); +		else { +			_engine->getVocabulary()->dumpParseTree(); +			_engine->getVocabulary()->parserIsValid = true; + +			int ret = said(_engine->_gamestate, (byte*)spec, true); +			DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match")); +		} + +	} else { +		DebugPrintf("Unknown word: '%s'\n", error); +		free(error); +	} + +	return true; +} + +  bool Console::cmdParserNodes(int argc, const char **argv) {  	if (argc != 2) {  		DebugPrintf("Shows the specified number of nodes from the parse node tree\n"); diff --git a/engines/sci/console.h b/engines/sci/console.h index 51f02d7168..cb96944e01 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -65,6 +65,7 @@ private:  	bool cmdSentenceFragments(int argc, const char **argv);  	bool cmdParse(int argc, const char **argv);  	bool cmdSetParseNodes(int argc, const char **argv); +	bool cmdSaid(int argc, const char **argv);  	// Resources  	bool cmdDiskDump(int argc, const char **argv);  	bool cmdHexDump(int argc, const char **argv);  | 
