Skip to content
This repository has been archived by the owner on Oct 9, 2018. It is now read-only.

Commit

Permalink
Basically working boost::exception code, with an array of information…
Browse files Browse the repository at this point in the history
… fields that can be appended to the exception as it travels up the stack
  • Loading branch information
davidcox committed Mar 3, 2011
1 parent 5def898 commit e69f85c
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 79 deletions.
51 changes: 36 additions & 15 deletions Core/ComponentRegistries/ComponentRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ void ComponentRegistry::registerStimulusNode(const std::string &tag_name, shared
// Instance lookups with some extra parsing smarts
shared_ptr<Variable> ComponentRegistry::getVariable(std::string expression){

shared_ptr<Variable> test = variable_cache[expression];
if(test != NULL){
return test;
}
shared_ptr<Variable> test = variable_cache[expression];
if(test != NULL){
return test;
}

// Check to see if it can be resolved, or if it will need to be resolved
// at runtime
Expand Down Expand Up @@ -308,8 +308,12 @@ shared_ptr<Variable> ComponentRegistry::getVariable(std::string expression){

shared_ptr<Variable> var = global_variable_registry->getVariable(strip_match[1]);

// cache/hash the variable for fast access
variable_cache[expression] = var;
if(var == NULL){
throw UnknownVariableException(strip_match[1]);
}

// cache/hash the variable for fast access
variable_cache[expression] = var;

return var;
}
Expand Down Expand Up @@ -344,13 +348,13 @@ shared_ptr<mw::StimulusNode> ComponentRegistry::getStimulus(std::string expressi
// without brackets.

} catch (regex_error& e) {
throw SimpleException("Regex error during stimulus parsing (regex_error exception)", e.what());
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 SimpleException("Regex error during stimulus parsing (not enough matches)");
throw FatalParserException("Regex error during stimulus parsing (not enough matches)");
}

// This the part before any brackets
Expand All @@ -366,7 +370,7 @@ shared_ptr<mw::StimulusNode> ComponentRegistry::getStimulus(std::string expressi
shared_ptr<StimulusGroup> stimulus_group = getObject<StimulusGroup>(stem);

if(stimulus_group == NULL){
throw SimpleException("Unknown stimulus group", stem);
throw FatalParserException("Unknown stimulus group", stem);
}

shared_ptr<StimulusNodeGroup> stimulus_node_group = getObject<StimulusNodeGroup>(stem + ":node");
Expand All @@ -379,8 +383,7 @@ shared_ptr<mw::StimulusNode> ComponentRegistry::getStimulus(std::string expressi
}

if(stimulus_group == NULL){
// TODO: throw?
throw SimpleException("Failed to find stimulus group", stem);
throw FatalParserException("Unknown stimulus group", stem);
}

// This is the stuff inside the outer brackets
Expand Down Expand Up @@ -418,7 +421,7 @@ shared_ptr<mw::StimulusNode> ComponentRegistry::getStimulus(std::string expressi
}

if(indices.size() != stimulus_group->getNDimensions()) {
throw SimpleException("Illegal stimulus dimension reference", stem);
throw FatalParserException("Illegal stimulus dimension reference", stem);
}

for(unsigned int i = 0; i < indices.size(); i++){
Expand All @@ -438,17 +441,35 @@ shared_ptr<mw::StimulusNode> ComponentRegistry::getStimulus(std::string expressi
index_expression = index_pattern;
}

// Parse the expression
shared_ptr<Variable> index = getVariable(index_expression);

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));
index_var));

return refnode;
}
Expand Down
68 changes: 68 additions & 0 deletions Core/Exceptions/Exceptions.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,71 @@
#include "Exceptions.h"
#include "Component.h"
#include <boost/variant/visitor_ptr.hpp>
#include "Stimulus.h"
#include "GenericVariable.h"

using namespace mw;
using namespace boost;

