Datum ComponentRegistry::getNumber(std::string expression, GenericDataType type){ Datum value; switch(type){ case M_FLOAT: case M_INTEGER: case M_BOOLEAN: case M_STRING: value = getValue(expression, type); if (value.getDataType() == type) { return value; } break; default: throw FatalParserException("Attempt to cast a number of invalid type"); } switch (type){ case M_FLOAT: return Datum(value.getFloat()); case M_INTEGER: return Datum(value.getInteger()); case M_STRING: return Datum(value.getString()); case M_BOOLEAN: return Datum(value.getBool()); default: return value; } }
Datum ComponentRegistry::getValue(std::string expression, GenericDataType type) { std::pair<std::string, GenericDataType> cacheKey(expression, type); shared_ptr<Datum> test = data_cache[cacheKey]; if(test != NULL){ return *test; } double doubleValue; long longValue; bool boolValue; Datum value; try { switch(type){ case M_FLOAT: case M_INTEGER: case M_BOOLEAN: doubleValue = boost::lexical_cast<double>(expression); if (M_FLOAT == type) { value = Datum(doubleValue); } else if (M_INTEGER == type) { longValue = (long)doubleValue; if ((double)longValue != doubleValue) { throw NonFatalParserException("invalid integer literal", expression.c_str()); } value = Datum(longValue); } else { boolValue = (bool)doubleValue; if ((double)boolValue != doubleValue) { throw NonFatalParserException("invalid boolean literal", expression.c_str()); } value = Datum(boolValue); } break; case M_STRING: value = Datum(string(expression)); break; default: // No lexical_cast for other types break; } if (!value.isUndefined()) { data_cache[cacheKey] = shared_ptr<Datum>(new Datum(value)); return value; } } catch (NonFatalParserException& e){ // Until we work out how to effectively flag these issues, treat them as fatal errors throw FatalParserException(e.what()); } catch (boost::bad_lexical_cast& e){ // no biggie, we can do this the hard(er) way } return Datum(ParsedExpressionVariable::evaluateExpression(expression)); }
BEGIN_NAMESPACE_MW FreezableVariableContainer::FreezableVariableContainer(shared_ptr<Variable> _var){ frozen = false; variable = _var; if(variable == NULL){ // TODO: make a better exception here; this is only effective for debugging as stands throw FatalParserException("Registering an empty variable within a FreezableVariableContainer " "(is there an empty variable passed into a Stimulus object?)"); } }
shared_ptr<mw::StimulusNode> ComponentRegistry::getStimulus(std::string expression){ // regex for parsing the stimulus string boost::regex stimulus_regex("(.+?)(\\[(.+)\\])?"); boost::smatch matches; try{ regex_match(expression, matches, stimulus_regex); // matches[0] contains the whole string // matches[1] contains the stimulus "stem" // matches[2] contains the index expression (if there is one), // including brackets. // matches[3] contains the index expression (if there is one), // without brackets. } catch (boost::regex_error& e) { throw FatalParserException("Regex error during stimulus parsing (regex_error exception)", e.what()); } // Something is wrong if there aren't at least two strings in matches if(matches.size() == 1){ // TODO: throw throw FatalParserException("Regex error during stimulus parsing (not enough matches)"); } // This the part before any brackets std::string stem = matches[1]; std::string remainder = matches[2]; if(remainder.empty()){ return getStimulusNode(stem); } // If we're still going, from this point forward, the stem refers to a // stimulus group shared_ptr<StimulusGroup> stimulus_group = getObject<StimulusGroup>(stem); if(stimulus_group == NULL){ throw FatalParserException("Unknown stimulus group", stem); } shared_ptr<StimulusNodeGroup> stimulus_node_group = getObject<StimulusNodeGroup>(stem + ":node"); if(stimulus_node_group == NULL){ stimulus_node_group = shared_ptr<StimulusNodeGroup>(new StimulusNodeGroup(stimulus_group)); shared_ptr<mw::Component> newStimulusNodeGroup = boost::dynamic_pointer_cast<mw::Component, StimulusNodeGroup>(stimulus_node_group); registerObject(stem + ":node", newStimulusNodeGroup); } if(stimulus_group == NULL){ throw FatalParserException("Unknown stimulus group", stem); } // This is the stuff inside the outer brackets std::string index_pattern = matches[3]; // This is where we are going to put the string when we are done with it std::string index_expression; // A regex to determine if the stimulus is multidimensional, e.g. stim[1][2] boost::regex multi_dimensional_group_regex(".+\\]\\s*\\[.+"); if( regex_match(index_pattern, multi_dimensional_group_regex) ){ // If it's multidimensional, we need to split up the contents of the // outer brackets and multiply/add them into a c-style multidimensional // array index. // We're going to use this string stream for syntactic convenience in // concatenating things together. std::ostringstream index_expression_stream; index_expression_stream << "0"; // get things started boost::regex index_regex("\\]\\s*\\["); // split the index strings boost::sregex_token_iterator i_t(index_pattern.begin(), index_pattern.end(), index_regex, -1); boost::sregex_token_iterator j_t; vector<string> indices; while(i_t != j_t){ indices.push_back(*i_t++); } if(indices.size() != stimulus_group->getNDimensions()) { throw FatalParserException("Illegal stimulus dimension reference", stem); } for(unsigned int i = 0; i < indices.size(); i++){ index_expression_stream << "+((" << boost::algorithm::trim_copy(indices.at(i)) << ")"; for(unsigned int j = i + 1; j < indices.size(); j++){ index_expression_stream << "*("; index_expression_stream << stimulus_group->dimensionSize(j); index_expression_stream << ")"; } index_expression_stream << ")"; } index_expression = index_expression_stream.str(); } else { // if not multi-dimensional, the work is easier index_expression = index_pattern; } if(index_expression.empty()){ FatalParserException f("Empty expression indexing stimulus group"); f << stimulus_group_error_info(stimulus_group); throw f; } shared_ptr<Variable> index_var; // Parse the index expression try { index_var = getVariable(index_expression); } catch(UnknownExpressionException& e){ FatalParserException f("Invalid index to stimulus group"); f << expression_error_info(index_expression.c_str()); throw f; } // Create a "node group" to go with the stimulus group //shared_ptr<StimulusNodeGroup> // stimulus_node_group(new StimulusNodeGroup(stimulus_group)); // Create the relevant reference shared_ptr<StimulusGroupReferenceNode> refnode(new StimulusGroupReferenceNode(stimulus_node_group, index_var)); return refnode; }