aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction/parser.cpp
diff options
context:
space:
mode:
authorNicola Mettifogo2008-08-02 02:24:36 +0000
committerNicola Mettifogo2008-08-02 02:24:36 +0000
commit15aada52c4d641e54bc6c15af0999b5ea47a9025 (patch)
treea55e78b5a278d1934b8c46a016bbcd23c7c77c79 /engines/parallaction/parser.cpp
parenta89fb6b7fb886e2bdb4ca0975b8aa075914c638a (diff)
downloadscummvm-rg350-15aada52c4d641e54bc6c15af0999b5ea47a9025.tar.gz
scummvm-rg350-15aada52c4d641e54bc6c15af0999b5ea47a9025.tar.bz2
scummvm-rg350-15aada52c4d641e54bc6c15af0999b5ea47a9025.zip
* Added a preprocessor to deal with the crappy location scripts in BRA.
* Added some comments on how the parser and related code should be changed to make things smoother. svn-id: r33509
Diffstat (limited to 'engines/parallaction/parser.cpp')
-rw-r--r--engines/parallaction/parser.cpp185
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