📄 from_xmpl.cpp
字号:
break; // pit points to the last iterator smaller than prop
}
pit = it;
++it;
}
// if we reached it==end, pit is last(), so this works in either case
clause_props.insert(pit, prop);
nclause_props++;
}
bool from_xmpl::clause_eq_clause_props(const L2rClause *cls) {
// See if the clause matches.
// Clauses are in increasing order, so we can check in linear time.
unsigned cp_size = nclause_props;
if(cp_size != cls->nprops()) return false;
// for each element in clause_props, make sure it's in cls->props_
unsigned i=0;
Slist<L2rProposition*>::iterator pit=clause_props.begin();
for( ; i < cp_size ; ++pit, ++i) {
if(*pit != cls->prop(i))
return false;
}
return true;
}
L2rClause *from_xmpl::find_or_create_clause() {
// in case we get <clause/> which we actually do
if(nclause_props==0) return 0;
// foreach clause
for(clausesIT it = clauses_.begin(); it != clauses_.end(); ++it) {
L2rClause *cls = *it;
// if we find a match, use it
if(clause_eq_clause_props(cls))
return cls;
}
// if we get here, then the clause represented by clause_props
// doesn't match any clause in clauses_
L2rClause *cls = new dbg_L2rClause(component_name, nclauses_++,
nclause_props,
list_to_array(clause_props),
false);
clauses_.push_front(cls);
verbose(cls->toOStream_long(_STD_ cout));
return cls;
}
/***************************************************************************
Callback functions
***************************************************************************/
// All variables are attributes.
void from_xmpl::start_attribute(const MBA_string& name, const MBA_string& type) {
MBA_string full_name = component_name + "." + name;
dbg_L2rEnumeration *en = find_enum(type);
L2rVariable *newvar = create_variable(en, full_name);
if(name == "mode") {
modevar_ = newvar;
modevar_->setKind(vk_mode);
}
}
// Note a variable is in fact commandable.
// Commandable variables must have the noCommand value in their domain.
// In fact, it must be index 0 (which is ensured by the code that makes the
// enumerations).
void from_xmpl::start_cmd(const MBA_string& varname) {
L2rVariable *var = find_variable(varname);
L2_assert(var->type()->hasDebug(), L2_fatal_error,
("Enumeration of variable "+varname+
" has no debugging information"));
const dbg_L2rEnumeration *en =
static_cast<const dbg_L2rEnumeration*>(var->type());
L2_assert(en->name(0) == noCommand, L2_parse_model_error,
("Enumeration "+ en->name() + " of commandable variable "+varname+
"\nshould have the `noCommand' value"));
var->setKind(vk_commanded);
}
// Note a variable is in fact observable.
void from_xmpl::start_obs(const MBA_string& varname) {
L2rVariable *var = find_variable(varname);
var->setKind(vk_observed);
}
// Initial value for a variable.
void from_xmpl::start_assign(const MBA_string& prop) {
// split the proposition
int eq_index = prop.find("=");
L2_assert(eq_index != MBA_string::npos, L2_parse_model_error,
("no '=' parsing assign "));
MBA_string varname(prop.c_str(), eq_index);
MBA_string valuename(prop.c_str()+eq_index+1); // skip the =
// find the internal representation
L2rVariable *var = find_variable(varname);
int value = find_enum_member(var->type(), valuename);
var->setInitial(value);
}
// An enumeration; the values are space-separated.
void from_xmpl::start_attributetype(const MBA_string& name, const MBA_string& values) {
// extract a list of strings from the single values string
Slist<MBA_string> memnames;
for(unsigned i=0; i<values.size(); /* iteration is done inside */ ) {
// skip a word
unsigned j;
for(j=i; j<values.size() && values[j]!=' '; j++) ;
memnames.push_back(MBA_string(values.c_str()+i, j-i));
i=j;
// skip whitespace
for( ; i<values.size() && values[i]==' '; i++) ;
}
create_enum(name, memnames);
}
// Start a new component; we just store the name to prepend it.
void from_xmpl::start_component(const MBA_string& name) {
component_name = name;
}
// We need to know we're parsing a clause.
void from_xmpl::start_clause() {
parsing_clause = true;
}
// We need to know we're parsing a prop.
void from_xmpl::start_prop() {
parsing_prop = true;
}
// Currently we only handle a single state (eg mode) variable and it
// must be called mode.
void from_xmpl::start_statevector(const MBA_string& vector) {
L2_assert(vector=="mode", L2_reader_error,
("mode variable must be called `mode', not `"+vector+"'"));
}
void from_xmpl::start_transition(const MBA_string& from, const MBA_string& to,
const MBA_string& name, const MBA_string& prob) {
parsing_transition = true;
transition_name = name;
transition_from = find_enum_member(modevar_->type(), from);
transition_to = find_enum_member(modevar_->type(), to);
if(prob=="") {
// probability is only specified for failures,
// so this must be a nominal transition
transition_isNominal = true;
transition_rank = 0;
}
else {
transition_isNominal = false;
transition_rank = convert_to_rank(prob);
}
}
void from_xmpl::characters(const MBA_string& prop_str) {
// ignore whitespace and other junk outside of the <term> tags
if (!parsing_prop) return;
// the string comes in the format:
// var=value
// or
// !var=value
// where value may be a member of var->type() or another variable
bool isPositive;
L2rVariable *var;
unsigned i;
if(prop_str[0] == '!') {
isPositive = false;
i = 1;
}
else {
isPositive = true ;
i = 0;
}
for(/*i already set*/ ; i<prop_str.size(); i++) {
if(prop_str[i]=='=') break;
}
MBA_string varname;
varname = component_name + ".";
// read up to but not including the '=' ; also, skip '!' (which of course
// changes the count)
if(isPositive) varname = varname + MBA_string(prop_str.c_str(), i);
else varname = varname + MBA_string(prop_str.c_str()+1, i-1);
// read starting from right after the '='
MBA_string valuename(prop_str.c_str()+i+1);
var = find_variable(varname);
add_clause_prop(find_or_create_prop(var, isPositive, valuename));
}
void from_xmpl::end_component() {
// fully-parsed already; unlike in the L2_writer,
// we really don't care about components.
component_name = "";
// just for debugging, really
modevar_ = 0;
return;
}
void from_xmpl::end_clause() {
// we may be creating a new clause here, or maybe not
L2rClause *cls = find_or_create_clause();
// this happens in a nominal, idle transition; we get a:
// <clause/> tag, which has no propositions. Looks like
// a dirty hack to me, and I don't need it.
if(!cls) return;
// if we're in the background model, stuff the clause there;
// if we're in a transition, put it there instead
if(parsing_transition)
transition_clauses.push_back(cls);
else
cls->putInBackground();
parsing_clause = false;
clause_props.erase();
nclause_props = 0;
}
// Propositions are stored in clause_props, which
// is cleaned up in </ci:clause> so nothing left to do here
void from_xmpl::end_prop() {
parsing_prop = false;
}
// Now we have the transition_clauses, so we can create the transition
void from_xmpl::end_transition() {
L2rTransition *newtran = new dbg_L2rTransition(
transition_name,
modevar_, transition_from, transition_to,
transition_clauses.size(),
list_to_array(transition_clauses),false,
transition_isNominal, transition_rank);
X_.push_back(newtran);
verbose(newtran->toOStream_long(_STD_ cout));
// clear the variables that accumulated the info
parsing_transition = false;
transition_clauses.erase();
// others don't matter; and we shouldn't clear modevar_
}
/***************************************************************************
The 'mainline'
***************************************************************************/
bool try_to_open(const MBA_string& name) {
_STD_ ifstream try_file(name.c_str());
if(!try_file) {
_STD_ cerr << "Error opening `" << name << "'";
#ifndef WIN32
_STD_ cerr << ": " << strerror(errno);
#endif
_STD_ cerr << _STD_ endl;
return false;
}
else
return true;
}
bool from_xmpl::read() {
// parse the files. Really easy now!
XMLPlatformUtils::Initialize();
HandlerBase_subclass handler (*this);
SAXParser parser;
parser.setDocumentHandler(&handler);
parser.setErrorHandler(&handler);
L2_TRY {
// the main model file
handler.filename = filename_ + ".xmpl";
verbose(_STD_ cout << "Reading " << handler.filename << _STD_ endl);
if(!try_to_open(handler.filename)) return false;
parser.parse( (handler.filename).c_str());
// the harness file
handler.filename = filename_ + ".hrn";
verbose(_STD_ cout << "Reading " << handler.filename << _STD_ endl);
if(!try_to_open(handler.filename)) return false;
parser.parse( (handler.filename).c_str());
// the initial mode file
handler.filename = filename_ + ".ini";
verbose(_STD_ cout << "Reading " << handler.filename << _STD_ endl);
if(!try_to_open(handler.filename)) return false;
parser.parse( (handler.filename).c_str());
}
#ifdef ENABLE_EXCEPTIONS
catch(const XMLException& xcp) {
L2_throw( L2_reader_error,
(MBA_string("Error reading `") + handler.filename +"': "
+ XMLString::transcode(xcp.getMessage()) + "\n"));
}
#endif
// Now, the bulk of this function's work: putting it all into
// the L2_file structure.
// We set the prop and transition IDs here only, since we have
// to put them in a particular order.
{
// enumerations
dest()->allocEnums(nenums_, true);
for(enumsIT eit = enums_.begin(); eit != enums_.end(); ++eit) {
dbg_L2rEnumeration *en = *eit;
dest()->setEnum(en->id(), en);
}
}
{
// variables
dest()->allocVars(vars_.size(), true);
for(varsIT vit = vars_.begin(); vit != vars_.end(); ++vit) {
dbg_L2rVariable *var = *vit;
dest()->setVar(var->id(), var);
}
}
{
dest()->allocProps(nprops_);
for(propsIT pit = props_.begin(); pit != props_.end(); ++pit) {
L2rProposition *p = *pit;
dest()->setProp(p->id(), p);
}
}
{
// clauses
dest()->allocClauses(nclauses_, true);
for(clausesIT cit = clauses_.begin(); cit != clauses_.end(); ++cit) {
L2rClause *cls = *cit;
dest()->setClause(cls->id(), cls);
}
}
{
// transitions ; these are just added in, don't even need to allocate
transitionsIT xit = X_.begin();
for(xit = X_.begin(); xit != X_.end(); ++xit) {
dest()->addTransition(*xit);
}
}
// didn't fail so we succeded!
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -