1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +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
struct VRPerformer;
template<typename OwnerType>
struct StandardBodyOptionItemVisitor : boost::static_visitor<>
{
@ -592,10 +590,10 @@ struct StandardBodyOptionItemVisitor : boost::static_visitor<>
{
throw EScriptExecError("Semi comparison not allowed in this receiver");
}
virtual void operator()(TMacroUsage const& cmp) const
{
throw EScriptExecError("Macro usage not allowed in this receiver");
}
// virtual void operator()(TMacroUsage const& cmp) const
// {
// throw EScriptExecError("Macro usage not allowed in this receiver");
// }
virtual void operator()(TMacroDef const& cmp) const
{
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;
};
struct VRPerformer;
struct VR_SPerformer : StandardBodyOptionItemVisitor<VRPerformer>
{
explicit VR_SPerformer(VRPerformer & _owner);
using StandardBodyOptionItemVisitor<VRPerformer>::operator();
void operator()(TStringConstant const& cmp) const OVERRIDE;
void operator()(TMacroUsage 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);
}
void VR_SPerformer::operator()(TMacroUsage const& cmp) const
{
owner.identifier.setTo(owner.interp->getIexp(cmp));
}
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>
{
OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos)
@ -807,7 +812,7 @@ struct OBPerformer : StandardReceiverVisitor<int3>
//TODO
}
break;
case 'R': //eable all gamers to use object
case 'R': //enable all gamers to use object
{
//TODO
}
@ -824,7 +829,10 @@ struct OBPerformer : StandardReceiverVisitor<int3>
break;
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;
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<>
{
@ -850,6 +867,39 @@ struct ERMExpDispatch : boost::static_visitor<>
}
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")
{
//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")
{
int3 objPos;
if(trig.identifier.is_initialized())
{
ERM::Tidentifier tid = trig.identifier.get();
switch(tid.size())
{
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;
}
objPos = HLP(owner).getPosFromIdentifier(tid, false);
//execute body
if(trig.body.is_initialized())
{
@ -954,7 +998,7 @@ struct ERMExpDispatch : boost::static_visitor<>
}
else
{
//unsupported or invalid trigger
//not supported or invalid trigger
}
}
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!");
}
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>()*/ )
{
struct HLP

View File

@ -471,14 +471,15 @@ public:
class ERMInterpreter
{
friend class ScriptScanner;
friend class TriggerIdMatchHelper;
friend class TriggerIdentifierMatch;
friend class ConditionDisemboweler;
friend struct LVL2IexpDisemboweler;
friend struct VR_SPerformer;
friend struct ERMExpDispatch;
friend struct VRPerformer;
/*not so*/ public:
// friend class ScriptScanner;
// friend class TriggerIdMatchHelper;
// friend class TriggerIdentifierMatch;
// friend class ConditionDisemboweler;
// friend struct LVL2IexpDisemboweler;
// friend struct VR_SPerformer;
// friend struct ERMExpDispatch;
// friend struct VRPerformer;
std::vector<VERMInterpreter::FileInfo*> files;
std::vector< VERMInterpreter::FileInfo* > fileInfos;
@ -500,6 +501,7 @@ class ERMInterpreter
IexpValStr getIexp(const ERM::TIexp & iexp) const;
IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
IexpValStr getIexp(const ERM::TVarpExp & tid) const;
static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
@ -509,6 +511,8 @@ class ERMInterpreter
static bool isATrigger(const ERM::TLine & line);
static ERM::EVOtions getExpType(const ERM::TVOption & opt);
IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
public:
typedef std::map< int, std::vector<int> > TIDPattern;
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(
ERM::TVarpExp,
(ERM::TVarpExp::Tvartype, var)
(ERM::TVarExp, var)
)
BOOST_FUSION_ADAPT_STRUCT(
@ -355,7 +355,7 @@ namespace ERM
/*qERMMacroUsage %= qi::lexeme[qi::lit("?$") >> *(qi::char_ - '$') >> qi::lit('$')];*/
varExp %= varExpNotMacro | ERMmacroUsage;
iexp %= varExp | qi::int_;
varp %= qi::lit("?") >> (varExpNotMacro | ERMmacroUsage);
varp %= qi::lit("?") >> varExp;
comment %= *qi::char_;
commentLine %= (~qi::char_("!") >> comment | (qi::char_('!') >> (~qi::char_("?!$#[")) >> comment ));
cmdName %= qi::lexeme[qi::repeat(2)[qi::char_]];
@ -373,7 +373,7 @@ namespace ERM
semiCompare %= +qi::char_("<=>") >> iexp;
curStr %= iexp >> 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("/"));
normalBodyOption = qi::char_("A-Z+") > exactBodyOptionList;
bodyOption %= VRLogic | VRarithmetic | normalBodyOption;

View File

@ -72,8 +72,7 @@ namespace ERM
//write-only variable expression
struct TVarpExp
{
typedef boost::variant<TVarExpNotMacro, TMacroUsage> Tvartype;
Tvartype var;
TVarExp var;
};
//i-expression (identifier expression) - an integral constant, variable symbol or array symbol
@ -115,7 +114,7 @@ namespace ERM
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;