1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

* minor improvements in parser/interpreter

This commit is contained in:
mateuszb
2011-05-16 12:11:00 +00:00
parent 4eef7aa83b
commit 6014edb7ea
4 changed files with 99 additions and 47 deletions

View File

@@ -568,8 +568,6 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
///////// /////////
//code execution //code execution
struct VRPerformer;
template<typename OwnerType> template<typename OwnerType>
struct StandardBodyOptionItemVisitor : boost::static_visitor<> struct StandardBodyOptionItemVisitor : boost::static_visitor<>
{ {
@@ -592,10 +590,10 @@ struct StandardBodyOptionItemVisitor : boost::static_visitor<>
{ {
throw EScriptExecError("Semi comparison not allowed in this receiver"); throw EScriptExecError("Semi comparison not allowed in this receiver");
} }
virtual void operator()(TMacroUsage const& cmp) const // virtual void operator()(TMacroUsage const& cmp) const
{ // {
throw EScriptExecError("Macro usage not allowed in this receiver"); // throw EScriptExecError("Macro usage not allowed in this receiver");
} // }
virtual void operator()(TMacroDef const& cmp) const virtual void operator()(TMacroDef const& cmp) const
{ {
throw EScriptExecError("Macro definition not allowed in this receiver"); throw EScriptExecError("Macro definition not allowed in this receiver");
@@ -633,13 +631,13 @@ struct StandardReceiverVisitor : boost::static_visitor<>
virtual void operator()(TNormalBodyOption const& trig) const = 0; virtual void operator()(TNormalBodyOption const& trig) const = 0;
}; };
struct VRPerformer;
struct VR_SPerformer : StandardBodyOptionItemVisitor<VRPerformer> struct VR_SPerformer : StandardBodyOptionItemVisitor<VRPerformer>
{ {
explicit VR_SPerformer(VRPerformer & _owner); explicit VR_SPerformer(VRPerformer & _owner);
using StandardBodyOptionItemVisitor<VRPerformer>::operator(); using StandardBodyOptionItemVisitor<VRPerformer>::operator();
void operator()(TStringConstant const& cmp) const OVERRIDE; void operator()(TStringConstant const& cmp) const OVERRIDE;
void operator()(TMacroUsage const& cmp) const OVERRIDE;
void operator()(TIexp const& cmp) const OVERRIDE; void operator()(TIexp const& cmp) const OVERRIDE;
}; };
@@ -761,13 +759,20 @@ void VR_SPerformer::operator()(TStringConstant const& cmp) const
{ {
owner.identifier.setTo(cmp.str); owner.identifier.setTo(cmp.str);
} }
void VR_SPerformer::operator()(TMacroUsage const& cmp) const
{
owner.identifier.setTo(owner.interp->getIexp(cmp));
}
struct ConditionDisemboweler; struct ConditionDisemboweler;
struct OBPerformer;
struct OB_UPerformer : StandardBodyOptionItemVisitor<OBPerformer>
{
explicit OB_UPerformer(OBPerformer & owner) : StandardBodyOptionItemVisitor(owner)
{}
using StandardBodyOptionItemVisitor<OBPerformer>::operator();
virtual void operator()(TIexp const& cmp) const;
virtual void operator()(TVarpExp const& cmp) const;
};
struct OBPerformer : StandardReceiverVisitor<int3> struct OBPerformer : StandardReceiverVisitor<int3>
{ {
OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos) OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos)
@@ -807,7 +812,7 @@ struct OBPerformer : StandardReceiverVisitor<int3>
//TODO //TODO
} }
break; break;
case 'R': //eable all gamers to use object case 'R': //enable all gamers to use object
{ {
//TODO //TODO
} }
@@ -824,7 +829,10 @@ struct OBPerformer : StandardReceiverVisitor<int3>
break; break;
case 'U': //sgc of obj subtype case 'U': //sgc of obj subtype
{ {
//TODO if(trig.params.size() == 1)
boost::apply_visitor(OB_UPerformer(const_cast<OBPerformer&>(*this)), trig.params[0]);
else
throw EScriptExecError("OB:U takes exactly one parameter!");
} }
break; break;
default: default:
@@ -834,6 +842,15 @@ struct OBPerformer : StandardReceiverVisitor<int3>
} }
}; };
void OB_UPerformer::operator()( TIexp const& cmp ) const
{
IexpValStr val = owner.interp->getIexp(cmp);
}
void OB_UPerformer::operator()( TVarpExp const& cmp ) const
{
IexpValStr val = owner.interp->getIexp(cmp);
}
struct ERMExpDispatch : boost::static_visitor<> struct ERMExpDispatch : boost::static_visitor<>
{ {
@@ -850,6 +867,39 @@ struct ERMExpDispatch : boost::static_visitor<>
} }
void operator()(Treceiver const& trig) const void operator()(Treceiver const& trig) const
{ {
struct HLP
{
ERMInterpreter * ei;
HLP(ERMInterpreter * interp) : ei(interp)
{}
int3 getPosFromIdentifier(ERM::Tidentifier tid, bool allowDummyFourth)
{
switch(tid.size())
{
case 1:
{
int num = ei->getIexp(tid[0]).getInt();
return int3(ei->ermGlobalEnv->getStandardVar(num),
ei->ermGlobalEnv->getStandardVar(num+1),
ei->ermGlobalEnv->getStandardVar(num+2));
}
break;
case 3:
case 4:
if(tid.size() == 4 && !allowDummyFourth)
throw EScriptExecError("4 items in identifirer are not allowed for this receiver!");
return int3(ei->getIexp(tid[0]).getInt(),
ei->getIexp(tid[1]).getInt(),
ei->getIexp(tid[2]).getInt());
break;
default:
throw EScriptExecError("This receiver takes 1 or 3 items in identifier!");
break;
}
}
};
if(trig.name == "VR") if(trig.name == "VR")
{ {
//check condition //check condition
@@ -912,31 +962,25 @@ struct ERMExpDispatch : boost::static_visitor<>
} }
} }
} }
else if(trig.name == "MO")
{
int3 objPos;
if(trig.identifier.is_initialized())
{
ERM::Tidentifier tid = trig.identifier.get();
objPos = HLP(owner).getPosFromIdentifier(tid, true);
}
else
throw EScriptExecError("MO receiver must have an identifier!");
}
else if(trig.name == "OB") else if(trig.name == "OB")
{ {
int3 objPos; int3 objPos;
if(trig.identifier.is_initialized()) if(trig.identifier.is_initialized())
{ {
ERM::Tidentifier tid = trig.identifier.get(); ERM::Tidentifier tid = trig.identifier.get();
switch(tid.size()) objPos = HLP(owner).getPosFromIdentifier(tid, false);
{
case 1:
{
int num = owner->getIexp(tid[0]).getInt();
objPos = int3(owner->ermGlobalEnv->getStandardVar(num),
owner->ermGlobalEnv->getStandardVar(num+1),
owner->ermGlobalEnv->getStandardVar(num+2));
}
break;
case 3:
objPos = int3(owner->getIexp(tid[0]).getInt(),
owner->getIexp(tid[1]).getInt(),
owner->getIexp(tid[2]).getInt());
break;
default:
throw EScriptExecError("OB receiver takes 1 or 3 items in identifier!");
break;
}
//execute body //execute body
if(trig.body.is_initialized()) if(trig.body.is_initialized())
{ {
@@ -954,7 +998,7 @@ struct ERMExpDispatch : boost::static_visitor<>
} }
else else
{ {
//unsupported or invalid trigger //not supported or invalid trigger
} }
} }
void operator()(TPostTrigger const& trig) const void operator()(TPostTrigger const& trig) const
@@ -1284,6 +1328,11 @@ IexpValStr ERMInterpreter::getIexp( const ERM::TIdentifierInternal & tid ) const
throw EScriptExecError("Identifier must be a valid i-expression to perform this operation!"); throw EScriptExecError("Identifier must be a valid i-expression to perform this operation!");
} }
IexpValStr ERMInterpreter::getIexp( const ERM::TVarpExp & tid ) const
{
return boost::apply_visitor(LVL2IexpDisemboweler(const_cast<ERMInterpreter*>(this), IexpDisemboweler::GET), tid.var);
}
void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams/*=std::vector<int>()*/ ) void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams/*=std::vector<int>()*/ )
{ {
struct HLP struct HLP

View File

@@ -471,14 +471,15 @@ public:
class ERMInterpreter class ERMInterpreter
{ {
friend class ScriptScanner; /*not so*/ public:
friend class TriggerIdMatchHelper; // friend class ScriptScanner;
friend class TriggerIdentifierMatch; // friend class TriggerIdMatchHelper;
friend class ConditionDisemboweler; // friend class TriggerIdentifierMatch;
friend struct LVL2IexpDisemboweler; // friend class ConditionDisemboweler;
friend struct VR_SPerformer; // friend struct LVL2IexpDisemboweler;
friend struct ERMExpDispatch; // friend struct VR_SPerformer;
friend struct VRPerformer; // friend struct ERMExpDispatch;
// friend struct VRPerformer;
std::vector<VERMInterpreter::FileInfo*> files; std::vector<VERMInterpreter::FileInfo*> files;
std::vector< VERMInterpreter::FileInfo* > fileInfos; std::vector< VERMInterpreter::FileInfo* > fileInfos;
@@ -500,6 +501,7 @@ class ERMInterpreter
IexpValStr getIexp(const ERM::TIexp & iexp) const; IexpValStr getIexp(const ERM::TIexp & iexp) const;
IexpValStr getIexp(const ERM::TMacroUsage & macro) const; IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const; IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
IexpValStr getIexp(const ERM::TVarpExp & tid) const;
static const std::string triggerSymbol, postTriggerSymbol, defunSymbol; static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
@@ -509,6 +511,8 @@ class ERMInterpreter
static bool isATrigger(const ERM::TLine & line); static bool isATrigger(const ERM::TLine & line);
static ERM::EVOtions getExpType(const ERM::TVOption & opt); static ERM::EVOtions getExpType(const ERM::TVOption & opt);
IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const; IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
public: public:
typedef std::map< int, std::vector<int> > TIDPattern; typedef std::map< int, std::vector<int> > TIDPattern;
void executeInstructions(); //called when starting a new game, before most of the map settings are done void executeInstructions(); //called when starting a new game, before most of the map settings are done

View File

@@ -239,7 +239,7 @@ BOOST_FUSION_ADAPT_STRUCT(
BOOST_FUSION_ADAPT_STRUCT( BOOST_FUSION_ADAPT_STRUCT(
ERM::TVarpExp, ERM::TVarpExp,
(ERM::TVarpExp::Tvartype, var) (ERM::TVarExp, var)
) )
BOOST_FUSION_ADAPT_STRUCT( BOOST_FUSION_ADAPT_STRUCT(
@@ -355,7 +355,7 @@ namespace ERM
/*qERMMacroUsage %= qi::lexeme[qi::lit("?$") >> *(qi::char_ - '$') >> qi::lit('$')];*/ /*qERMMacroUsage %= qi::lexeme[qi::lit("?$") >> *(qi::char_ - '$') >> qi::lit('$')];*/
varExp %= varExpNotMacro | ERMmacroUsage; varExp %= varExpNotMacro | ERMmacroUsage;
iexp %= varExp | qi::int_; iexp %= varExp | qi::int_;
varp %= qi::lit("?") >> (varExpNotMacro | ERMmacroUsage); varp %= qi::lit("?") >> varExp;
comment %= *qi::char_; comment %= *qi::char_;
commentLine %= (~qi::char_("!") >> comment | (qi::char_('!') >> (~qi::char_("?!$#[")) >> comment )); commentLine %= (~qi::char_("!") >> comment | (qi::char_('!') >> (~qi::char_("?!$#[")) >> comment ));
cmdName %= qi::lexeme[qi::repeat(2)[qi::char_]]; cmdName %= qi::lexeme[qi::repeat(2)[qi::char_]];
@@ -373,7 +373,7 @@ namespace ERM
semiCompare %= +qi::char_("<=>") >> iexp; semiCompare %= +qi::char_("<=>") >> iexp;
curStr %= iexp >> string; curStr %= iexp >> string;
varConcatString %= varExp >> qi::lit("+") >> string; varConcatString %= varExp >> qi::lit("+") >> string;
bodyOptionItem %= varConcatString | curStr | string | semiCompare | ERMmacroUsage | ERMmacroDef | varp | iexp | qi::eps; bodyOptionItem %= varConcatString | curStr | string | semiCompare | ERMmacroDef | varp | iexp | qi::eps;
exactBodyOptionList %= (bodyOptionItem % qi::lit("/")); exactBodyOptionList %= (bodyOptionItem % qi::lit("/"));
normalBodyOption = qi::char_("A-Z+") > exactBodyOptionList; normalBodyOption = qi::char_("A-Z+") > exactBodyOptionList;
bodyOption %= VRLogic | VRarithmetic | normalBodyOption; bodyOption %= VRLogic | VRarithmetic | normalBodyOption;

View File

@@ -72,8 +72,7 @@ namespace ERM
//write-only variable expression //write-only variable expression
struct TVarpExp struct TVarpExp
{ {
typedef boost::variant<TVarExpNotMacro, TMacroUsage> Tvartype; TVarExp var;
Tvartype var;
}; };
//i-expression (identifier expression) - an integral constant, variable symbol or array symbol //i-expression (identifier expression) - an integral constant, variable symbol or array symbol
@@ -115,7 +114,7 @@ namespace ERM
TStringConstant string; TStringConstant string;
}; };
typedef boost::variant<TVarConcatString, TStringConstant, TCurriedString, TSemiCompare, TMacroUsage, TMacroDef, TIexp, TVarpExp, boost::spirit::unused_type> TBodyOptionItem; typedef boost::variant<TVarConcatString, TStringConstant, TCurriedString, TSemiCompare, TMacroDef, TIexp, TVarpExp, boost::spirit::unused_type> TBodyOptionItem;
typedef std::vector<TBodyOptionItem> TNormalBodyOptionList; typedef std::vector<TBodyOptionItem> TNormalBodyOptionList;