#ifndef EXPRESSIONPRINTER_HH_ #define EXPRESSIONPRINTER_HH_ #include "ExpressionContainer.hh" #include //#define ADD_DEBUG_TAG namespace AMDA { namespace parser { namespace Expression { class ExpressionPrinter : public boost::static_visitor { public: ExpressionPrinter(std::ostream& os) : _os(os) {} std::ostream& _os; void operator()(const var& v) const { #ifdef ADD_DEBUG_TAG _os << "@VAR@"; #endif _os << v; } void operator()(const BinaryOperation& b) const { #ifdef ADD_DEBUG_TAG _os << "@BINOP@"; #endif _os << "("; boost::apply_visitor(*this, b.l); _os << b.op.kernelSymbol; boost::apply_visitor(*this, b.r); _os << ")"; } void operator()(const UnaryOperation& u) const{ #ifdef ADD_DEBUG_TAG _os << "@UNOP@"; #endif _os << u.op.kernelSymbol; boost::apply_visitor(*this, u.e); } void operator()(const PowerOperation& p) const{ #ifdef ADD_DEBUG_TAG _os << "@POWER@"; #endif _os << "pow("; boost::apply_visitor(*this, p.l); _os << ","; boost::apply_visitor(*this, p.r); _os << ")"; } void operator()(const FunctionOperation& f) const{ #ifdef ADD_DEBUG_TAG _os << "@FUNC@"; #endif _os << f.func << "("; bool isProcess = (!f.func.empty() && (f.func[0] == '#')); for (unsigned int i = 0; i < f.args.size(); ++i) { if (i != 0) { _os << (isProcess ? ";" : ","); } boost::apply_visitor(*this, f.args[i]); } _os << ")"; } void operator()(const ParameterDef& p) const{ #ifdef ADD_DEBUG_TAG _os << "@PARAM@"; #endif if ( p.components.empty() || ((p.components.size() == 1) && (p.components[0].type == ParameterDef::ComponentType::CT_ALL)) || ((p.components.size() == 2) && (p.components[0].type == ParameterDef::ComponentType::CT_ALL) && (p.components[1].type == ParameterDef::ComponentType::CT_ALL))) { // All components _os << printParam(p.param); } else if ((p.components.size() == 1) || ((p.components.size() == 2) && (p.components[1].type == ParameterDef::ComponentType::CT_ALL))) { //only first component defined switch (p.components[0].type) { case ParameterDef::ComponentType::CT_INDEX: _os << printParam(p.param); _os << printComponentIndex(p.components[0].index); break; case ParameterDef::CT_RANGE_VALUES: case ParameterDef::CT_RANGE_INDEXES: { std::stringstream ss; ss << printParam(p.param); _os << printSumIntoTable(p.components[0].type, ss.str(), 0, p.components[0].min, p.components[0].max); break; } default: //Unknown case => return parameter _os << printParam(p.param); } } else if ((p.components.size() == 2) && (p.components[0].type == ParameterDef::ComponentType::CT_ALL)) { //only second component defined switch (p.components[1].type) { case ParameterDef::ComponentType::CT_INDEX: { _os << printParamColumn(p.param, p.components[1].index); break; } case ParameterDef::CT_RANGE_VALUES: case ParameterDef::CT_RANGE_INDEXES: { std::stringstream ss; ss << printParam(p.param); _os << printSumIntoTable(p.components[1].type, ss.str(), 1, p.components[1].min, p.components[1].max); } break; default: //Unknown case => return parameter _os << printParam(p.param); } } else { //two components defined switch (p.components[0].type) { case ParameterDef::ComponentType::CT_INDEX: { switch (p.components[1].type) { case ParameterDef::ComponentType::CT_INDEX: _os << printParam(p.param); _os << printComponentIndex(p.components[0].index); _os << printComponentIndex(p.components[1].index); break; case ParameterDef::CT_RANGE_VALUES: case ParameterDef::CT_RANGE_INDEXES: { std::stringstream ss; ss << printParam(p.param); ss << printComponentIndex(p.components[0].index); _os << printSumIntoTable(p.components[1].type, ss.str(), 0, p.components[1].min, p.components[1].max); } break; default: //Unknown case => return parameter _os << printParam(p.param); } } break; case ParameterDef::CT_RANGE_VALUES: case ParameterDef::CT_RANGE_INDEXES: { switch (p.components[1].type) { case ParameterDef::ComponentType::CT_INDEX: { std::stringstream ss; ss << printParamColumn(p.param,p.components[1].index); _os << printSumIntoTable(p.components[0].type, ss.str(), 0, p.components[0].min, p.components[0].max); } break; case ParameterDef::CT_RANGE_VALUES: case ParameterDef::CT_RANGE_INDEXES: if (p.components[0].type != p.components[1].type) { //Cannot mix range values and range indexes => return parameter _os << printParam(p.param); } else { std::stringstream ss; ss << printParam(p.param); _os << printSumIntoTable(p.components[0].type, ss.str(), 0, p.components[0].min, p.components[0].max, p.components[1].min, p.components[1].max); } break; default: //Unknown case => return parameter _os << printParam(p.param); } } break; default: //Unknown case => return parameter _os << printParam(p.param); } } } private: std::string printParam(std::string name) const { std::stringstream ss; ss << "$"; ss << name; return ss.str(); } std::string printParamColumn(std::string name, int col) const { std::stringstream ss; ss << "("; ss << printParam(name); ss << ").getColumn("; ss << col; ss << ")"; return ss.str(); } std::string printComponentIndex(int index) const { std::stringstream ss; ss << "["; ss << index; ss << "]"; return ss.str(); } std::string printSumIntoTable(ParameterDef::ComponentType type, std::string expression, int relatedDim1, float min, float max, float min2 = NAN, float max2 = NAN) const { std::stringstream ss; bool forceInt = false; if (type == ParameterDef::ComponentType::CT_RANGE_INDEXES) { ss << "#sum_into_table_indexes"; forceInt = true; } else { ss << "#sum_into_table_range"; } ss << "("; ss << expression; ss << ";"; ss << relatedDim1; ss << ";"; ss << (forceInt ? (int)min : min); ss << ";"; ss << (forceInt ? (int)max : max); if (!std::isnan(min2) && !std::isnan(max2)) { ss << ";"; ss << (forceInt ? (int)min2 : min2); ss << ";"; ss << (forceInt ? (int)max2 : max2); } ss << ")"; return ss.str(); } }; std::ostream& operator<<(std::ostream& os, const ExpressionContainer& e) { boost::apply_visitor(ExpressionPrinter(os), e); return os; } } /* namespace Expression */ } /* namespace parser */ } /* namespace AMDA */ #endif