2011-03-19 19:06:46 +02:00
# pragma once
2011-12-14 00:23:17 +03:00
2012-12-20 16:56:57 +03:00
# include <boost/spirit/home/support/unused.hpp>
# include <boost/spirit/include/qi.hpp>
# include <boost/spirit/include/phoenix_core.hpp>
# include <boost/spirit/include/phoenix_operator.hpp>
# include <boost/spirit/include/phoenix_fusion.hpp>
# include <boost/spirit/include/phoenix_stl.hpp>
# include <boost/spirit/include/phoenix_object.hpp>
# include <boost/fusion/include/adapt_struct.hpp>
namespace spirit = boost : : spirit ;
namespace qi = boost : : spirit : : qi ;
namespace ascii = spirit : : ascii ;
namespace phoenix = boost : : phoenix ;
2011-04-06 23:30:59 +03: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
*
*/
2011-04-04 00:38:47 +03:00
class CERMPreprocessor
{
std : : string fname ;
std : : ifstream file ;
int lineNo ;
enum { INVALID , ERM , VERM } version ;
void getline ( std : : string & ret ) ;
public :
CERMPreprocessor ( const std : : string & Fname ) ;
std : : string retreiveCommandLine ( ) ;
2011-05-11 22:53:55 +03:00
int getCurLineNo ( ) const
{
return lineNo ;
}
2011-04-04 00:38:47 +03:00
} ;
2011-03-19 19:06:46 +02:00
2011-04-06 23:30:59 +03:00
//various classes that represent ERM/VERM AST
namespace ERM
{
struct TStringConstant
{
std : : string str ;
} ;
struct TMacroUsage
{
std : : string macro ;
} ;
2011-05-14 16:20:19 +03:00
// //macro with '?', for write only
// struct TQMacroUsage
// {
// std::string qmacro;
// };
2011-04-06 23:30:59 +03:00
//definition of a macro
struct TMacroDef
{
std : : string macro ;
} ;
typedef std : : string TCmdName ;
struct TVarExpNotMacro
{
typedef boost : : optional < int > Tval ;
boost : : optional < char > questionMark ;
std : : string varsym ;
Tval val ;
} ;
typedef boost : : variant < TVarExpNotMacro , TMacroUsage > TVarExp ;
//write-only variable expression
struct TVarpExp
{
2011-05-16 15:11:00 +03:00
TVarExp var ;
2011-04-06 23:30:59 +03:00
} ;
//i-expression (identifier expression) - an integral constant, variable symbol or array symbol
typedef boost : : variant < TVarExp , int > TIexp ;
struct TArithmeticOp
{
TIexp lhs , 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 ;
} ;
2011-05-16 15:11:00 +03:00
typedef boost : : variant < TVarConcatString , TStringConstant , TCurriedString , TSemiCompare , TMacroDef , TIexp , TVarpExp , boost : : spirit : : unused_type > TBodyOptionItem ;
2011-04-06 23:30:59 +03:00
typedef std : : vector < TBodyOptionItem > TNormalBodyOptionList ;
struct TNormalBodyOption
{
char optionCode ;
TNormalBodyOptionList params ;
} ;
typedef boost : : variant < TVRLogic , TVRArithmetic , TNormalBodyOption > TBodyOption ;
typedef boost : : variant < TIexp , TArithmeticOp > TIdentifierInternal ;
typedef std : : vector < TIdentifierInternal > Tidentifier ;
struct TComparison
{
std : : string compSign ;
TIexp lhs , rhs ;
} ;
struct Tcondition ;
typedef
boost : : optional <
boost : : recursive_wrapper < Tcondition >
>
TconditionNode ;
struct Tcondition
{
typedef boost : : variant <
TComparison ,
int >
Tcond ; //comparison or condition flag
char ctype ;
Tcond cond ;
TconditionNode rhs ;
} ;
2011-05-14 16:20:19 +03:00
struct TTriggerBase
2011-04-06 23:30:59 +03:00
{
2011-05-14 16:20:19 +03:00
bool pre ; //if false it's !$ post-trigger, elsewise it's !# (pre)trigger
2011-04-06 23:30:59 +03:00
TCmdName name ;
boost : : optional < Tidentifier > identifier ;
boost : : optional < Tcondition > condition ;
} ;
2011-05-14 16:20:19 +03:00
struct Ttrigger : TTriggerBase
{
Ttrigger ( )
{
2011-05-22 21:46:52 +03:00
pre = true ;
2011-05-14 16:20:19 +03:00
}
} ;
struct TPostTrigger : TTriggerBase
{
TPostTrigger ( )
{
2011-05-22 21:46:52 +03:00
pre = false ;
2011-05-14 16:20:19 +03:00
}
} ;
2011-04-06 23:30:59 +03:00
//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 boost::variant<char, TStringConstant, TMacroUsage, TMacroDef> bodyItem;
typedef std : : vector < TBodyOption > Tbody ;
struct Tinstruction
{
TCmdName name ;
boost : : optional < Tidentifier > identifier ;
boost : : optional < Tcondition > condition ;
Tbody body ;
} ;
struct Treceiver
{
TCmdName name ;
boost : : optional < Tidentifier > identifier ;
boost : : optional < Tcondition > condition ;
boost : : optional < Tbody > body ;
} ;
struct Tcommand
{
typedef boost : : variant <
Ttrigger ,
Tinstruction ,
Treceiver ,
TPostTrigger
>
Tcmd ;
Tcmd cmd ;
std : : string comment ;
} ;
//vector expression
typedef boost : : 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
2011-04-10 19:39:34 +03:00
enum EVOtions { VEXP , SYMBOL , CHAR , DOUBLE , INT , TCMD , STRINGC } ;
2011-04-06 23:30:59 +03:00
struct TVExp ;
typedef boost : : 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 boost : : variant < TVExp , TERMline > TLine ;
}
2011-05-11 22:53:55 +03:00
struct LineInfo
{
ERM : : TLine tl ;
int realLineNum ;
} ;
2011-03-19 19:06:46 +02:00
class ERMParser
{
private :
std : : string srcFile ;
2011-03-28 22:34:00 +03:00
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
2011-04-03 16:15:07 +03:00
enum ELineType { COMMAND_FULL , COMMENT , UNFINISHED , END_OF } ;
2011-03-25 22:38:24 +02:00
int countHatsBeforeSemicolon ( const std : : string & line ) const ;
2011-05-11 22:53:55 +03:00
ERM : : TLine parseLine ( const std : : string & line , int realLineNo ) ;
2011-03-19 19:06:46 +02:00
public :
ERMParser ( std : : string file ) ;
2011-05-11 22:53:55 +03:00
std : : vector < LineInfo > parseFile ( ) ;
2011-06-24 00:42:30 +03:00
static ERM : : TLine parseLine ( const std : : string & line ) ;
2011-03-19 19:06:46 +02:00
} ;