diff options
Diffstat (limited to 'engines/parallaction/parser.cpp')
-rw-r--r-- | engines/parallaction/parser.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp index 6de0a7d7f5..710820f41a 100644 --- a/engines/parallaction/parser.cpp +++ b/engines/parallaction/parser.cpp @@ -28,6 +28,7 @@ namespace Parallaction { +int _numTokens; char _tokens[20][MAX_TOKEN_LEN]; Script::Script(Common::ReadStream *input, bool disposeSource) : _input(input), _disposeSource(disposeSource), _line(0) {} @@ -68,6 +69,8 @@ void Script::clearTokens() { for (uint16 i = 0; i < 20; i++) _tokens[i][0] = '\0'; + _numTokens = 0; + return; } @@ -157,6 +160,8 @@ uint16 Script::fillTokens(char* line) { i++; } + _numTokens = i; + return i; } @@ -243,4 +248,184 @@ void Parser::parseStatement() { } +#define BLOCK_BASE 100 + +class StatementDef { +protected: + Common::String makeLineFromTokens() { + Common::String space(" "); + Common::String newLine("\n"); + Common::String text; + for (int i = 0; i < _numTokens; i++) + text += (Common::String(_tokens[i]) + space); + text.deleteLastChar(); + text += newLine; + return text; + } + +public: + uint score; + const char* name; + + + StatementDef(uint score, const char *name) : score(score), name(name) { } + + virtual Common::String makeLine(Script &script) = 0;; + +}; + + +class SimpleStatementDef : public StatementDef { + +public: + SimpleStatementDef(uint score, const char *name) : StatementDef(score, name) { } + + Common::String makeLine(Script &script) { + return makeLineFromTokens(); + } + +}; + + + +class BlockStatementDef : public StatementDef { + + const char* ending1; + const char* ending2; + +public: + BlockStatementDef(uint score, const char *name, const char *ending1, const char *ending2 = 0) : StatementDef(score, name), ending1(ending1), + ending2(ending2) { } + + Common::String makeLine(Script &script) { + Common::String text = makeLineFromTokens(); + bool end; + do { + script.readLineToken(true); + text += makeLineFromTokens(); + end = !scumm_stricmp(ending1, _tokens[0]) || (ending2 && !scumm_stricmp(ending2, _tokens[0])); + } while (!end); + return text; + } + +}; + +class CommentStatementDef : public StatementDef { + + Common::String parseComment(Script &script) { + Common::String result; + char buf[129]; + + do { + script.readLine(buf, 128); + buf[strlen(buf)-1] = '\0'; + if (!scumm_stricmp(buf, "endtext")) + break; + result += Common::String(buf) + "\n"; + } while (true); + result += "endtext\n"; + return result; + } + +public: + CommentStatementDef(uint score, const char *name) : StatementDef(score, name) { } + + Common::String makeLine(Script &script) { + Common::String text = makeLineFromTokens(); + text += parseComment(script); + return text; + } + +}; + + + + +PreProcessor::PreProcessor() { + _defs.push_back(new SimpleStatementDef(1, "disk" )); + _defs.push_back(new SimpleStatementDef(2, "location" )); + _defs.push_back(new SimpleStatementDef(3, "localflags" )); + _defs.push_back(new SimpleStatementDef(4, "flags" )); + _defs.push_back(new SimpleStatementDef(5, "zeta" )); + _defs.push_back(new SimpleStatementDef(6, "music" )); + _defs.push_back(new SimpleStatementDef(7, "sound" )); + _defs.push_back(new SimpleStatementDef(8, "mask" )); + _defs.push_back(new SimpleStatementDef(9, "path" )); + _defs.push_back(new SimpleStatementDef(10, "character" )); + _defs.push_back(new CommentStatementDef(11, "comment" )); + _defs.push_back(new CommentStatementDef(12, "endcomment" )); + _defs.push_back(new BlockStatementDef(13, "ifchar", "endif" )); + _defs.push_back(new BlockStatementDef(BLOCK_BASE, "zone", "endanimation", "endzone" )); + _defs.push_back(new BlockStatementDef(BLOCK_BASE, "animation", "endanimation", "endzone" )); + _defs.push_back(new BlockStatementDef(1000, "commands", "endcommands" )); + _defs.push_back(new BlockStatementDef(1001, "acommands", "endcommands" )); + _defs.push_back(new BlockStatementDef(1002, "escape", "endcommands" )); + _defs.push_back(new SimpleStatementDef(2000, "endlocation")); +} + +PreProcessor::~PreProcessor() { + DefList::iterator it = _defs.begin(); + for (; it != _defs.end(); it++) { + delete *it; + } +} + +StatementDef* PreProcessor::findDef(const char* name) { + DefList::iterator it = _defs.begin(); + for (; it != _defs.end(); it++) { + if (!scumm_stricmp((*it)->name, name)) { + return *it; + } + } + return 0; +} + + + +uint PreProcessor::getDefScore(StatementDef* def) { + if (def->score == BLOCK_BASE) { + _numZones++; + return (_numZones + BLOCK_BASE); + } + return def->score; +} + + +void PreProcessor::preprocessScript(Script &script, StatementList &list) { + _numZones = 0; + Common::String text; + do { + script.readLineToken(false); + if (_numTokens == 0) + break; + + StatementDef *def = findDef(_tokens[0]); + assert(def); + + text = def->makeLine(script); + int score = getDefScore(def); + list.push_back(StatementListNode(score, def->name, text)); + } while (true); + Common::sort(list.begin(), list.end()); +} + + + + +void testPreprocessing(Parallaction *vm, const char *filename) { + Script *script = vm->_disk->loadLocation(filename); + StatementList list; + PreProcessor pp; + pp.preprocessScript(*script, list); + delete script; + Common::DumpFile dump; + dump.open(filename); + StatementList::iterator it = list.begin(); + for ( ; it != list.end(); it++) { + dump.write((*it)._text.c_str(), (*it)._text.size()); + } + dump.close(); +} + + } // namespace Parallaction |