From 6014edb7eaa153fce5cf137e590788f005b87c9f Mon Sep 17 00:00:00 2001 From: mateuszb Date: Mon, 16 May 2011 12:11:00 +0000 Subject: [PATCH] * minor improvements in parser/interpreter --- lib/ERMInterpreter.cpp | 115 +++++++++++++++++++++++++++++------------ lib/ERMInterpreter.h | 20 ++++--- lib/ERMParser.cpp | 6 +-- lib/ERMParser.h | 5 +- 4 files changed, 99 insertions(+), 47 deletions(-) diff --git a/lib/ERMInterpreter.cpp b/lib/ERMInterpreter.cpp index fd6203497..63c4404f9 100644 --- a/lib/ERMInterpreter.cpp +++ b/lib/ERMInterpreter.cpp @@ -568,8 +568,6 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const ///////// //code execution -struct VRPerformer; - template 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 { explicit VR_SPerformer(VRPerformer & _owner); using StandardBodyOptionItemVisitor::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 +{ + explicit OB_UPerformer(OBPerformer & owner) : StandardBodyOptionItemVisitor(owner) + {} + using StandardBodyOptionItemVisitor::operator(); + + virtual void operator()(TIexp const& cmp) const; + virtual void operator()(TVarpExp const& cmp) const; +}; + struct OBPerformer : StandardReceiverVisitor { OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos) @@ -807,7 +812,7 @@ struct OBPerformer : StandardReceiverVisitor //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 break; case 'U': //sgc of obj subtype { - //TODO + if(trig.params.size() == 1) + boost::apply_visitor(OB_UPerformer(const_cast(*this)), trig.params[0]); + else + throw EScriptExecError("OB:U takes exactly one parameter!"); } break; default: @@ -834,6 +842,15 @@ struct OBPerformer : StandardReceiverVisitor } }; +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(this), IexpDisemboweler::GET), tid.var); +} + void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector &funParams/*=std::vector()*/ ) { struct HLP diff --git a/lib/ERMInterpreter.h b/lib/ERMInterpreter.h index 5d31934f1..44eb7ed3a 100644 --- a/lib/ERMInterpreter.h +++ b/lib/ERMInterpreter.h @@ -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 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 initVal) const; + + public: typedef std::map< int, std::vector > TIDPattern; void executeInstructions(); //called when starting a new game, before most of the map settings are done diff --git a/lib/ERMParser.cpp b/lib/ERMParser.cpp index bd8a7d2ff..cff828b57 100644 --- a/lib/ERMParser.cpp +++ b/lib/ERMParser.cpp @@ -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; diff --git a/lib/ERMParser.h b/lib/ERMParser.h index 422e786fc..68affc9e3 100644 --- a/lib/ERMParser.h +++ b/lib/ERMParser.h @@ -72,8 +72,7 @@ namespace ERM //write-only variable expression struct TVarpExp { - typedef boost::variant 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 TBodyOptionItem; + typedef boost::variant TBodyOptionItem; typedef std::vector TNormalBodyOptionList;