123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /*
- * ERMParser.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #pragma once
- #include <boost/spirit/home/support/unused.hpp>
- #include <boost/variant/recursive_wrapper.hpp>
- namespace spirit = boost::spirit;
- class CERMPreprocessor
- {
- std::string fname;
- std::stringstream sourceStream;
- int lineNo;
- void getline(std::string &ret);
- public:
- enum class Version : ui8
- {
- INVALID,
- ERM,
- VERM
- };
- Version version;
- CERMPreprocessor(const std::string & source);
- std::string retrieveCommandLine();
- int getCurLineNo() const
- {
- return lineNo;
- }
- const std::string& getCurFileName() const
- {
- return fname;
- }
- };
- //various classes that represent ERM/VERM AST
- namespace ERM
- {
- using ValType = int; //todo: set to int64_t
- using IType = int; //todo: set to int32_t
- struct TStringConstant
- {
- std::string str;
- };
- struct TMacroUsage
- {
- std::string macro;
- };
- // //macro with '?', for write only
- // struct TQMacroUsage
- // {
- // std::string qmacro;
- // };
- //definition of a macro
- struct TMacroDef
- {
- std::string macro;
- };
- typedef std::string TCmdName;
- struct TVarExpNotMacro
- {
- typedef std::optional<int> Tval;
- std::optional<char> questionMark;
- std::string varsym;
- Tval val;
- };
- typedef std::variant<TVarExpNotMacro, TMacroUsage> TVarExp;
- //write-only variable expression
- struct TVarpExp
- {
- TVarExp var;
- };
- //i-expression (identifier expression) - an integral constant, variable symbol or array symbol
- typedef std::variant<TVarExp, int> TIexp;
- struct TArithmeticOp
- {
- TIexp lhs;
- TIexp rhs;
- char opcode;
- };
- struct TVRLogic
- {
- char opcode;
- TIexp var;
- };
- struct TVRArithmetic
- {
- char opcode;
- TIexp rhs;
- };
- struct TSemiCompare
- {
- std::string compSign;
- TIexp rhs;
- };
- struct TCurriedString
- {
- TIexp iexp;
- TStringConstant string;
- };
- struct TVarConcatString
- {
- TVarExp var;
- TStringConstant string;
- };
- typedef std::variant<TVarConcatString, TStringConstant, TCurriedString, TSemiCompare, TMacroDef, TIexp, TVarpExp> TBodyOptionItem;
- typedef std::vector<TBodyOptionItem> TNormalBodyOptionList;
- struct TNormalBodyOption
- {
- char optionCode;
- std::optional<TNormalBodyOptionList> params;
- };
- typedef std::variant<TVRLogic, TVRArithmetic, TNormalBodyOption> TBodyOption;
- // typedef std::variant<TIexp, TArithmeticOp > TIdentifierInternal;
- typedef std::vector< TIexp > Tidentifier;
- struct TComparison
- {
- std::string compSign;
- TIexp lhs;
- TIexp rhs;
- };
- struct Tcondition;
- typedef std::optional<boost::recursive_wrapper<Tcondition>> TconditionNode;
- struct Tcondition
- {
- typedef std::variant<
- TComparison,
- int>
- Tcond; //comparison or condition flag
- char ctype;
- Tcond cond;
- TconditionNode rhs;
- };
- struct TTriggerBase
- {
- bool pre; //if false it's !$ post-trigger, elsewise it's !# (pre)trigger
- TCmdName name;
- std::optional<Tidentifier> identifier;
- std::optional<Tcondition> condition;
- };
- struct Ttrigger : TTriggerBase
- {
- Ttrigger()
- {
- pre = true;
- }
- };
- struct TPostTrigger : TTriggerBase
- {
- TPostTrigger()
- {
- pre = false;
- }
- };
- //a dirty workaround for preprocessor magic that prevents the use types with comma in it in BOOST_FUSION_ADAPT_STRUCT
- //see http://comments.gmane.org/gmane.comp.lib.boost.user/62501 for some info
- //
- //moreover, I encountered a quite serious bug in boost: http://boost.2283326.n4.nabble.com/container-hpp-111-error-C2039-value-type-is-not-a-member-of-td3352328.html
- //not sure how serious it is...
- //typedef std::variant<char, TStringConstant, TMacroUsage, TMacroDef> bodyItem;
- typedef std::vector<TBodyOption> Tbody;
- struct Tinstruction
- {
- TCmdName name;
- std::optional<Tidentifier> identifier;
- std::optional<Tcondition> condition;
- Tbody body;
- };
- struct Treceiver
- {
- TCmdName name;
- std::optional<Tidentifier> identifier;
- std::optional<Tcondition> condition;
- std::optional<Tbody> body;
- };
- struct Tcommand
- {
- typedef std::variant<
- Ttrigger,
- Tinstruction,
- Treceiver,
- TPostTrigger
- >
- Tcmd;
- Tcmd cmd;
- //std::string comment;
- };
- //vector expression
- typedef std::variant<Tcommand, std::string, boost::spirit::unused_type> TERMline;
- typedef std::string TVModifier; //'`', ',', ',@', '#''
- struct TSymbol
- {
- std::vector<TVModifier> symModifier;
- std::string sym;
- };
- //for #'symbol expression
- enum EVOptions{VEXP, SYMBOL, CHAR, DOUBLE, INT, TCMD, STRINGC};
- struct TVExp;
- typedef std::variant<boost::recursive_wrapper<TVExp>, TSymbol, char, double, int, Tcommand, TStringConstant > TVOption; //options in v-expression
- //v-expression
- struct TVExp
- {
- std::vector<TVModifier> modifier;
- std::vector<TVOption> children;
- };
- //script line
- typedef std::variant<TVExp, TERMline> TLine;
- template <typename T> struct ERM_grammar;
- }
- struct LineInfo
- {
- ERM::TLine tl;
- int realLineNum;
- };
- class ERMParser
- {
- public:
- std::shared_ptr<ERM::ERM_grammar<std::string::const_iterator>> ERMgrammar;
- ERMParser();
- virtual ~ERMParser();
- std::vector<LineInfo> parseFile(CERMPreprocessor & preproc);
- private:
- void repairEncoding(char * str, int len) const; //removes nonstandard ascii characters from string
- void repairEncoding(std::string & str) const; //removes nonstandard ascii characters from string
- ERM::TLine parseLine(const std::string & line, int realLineNo);
- ERM::TLine parseLine(const std::string & line);
- };
|