1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-12 10:03:53 +02:00
vcmi/scripting/erm/ERMParser.h

281 lines
5.4 KiB
C++
Raw Normal View History

/*
* 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);
};