namespace mw{

string to_string_visitor::operator()(shared_ptr<mw::Component> operand) const{
string tag = operand->getTag(); // TODO: try/catch
if(tag.empty()){
tag = "<unknown component>";
}

return tag;
}

string to_string_visitor::operator()(shared_ptr<mw::Stimulus> operand) const{
return this->operator()(dynamic_pointer_cast<mw::Component, mw::Stimulus>(operand) );
}

string to_string_visitor::operator()(shared_ptr<mw::StimulusGroup> operand) const{
return this->operator()(dynamic_pointer_cast<mw::Component, mw::StimulusGroup>(operand) );
}

string to_string_visitor::operator()(shared_ptr<mw::Variable> operand) const{
return this->operator()(dynamic_pointer_cast<mw::Component, mw::Variable>(operand) );
}


#define CHECK_AND_REPORT_STRING_ERROR_INFORMATION(TOKEN, TYPE) \
if( get_error_info< ERROR_INFO_OBJECT(TOKEN) >(e) != NULL ){ \
TYPE TOKEN ## _tmp = *(get_error_info< ERROR_INFO_OBJECT(TOKEN) >(e)); \
merror(e.getDomain(), "\t%s: %s", #TOKEN, TOKEN ## _tmp.c_str()); \
}


#define CHECK_AND_REPORT_ERROR_INFORMATION(TOKEN, TYPE) \
if( get_error_info< ERROR_INFO_OBJECT(TOKEN) >(e) != NULL ){ \
TYPE TOKEN ## _tmp = *(get_error_info< ERROR_INFO_OBJECT(TOKEN) >(e)); \
string result = apply_visitor(to_string_visitor(), TOKEN ## _tmp); \
if(!result.empty()){ \
merror(e.getDomain(), "\t%s: %s", #TOKEN, result.c_str()); \
} \
}


void display_extended_error_information(SimpleException& e){

// Display the primary message
merror(e.getDomain(), e.what());


using namespace mw::error_info_types;

CHECK_AND_REPORT_ERROR_INFORMATION( reason, ErrorString);
CHECK_AND_REPORT_ERROR_INFORMATION( additional_msg, ErrorString);
CHECK_AND_REPORT_ERROR_INFORMATION( object_type, ErrorString);
CHECK_AND_REPORT_ERROR_INFORMATION( parent_scope, ErrorString);
CHECK_AND_REPORT_ERROR_INFORMATION( ref_id, ErrorString);
CHECK_AND_REPORT_ERROR_INFORMATION( parent_component, ComponentOrString );
CHECK_AND_REPORT_ERROR_INFORMATION( child_component, ComponentOrString );
CHECK_AND_REPORT_ERROR_INFORMATION( variable, VariableOrString );
CHECK_AND_REPORT_ERROR_INFORMATION( parser_context, ErrorString );

}

}
97 changes: 91 additions & 6 deletions Core/Exceptions/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,21 @@
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/exception/all.hpp>
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <map>
#include <string>



namespace mw {

// forward decls
class Stimulus;
class Variable;
class StimulusGroup;
class Component;

using namespace std;
using namespace boost;

Expand Down Expand Up @@ -54,11 +66,10 @@ class SimpleException : public std::exception, public boost::exception {
domain = _domain;
}

SimpleException(const SimpleException& e){
domain = e.domain;
message = e.message;
//subject = e.subject;
}
//SimpleException(const SimpleException& e){
// domain = e.domain;
// message = e.message;
// }

virtual ~SimpleException() throw() {}

Expand Down Expand Up @@ -127,25 +138,99 @@ class FatalParserException : public SimpleException {
public:
FatalParserException(string _subject) : SimpleException(M_PARSER_MESSAGE_DOMAIN, _subject){ }

FatalParserException(string _msg, string _subject) : SimpleException(M_PARSER_MESSAGE_DOMAIN, _msg, _subject){ }

FatalParserException() : SimpleException(M_PARSER_MESSAGE_DOMAIN, "A fatal error occurred"){ }

virtual ~FatalParserException() throw(){ }


};


class UnknownExpressionException : public SimpleException {
public:
UnknownExpressionException(string _subject) : SimpleException(M_PARSER_MESSAGE_DOMAIN, "Invalid expression: ", _subject){ }
};

class UnknownVariableException : public SimpleException {
public:
UnknownVariableException(string _subject) : SimpleException(M_PARSER_MESSAGE_DOMAIN, "Invalid variable definition: ", _subject){ }
};



class ComponentFactoryConflictException : public SimpleException{


public:

ComponentFactoryConflictException(string _subject) :
SimpleException(M_PLUGIN_MESSAGE_DOMAIN, "A plugin has attempted to redefine the behavior of an existing XML signature.", _subject){
SimpleException(M_PLUGIN_MESSAGE_DOMAIN, "A plugin has attempted to redefine the behavior of an existing component signature.", _subject){
}

virtual ~ComponentFactoryConflictException() throw() {}
};


// Common error info payloads (can be added to exception objects
// above via operator<<

#define ERROR_INFO_TOKEN(TOKEN) struct TOKEN ## _error_info_token
#define ERROR_INFO_STRING(TOKEN) TOKEN ## _error_info_string
#define ERROR_INFO_OBJECT(TOKEN) TOKEN ## _error_info

#define ERROR_INFO_DECLARATION(TOKEN, TYPE) \
ERROR_INFO_TOKEN(TOKEN); \
typedef error_info< ERROR_INFO_TOKEN(TOKEN), TYPE > ERROR_INFO_OBJECT(TOKEN);


namespace error_info_types{
typedef variant<shared_ptr<Component>, string> ComponentOrString;
typedef variant<shared_ptr<Stimulus>, string> StimulusOrString;
typedef variant<shared_ptr<StimulusGroup>, string> StimulusGroupOrString;
typedef variant<shared_ptr<Variable>, string> VariableOrString;
typedef variant< string > ErrorString;
typedef variant< map<string, string> , string> ComponentAttributeMap;
typedef variant< int, double > ErrorNumber;
}

ERROR_INFO_DECLARATION( parent_component, error_info_types::ComponentOrString );
ERROR_INFO_DECLARATION( child_component, error_info_types::ComponentOrString );
ERROR_INFO_DECLARATION( component, error_info_types::ComponentOrString );
ERROR_INFO_DECLARATION( object_type, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( parent_scope, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( ref_id, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( stimulus, error_info_types::StimulusOrString );
ERROR_INFO_DECLARATION( stimulus_group, error_info_types::StimulusGroupOrString );
ERROR_INFO_DECLARATION( variable, error_info_types::VariableOrString);
ERROR_INFO_DECLARATION( expression, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( subexpression, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( xml_code, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( component_attributes, error_info_types::ComponentAttributeMap );
ERROR_INFO_DECLARATION( line_number, error_info_types::ErrorNumber);
ERROR_INFO_DECLARATION( col_number, error_info_types::ErrorNumber);
ERROR_INFO_DECLARATION( reason, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( additional_msg, error_info_types::ErrorString);
ERROR_INFO_DECLARATION( parser_context, error_info_types::ErrorString);


extern void display_extended_error_information(SimpleException& e);

// A "visitor" class for dealing with the above boost::variant objects
class to_string_visitor : public boost::static_visitor<string> {
public:

string operator()(shared_ptr<mw::Component> operand) const;
string operator()(shared_ptr<mw::Stimulus> operand) const;
string operator()(shared_ptr<mw::StimulusGroup> operand) const;
string operator()(shared_ptr<mw::Variable> operand) const;
string operator()(string operand) const {
string return_string = operand;
return return_string;
}
};

}

#endif
Expand Down
26 changes: 12 additions & 14 deletions Core/ExperimentDataLoading/LoadingUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,7 @@ namespace mw {
global_outgoing_event_buffer->putEvent(SystemEventFactory::currentExperimentState());
return false;
}

// This is getting double loaded
/* try {
loadSetupVariables();
} catch(std::exception& e){
merror(M_PARSER_MESSAGE_DOMAIN, "Failed to load setup variables. Specific problems was: \"%s\"", e.what());
GlobalCurrentExperiment = shared_ptr<Experiment>();
global_outgoing_event_buffer->putEvent(SystemEventFactory::currentExperimentState());
return false;
}*/


shared_ptr<ComponentRegistry> reg = ComponentRegistry::getSharedRegistry();

try {
Expand All @@ -152,12 +142,20 @@ namespace mw {
parser.validate();
parser.parse(true);

} catch(std::exception& e){
merror(M_PARSER_MESSAGE_DOMAIN, e.what());
} catch(SimpleException& e){
// This is the "main" catch block for parsing
display_extended_error_information(e);
GlobalCurrentExperiment = shared_ptr<Experiment>();
global_outgoing_event_buffer->putEvent(SystemEventFactory::currentExperimentState());
return false;
}
} catch(std::exception& e){
merror(M_PARSER_MESSAGE_DOMAIN,
"An unanticipated error occurred. This is probably a bug. Error message was: %s",
e.what());
GlobalCurrentExperiment = shared_ptr<Experiment>();
global_outgoing_event_buffer->putEvent(SystemEventFactory::currentExperimentState());
return false;
}

if(GlobalCurrentExperiment == NULL) {
merror(M_PARSER_MESSAGE_DOMAIN, "Experiment load failed");
Expand Down
7 changes: 3 additions & 4 deletions Core/Variables/ExpressionVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ class ParsedExpressionVariable : public Variable {

} catch (stx::UnknownSymbolException &e){

merror(M_PARADIGM_MESSAGE_DOMAIN, "unknown symbol exception");
//std::cout << "UnknownSymbolException: " << e.what() << "\n";
//return Datum(0L);
throw(e);
FatalParserException f("Unknown symbol while parsing expression");


} catch (stx::ExpressionParserException &e){
merror(M_PARADIGM_MESSAGE_DOMAIN, "expression parser exception");
//std::cout << "ExpressionParserException: " << e.what() << "\n";
Expand Down
Loading

0 comments on commit e69f85c

Please sign in to comment.