2023-10-19 16:19:09 +02:00
/*
* 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
{
2024-01-10 00:38:54 +02:00
TIexp lhs ;
TIexp rhs ;
2023-10-19 16:19:09 +02:00
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 ;
2024-01-10 00:38:54 +02:00
TIexp lhs ;
TIexp rhs ;
2023-10-19 16:19:09 +02:00
} ;
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 EVOtions { 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 ) ;
} ;