scummvm/engines/twp/yack.h

454 lines
11 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef TWP_YACK_H
#define TWP_YACK_H
#include "common/array.h"
#include "common/str.h"
#include "common/stream.h"
#include "common/debug.h"
#include "twp/util.h"
namespace Twp {
enum class YackTokenId {
None,
NewLine,
Identifier,
WaitWhile,
Int,
Float,
Whitespace,
Colon,
Condition,
String,
Assign,
Comment,
Goto,
Code,
Dollar,
End
};
// enumeration that lists all errors that can occur
enum YackError {
ERR_NONE, // no error
ERR_INVALIDYackToken, // invalid YackToken
ERR_STRINGEXPECTED, // string expected
ERR_COLONEXPECTED, // `:` expected
ERR_COMMAEXPECTED, // `,` expected
ERR_BRACKETRIEXPECTED, // `]` expected
ERR_CURLYRIEXPECTED, // `}` expected
ERR_QUOTEEXPECTED, // `"` or `'` expected
ERR_EOC_EXPECTED, // `*/` expected
ERR_EOFEXPECTED, // EOF expected
ERR_EXPREXPECTED // expr expected
};
class YackVisitor;
class YackNode {
public:
virtual ~YackNode() {}
virtual void accept(YackVisitor &v) = 0;
};
// Represents a condition
class YCond : public YackNode {
public:
virtual ~YCond() {}
public:
int _line;
};
class YCodeCond : public YCond {
public:
YCodeCond(int line) { _line = line; }
virtual ~YCodeCond() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _code;
};
class YOnce : public YCond {
public:
YOnce(int line) { _line = line; }
virtual ~YOnce() {}
virtual void accept(YackVisitor &v) override;
};
class YShowOnce : public YCond {
public:
YShowOnce(int line) { _line = line; }
virtual ~YShowOnce() {}
virtual void accept(YackVisitor &v) override;
};
class YOnceEver : public YCond {
public:
YOnceEver(int line) { _line = line; }
virtual ~YOnceEver() {}
virtual void accept(YackVisitor &v) override;
};
class YTempOnce : public YCond {
public:
YTempOnce(int line) { _line = line; }
virtual ~YTempOnce() {}
virtual void accept(YackVisitor &v) override;
};
// Expression
class YExp : public YackNode {
public:
YExp() {}
virtual ~YExp() {}
};
class YGoto : public YExp {
public:
YGoto(int line) { _line = line; }
virtual ~YGoto() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _name;
int _line = 0;
};
class YCodeExp : public YExp {
public:
virtual ~YCodeExp() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _code;
};
class YChoice : public YExp {
public:
virtual ~YChoice() {}
virtual void accept(YackVisitor &v) override;
public:
int _number = 0;
Common::String _text;
Common::SharedPtr<YGoto> _goto;
};
class YSay : public YExp {
public:
virtual ~YSay() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _actor;
Common::String _text;
};
class YPause : public YExp {
public:
virtual ~YPause() {}
virtual void accept(YackVisitor &v) override;
public:
int _time = 0;
};
class YParrot : public YExp {
public:
virtual ~YParrot() {}
virtual void accept(YackVisitor &v) override;
public:
bool _active = true;
};
class YDialog : public YExp {
public:
virtual ~YDialog() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _actor;
};
class YOverride : public YExp {
public:
virtual ~YOverride() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _node;
};
class YShutup : public YExp {
public:
virtual ~YShutup() {}
virtual void accept(YackVisitor &v) override;
};
class YAllowObjects : public YExp {
public:
virtual ~YAllowObjects() {}
virtual void accept(YackVisitor &v) override;
public:
bool _active = true;
};
class YLimit : public YExp {
public:
virtual ~YLimit() {}
virtual void accept(YackVisitor &v) override;
public:
int _max = 8;
};
class YWaitWhile : public YExp {
public:
virtual ~YWaitWhile() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _cond;
};
class YWaitFor : public YExp {
public:
virtual ~YWaitFor() {}
virtual void accept(YackVisitor &v) override;
public:
Common::String _actor;
};
//
class YStatement : public YackNode {
public:
virtual ~YStatement() override {}
virtual void accept(YackVisitor &v) override;
public:
Common::SharedPtr<YExp> _exp;
Common::Array<Common::SharedPtr<YCond> > _conds;
};
class YLabel : public YackNode {
public:
YLabel(int line);
virtual ~YLabel() override;
virtual void accept(YackVisitor &v) override;
public:
Common::String _name;
Common::Array<Common::SharedPtr<YStatement> > _stmts;
int _line = 0;
};
class YCompilationUnit : public YackNode {
public:
virtual ~YCompilationUnit() override;
virtual void accept(YackVisitor &v) override;
public:
Common::Array<Common::SharedPtr<YLabel> > _labels;
};
class YackVisitor {
public:
virtual ~YackVisitor() {}
virtual void visit(const YCompilationUnit &node) { defaultVisit(node); }
virtual void visit(const YStatement &node) { defaultVisit(node); }
virtual void visit(const YWaitFor &node) { defaultVisit(node); }
virtual void visit(const YWaitWhile &node) { defaultVisit(node); }
virtual void visit(const YLimit &node) { defaultVisit(node); }
virtual void visit(const YAllowObjects &node) { defaultVisit(node); }
virtual void visit(const YShutup &node) { defaultVisit(node); }
virtual void visit(const YOverride &node) { defaultVisit(node); }
virtual void visit(const YDialog &node) { defaultVisit(node); }
virtual void visit(const YParrot &node) { defaultVisit(node); }
virtual void visit(const YPause &node) { defaultVisit(node); }
virtual void visit(const YSay &node) { defaultVisit(node); }
virtual void visit(const YChoice &node) { defaultVisit(node); }
virtual void visit(const YCodeExp &node) { defaultVisit(node); }
virtual void visit(const YGoto &node) { defaultVisit(node); }
virtual void visit(const YTempOnce &node) { defaultVisit(node); }
virtual void visit(const YOnceEver &node) { defaultVisit(node); }
virtual void visit(const YShowOnce &node) { defaultVisit(node); }
virtual void visit(const YOnce &node) { defaultVisit(node); }
virtual void visit(const YCodeCond &node) { defaultVisit(node); }
virtual void visit(const YLabel &node) { defaultVisit(node); }
virtual void defaultVisit(const YackNode &node) {}
};
struct YackToken {
YackTokenId id = YackTokenId::None;
int64 start = 0;
int64 end = 0;
int line = 0;
Common::String toString() const;
};
class YackTokenReader {
public:
class Iterator {
public:
using value_type = YackToken;
using difference_type = ptrdiff_t;
using pointer = YackToken *;
using reference = YackToken &;
private:
YackTokenReader *_reader = nullptr;
int64 _pos = 0;
YackToken _token;
public:
Iterator() {}
Iterator(YackTokenReader &reader, int64 pos);
Iterator(const Iterator &it);
Iterator &operator++();
Iterator operator++(int);
Iterator &operator=(const Iterator &rhs) {
_pos = rhs._pos;
_token = rhs._token;
_reader = rhs._reader;
return *this;
}
bool operator==(const Iterator &rhs) const { return _pos == rhs._pos; }
bool operator!=(const Iterator &rhs) const { return _pos != rhs._pos; }
YackToken &operator*();
const YackToken &operator*() const;
YackToken *operator->();
};
using iterator = Iterator;
public:
void open(Common::SeekableReadStream *stream);
iterator begin();
iterator end();
Common::String readText(const YackToken &YackToken);
private:
bool readYackToken(YackToken &YackToken);
Common::String readText(int64 pos, int64 size);
YackTokenId readYackTokenId();
YackTokenId readCode();
YackTokenId readCondition();
YackTokenId readDollar();
YackTokenId readNumber();
YackTokenId readComment();
YackTokenId readString();
YackTokenId readIdentifier(char c);
byte peek();
void ignore(int64 n = 1, int delim = EOF);
private:
Common::SeekableReadStream *_stream = nullptr;
int _line = 0;
friend class YackParser;
};
class YackParser {
public:
YackParser() {}
YCompilationUnit *parse(Common::SeekableReadStream *stream);
private:
bool match(const std::initializer_list<YackTokenId> &ids);
Common::SharedPtr<YLabel> parseLabel();
Common::SharedPtr<YStatement> parseStatement();
Common::SharedPtr<YCond> parseCondition();
Common::SharedPtr<YExp> parseExpression();
Common::SharedPtr<YSay> parseSayExpression();
Common::SharedPtr<YExp> parseWaitWhileExpression();
Common::SharedPtr<YExp> parseInstructionExpression();
Common::SharedPtr<YGoto> parseGotoExpression();
Common::SharedPtr<YCodeExp> parseCodeExpression();
Common::SharedPtr<YChoice> parseChoiceExpression();
private:
YackTokenReader _reader;
YackTokenReader::iterator _it;
};
class YackDump : public YackVisitor {
public:
virtual ~YackDump() {}
virtual void visit(const YCompilationUnit &node) {
debug("CompilationUnit:");
for (const auto &cond : node._labels) {
cond->accept(*this);
}
}
virtual void visit(const YLabel &node) {
debug("Label: %s [%d]", node._name.c_str(), node._line);
for (const auto &stmt : node._stmts) {
stmt->accept(*this);
}
}
virtual void visit(const YStatement &node) {
debug("Statement:");
for (const auto &cond : node._conds) {
cond->accept(*this);
}
node._exp->accept(*this);
}
virtual void visit(const YWaitFor &node) { debug("WaifFor %s", node._actor.c_str()); }
virtual void visit(const YWaitWhile &node) { debug("WaitWhile %s", node._cond.c_str()); }
virtual void visit(const YLimit &node) { debug("Limit: %d", node._max); }
virtual void visit(const YAllowObjects &node) { debug("AllowObjects"); }
virtual void visit(const YShutup &node) { debug("Shutup"); }
virtual void visit(const YOverride &node) { defaultVisit(node); }
virtual void visit(const YDialog &node) { debug("Dialog: %s", node._actor.c_str()); }
virtual void visit(const YParrot &node) { debug("Parrot: %s", node._active ? "YES" : "NO"); }
virtual void visit(const YPause &node) { debug("Pause: %d", node._time); }
virtual void visit(const YSay &node) { debug("Say: actor: %s, text = %s", node._actor.c_str(), node._text.c_str()); }
virtual void visit(const YChoice &node) { debug("Choice %d: %s -> %s", node._number, node._text.c_str(), node._goto->_name.c_str()); }
virtual void visit(const YCodeExp &node) { debug("Code: %s", node._code.c_str()); }
virtual void visit(const YGoto &node) { debug("Goto: %s", node._name.c_str()); }
virtual void visit(const YTempOnce &node) { debug("TempOnce"); }
virtual void visit(const YOnceEver &node) { debug("OnceEver"); }
virtual void visit(const YShowOnce &node) { debug("ShowOnce"); }
virtual void visit(const YOnce &node) { debug("Once"); }
virtual void visit(const YCodeCond &node) { debug("Cond: %s", node._code.c_str()); }
virtual void defaultVisit(const YackNode &node) {}
};
} // namespace Twp
#endif