#ifndef PARSERGRAMMAR_HH_ #define PARSERGRAMMAR_HH_ #include #include #include "ExpressionContainer.hh" #include "CustomFoldDirective.hh" #include "ParserToolbox.hh" #include "Properties.hh" #include "FunctionInfo.hh" namespace AMDA { namespace parser { namespace qi = boost::spirit::qi; using namespace qi; using namespace Expression; #define PARSERGRAMMAR_ADD_OPERATOR(operation, next, operator) fold(next.alias())[operator >> next] template class ParserGrammar : public qi::grammar { public: ParserGrammar(AMDA::helpers::Properties& lProperties) : ParserGrammar::base_type(expr_) { expr_ = equal_.alias(); equal_ = PARSERGRAMMAR_ADD_OPERATOR(EqualOperation, unequal_, equalOperator_); unequal_ = PARSERGRAMMAR_ADD_OPERATOR(UnequalOperation, greaterOrEqual_, unequalOperator_); greaterOrEqual_ = PARSERGRAMMAR_ADD_OPERATOR(GreaterOrEqualOperation, lowerOrEqual_, greaterOrEqualOperator_); lowerOrEqual_ = PARSERGRAMMAR_ADD_OPERATOR(LowerOrEqualOperation, greater_, lowerOrEqualOperator_); greater_ = PARSERGRAMMAR_ADD_OPERATOR(GreaterOperation, lower_, greaterOperator_); lower_ = PARSERGRAMMAR_ADD_OPERATOR(LowerOperation, or_, lowerOperator_); or_ = PARSERGRAMMAR_ADD_OPERATOR(OrOperation, sum_, orOperator_); sum_ = PARSERGRAMMAR_ADD_OPERATOR(SumOperation, difference_, sumOperator_); difference_ = PARSERGRAMMAR_ADD_OPERATOR(DifferenceOperation, and_, differenceOperator_); and_ = PARSERGRAMMAR_ADD_OPERATOR(AndOperation, factor_, andOperator_); factor_ = PARSERGRAMMAR_ADD_OPERATOR(FactorOperation, division_, factorOperator_); division_ = PARSERGRAMMAR_ADD_OPERATOR(DivisionOperation, powerTen_, divisionOperator_); powerTen_ = PARSERGRAMMAR_ADD_OPERATOR(PowerTenOperation, powerTenD_, powerTenOperator_); powerTenD_ = PARSERGRAMMAR_ADD_OPERATOR(PowerTenDOperation, pow_, powerTenDOperator_); pow_ = PARSERGRAMMAR_ADD_OPERATOR(PowerOperation, plusSign_, powOperator_); plusSign_ = ((sumOperator_ >>-*sumOperator_)> minusSign_ ) [_val = boost::phoenix::construct(_1)] || ((differenceOperator_ >>differenceOperator_)> minusSign_ ) [_val = boost::phoenix::construct(_1)] |minusSign_ [_val = _1]; minusSign_ = (((-*sumOperator_>>differenceOperator_ >>-*sumOperator_) ) > not_) [_val = boost::phoenix::construct(_1)] | not_[_val = _1]; not_ = (notOperator_ > functions_) [_val = boost::phoenix::construct(_1)] | functions_[_val = _1]; functions_ = (fourArgsFunction>>"(">>funArgs_>>argumentSeparator_>>funArgs_>>argumentSeparator_>>funArgs_>>argumentSeparator_>>funArgs_>>")")[_val= boost::phoenix::construct(_1,_2,_3,_4,_5)] || (threeArgsFunction>>"(">>funArgs_>>argumentSeparator_>>funArgs_>>argumentSeparator_>>funArgs_>>")")[_val= boost::phoenix::construct(_1,_2,_3,_4)] || (twoArgsFunction>>"(">>funArgs_>>argumentSeparator_>>funArgs_>>")")[_val= boost::phoenix::construct(_1,_2,_3)]|| (oneArgsFunction>>"(">>funArgs_>>")")[_val= boost::phoenix::construct(_1,_2)]|const_[_val=_1]; // UNARY OPERATIONS const_ = (definedConstants) [_val = boost::phoenix::construct(_1)] | param_[_val = _1]; param_= ((localParams_ | derivedParam_ | uploadedParam_ | impexParam_ | themisParam_ | cdaWebParam_ | templatedParam_) >>('(' >> componentValue_ >> componentSeparator_ >> componentValue_ >>')'))[_val=boost::phoenix::construct(_1,_2,_3)] || ((localParams_ | derivedParam_ | uploadedParam_ | impexParam_ | themisParam_ | cdaWebParam_ | templatedParam_) >>('(' >> componentValue_ >> ')'))[_val=boost::phoenix::construct(_1,_2)] || ((localParams_ | derivedParam_ | uploadedParam_ | impexParam_ | themisParam_ | cdaWebParam_ | templatedParam_))[_val=boost::phoenix::construct(_1)] | simple[_val = _1]; funArgs_=((expr_ |var_ | definedArgsListValues) |functions_); simple = (('(' > expr_ > ')') | var_); var_ = (+qi::char_('0','9') >> -qi::char_('.') >> -(+qi::char_('0','9'))) | ((qi::char_('.') >> +qi::char_('0','9'))); componentValue_ = (+qi::char_('0','9') | qi::char_('*') | (qi::string("range[") >> var_ >> qi::char_(',') >> var_ >> qi::string("]")) | (qi::string("indexes[") >> indexValue_ >> qi::char_(',') >> indexValue_ >> qi::string("]"))); indexValue_ = +qi::char_('0','9'); derivedParam_ = (qi::string("ws_") >> +(qi::alnum | qi::char_('_'))); uploadedParam_ = (qi::string("wsd_") >> +(qi::alnum | qi::char_('_'))); impexParam_ = (qi::string("spase___IMPEX_") >> +(qi::alnum | qi::char_('_'))); themisParam_ = (qi::string("th") >> qi::char_('a','e') >> qi::char_('_') >> +(qi::alnum | qi::char_('_'))); cdaWebParam_ = (qi::string("cdaweb_") >> +(qi::alnum | qi::char_('_'))); powOperator_ = qi::char_('^'); powerTenOperator_ = qi::char_('e'); powerTenDOperator_ = qi::char_('d'); notOperator_ = qi::char_('!'); andOperator_ = qi::string("&"); orOperator_ = qi::string("|"); equalOperator_ = qi::string("="); unequalOperator_ = qi::string("!="); sumOperator_ = qi::char_('+'); differenceOperator_ = qi::char_('-'); factorOperator_ = qi::char_("*"); divisionOperator_ = qi::char_("/"); greaterOperator_ = qi::char_(">"); greaterOrEqualOperator_ = qi::string(">="); lowerOrEqualOperator_ = qi::string("<="); lowerOperator_ = qi::char_("<"); argumentSeparator_ = qi::char_(","); componentSeparator_ = qi::char_(","); // Define available constants std::map existingConstants = ParserToolbox::getConstants(lProperties); for(std::map::iterator it = existingConstants.begin(); it != existingConstants.end(); ++it) { definedConstants.add (it->first, it->second); } // Define available local params std::vector existingParams = ParserToolbox::getParameters(lProperties); const char *otherPatterns[5] = { "ws_", "wsd", "spase___IMPEX_", "th", "cdaweb_"}; for(std::vector::iterator it = existingParams.begin(); it != existingParams.end(); ++it) { bool isLocal = true; for (auto patt : otherPatterns){ if (it->rfind(patt, 0) == 0) isLocal = false; } if(isLocal) localParams_.add(*it,*it); } // Defined functions available std::map existingFunctions = ParserToolbox::getFunctions(lProperties); for(auto const& x : existingFunctions ) { int nbAllArgs = x.second.getNbArgs() + x.second.getNbPromptedArgs(); if (nbAllArgs == 1) { oneArgsFunction.add(x.second.getIHMName(), x.second.getKernelName()); }else if (nbAllArgs == 2) { twoArgsFunction.add(x.second.getIHMName(), x.second.getKernelName()); }else if (nbAllArgs == 3) { threeArgsFunction.add(x.second.getIHMName(), x.second.getKernelName()); }else if (nbAllArgs == 4) { fourArgsFunction.add(x.second.getIHMName(), x.second.getKernelName()); } } // Defined available values for functions args list std::map existingArgsLists = ParserToolbox::getArgsLists(lProperties); for(auto const& x : existingArgsLists ) { for(auto const& y : x.second.getValues()) { definedArgsListValues.add(y.first,y.first); } } // Defined templated parameters TemplateParamsList existingTemplateParams = ParserToolbox::getTemplateParams(lProperties); templatedParam_ = (qi::string("fakeparam")); for(auto const& t : existingTemplateParams ) { templatedParam_ = (templatedParam_.copy() | (qi::string(t.getParamId()) >> +(qi::alnum | qi::char_('_'))));; } BOOST_SPIRIT_DEBUG_NODES((expr_)(or_)(and_)(equal_)(unequal_)(greaterOrEqual_)(lowerOrEqual_)(lower_)(sum_) (difference_)(factor_)(division_)(simple)(notOperator_)(andOperator_)(orOperator_)(equalOperator_)(unequalOperator_) (sumOperator_)(differenceOperator_)(factorOperator_)(divisionOperator_)(greater_)(lower_)(functions_)); } private: qi::rule var_, componentValue_, indexValue_, derivedParam_, uploadedParam_, impexParam_, themisParam_, cdaWebParam_, templatedParam_; qi::rule not_ , pow_ , powerTen_ , powerTenD_ , and_ , or_ , equal_ , unequal_ , sum_ , difference_ , factor_ , division_ , simple , expr_ ,plusSign_ ,minusSign_ ,greater_ ,greaterOrEqual_ ,lowerOrEqual_ ,lower_ ,const_ ,frame_ ,param_ ,functions_ ,funArgs_; qi::rule notOperator_ , powOperator_ , powerTenOperator_ , powerTenDOperator_ , andOperator_ , orOperator_ , equalOperator_ , unequalOperator_ , sumOperator_ , differenceOperator_ , factorOperator_ , divisionOperator_ , greaterOperator_ , greaterOrEqualOperator_ , lowerOrEqualOperator_ , lowerOperator_ , argumentSeparator_ , componentSeparator_; qi::symbols definedConstants; qi::symbols definedArgsListValues; qi::symbols localParams_; qi::symbols twoArgsFunction; qi::symbols oneArgsFunction; qi::symbols threeArgsFunction; qi::symbols fourArgsFunction; }; } } #endif