From 321185b08dc338e8aaa489b1b909069274b4dc4c Mon Sep 17 00:00:00 2001 From: sbrandt Date: Wed, 15 Jan 2014 21:55:04 +0000 Subject: Fix ticket 1401 git-svn-id: http://svn.cactuscode.org/flesh/trunk@5066 17b73243-c579-4c4c-a9d2-2d5706c11dac --- src/piraha/Call.cc | 1516 +++++++++++++++++++++++++------------------------ src/piraha/Matcher.cc | 27 +- src/piraha/Piraha.hpp | 4 + src/piraha/Seq.cc | 2 + 4 files changed, 796 insertions(+), 753 deletions(-) diff --git a/src/piraha/Call.cc b/src/piraha/Call.cc index fd2ff1ca..30547c0d 100644 --- a/src/piraha/Call.cc +++ b/src/piraha/Call.cc @@ -25,9 +25,9 @@ extern "C" int CCTK_ParameterFilename(int len, char *filename); static smart_ptr par_file_grammar = new Grammar(); static std::string mklower(std::string& in) { - std::string s = in; - std::transform(s.begin(), s.end(), s.begin(), ::tolower); - return s; + std::string s = in; + std::transform(s.begin(), s.end(), s.begin(), ::tolower); + return s; } enum ValueType { PIR_STRING,PIR_INT,PIR_REAL,PIR_BOOL,PIR_VOID }; @@ -43,26 +43,26 @@ std::string get_parfile() { } int n = strlen(value); if(n > 4 && strcmp(value+n-4,".par")==0) { - value[n-4] = '\0'; + value[n-4] = '\0'; } std::string s = value; return s; } std::ostream& operator<<(std::ostream& o,const ValueType& vt) { - if(vt == PIR_STRING) - o << "STRING"; - else if(vt == PIR_INT) - o << "INT"; - else if(vt == PIR_REAL) - o << "REAL"; - else if(vt == PIR_BOOL) - o << "BOOL"; - else if(vt == PIR_VOID) - o << "VOID"; - else - o << "UNDEF"; - return o; + if(vt == PIR_STRING) + o << "STRING"; + else if(vt == PIR_INT) + o << "INT"; + else if(vt == PIR_REAL) + o << "REAL"; + else if(vt == PIR_BOOL) + o << "BOOL"; + else if(vt == PIR_VOID) + o << "VOID"; + else + o << "UNDEF"; + return o; } std::string current_thorn; @@ -73,140 +73,140 @@ std::string current_thorn; * that identifies which field is currently valid. */ struct Value { - /** This field holds the parse tree element associated with this Value. */ - smart_ptr hold; - double ddata; - int idata; - std::string sdata; - ValueType type; - Value(smart_ptr g) : hold(g), ddata(0), idata(0), sdata(), type(PIR_VOID) {} - ~Value() {} - /** - * Create a string representation of the Value. - */ - std::string copy() { - assert(type != PIR_VOID); - if(type == PIR_STRING) { - return sdata; - } else if(type == PIR_BOOL) { - std::string s = idata ? "yes" : "no"; - return s; - } else { - std::ostringstream o; - if(type == PIR_REAL) { - o << std::setprecision(15) << ddata; - } else { - o << idata; - } - return o.str(); - } - } - /** - * Check to see if something is a bool and throw an error - * if it's not. - */ - void checkBool() { - if(type != PIR_BOOL) { - std::ostringstream msg; - msg << "Does not evaluate to a boolean: " << hold->substring(); - std::string par = get_parfile(); - CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } - /** - * Compares with another Value, and throws a CCTK_Error - * if the comparison doesn't make sense. - */ - bool equals(smart_ptr v) { - if(type == PIR_BOOL && v->type == PIR_BOOL) { - return idata == v->idata; - } else if(type == PIR_INT && v->type == PIR_INT) { - return idata == v->idata; - } else if(type == PIR_INT && v->type == PIR_REAL) { - return idata == v->ddata; - } else if(type == PIR_REAL && v->type == PIR_INT) { - return ddata == v->idata; - } else if(type == PIR_REAL && v->type == PIR_REAL) { - return ddata == v->ddata; - } else if(type == PIR_STRING && v->type == PIR_STRING) { - return sdata == v->sdata; - } - std::ostringstream msg; - msg << "Cannot compare " << type << " and " << v->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - /** - * Return a double value, whether the underlying - * quantity is integer or real. - */ - double doubleValue() { - if(type == PIR_REAL) - return ddata; - else if(type == PIR_INT) - return idata; - std::ostringstream msg; - msg << "Cannot convert " << type << " to double." << std::endl; - std::string par = get_parfile(); - CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - return 0; - } - bool intOrDouble() { - return type == PIR_INT || type == PIR_REAL; - } - /** - * This function converts a double to a real, but - * only if this can be done without loss of precision. - */ - void integerize() { - if(type == PIR_REAL) { - idata = ddata; - if(idata == ddata) { - type = PIR_INT; - } - } - } - void booleanize(smart_ptr gr) { - if(type == PIR_STRING) { - std::string s = mklower(sdata); - if(s == "yes" || s == "true") { - idata = 1; - type = PIR_BOOL; - } else if(s == "no" || s == "false") { - idata = 0; - type = PIR_BOOL; - } - } else if(type == PIR_INT) { - /// Steven R. Brandt would like to remove this - /// particular auto-conversion - if(idata == 1 || idata == 0) { - type = PIR_BOOL; - std::ostringstream msg; - msg << "Boolean variable is set with integer: " << gr->substring() << std::endl; - std::string par = get_parfile(); - CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } - } + /** This field holds the parse tree element associated with this Value. */ + smart_ptr hold; + double ddata; + int idata; + std::string sdata; + ValueType type; + Value(smart_ptr g) : hold(g), ddata(0), idata(0), sdata(), type(PIR_VOID) { smart_ptr foo(g); } + ~Value() {} + /** + * Create a string representation of the Value. + */ + std::string copy() { + assert(type != PIR_VOID); + if(type == PIR_STRING) { + return sdata; + } else if(type == PIR_BOOL) { + std::string s = idata ? "yes" : "no"; + return s; + } else { + std::ostringstream o; + if(type == PIR_REAL) { + o << std::setprecision(15) << ddata; + } else { + o << idata; + } + return o.str(); + } + } + /** + * Check to see if something is a bool and throw an error + * if it's not. + */ + void checkBool() { + if(type != PIR_BOOL) { + std::ostringstream msg; + msg << "Does not evaluate to a boolean: " << hold->substring(); + std::string par = get_parfile(); + CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } + /** + * Compares with another Value, and throws a CCTK_Error + * if the comparison doesn't make sense. + */ + bool equals(smart_ptr v) { + if(type == PIR_BOOL && v->type == PIR_BOOL) { + return idata == v->idata; + } else if(type == PIR_INT && v->type == PIR_INT) { + return idata == v->idata; + } else if(type == PIR_INT && v->type == PIR_REAL) { + return idata == v->ddata; + } else if(type == PIR_REAL && v->type == PIR_INT) { + return ddata == v->idata; + } else if(type == PIR_REAL && v->type == PIR_REAL) { + return ddata == v->ddata; + } else if(type == PIR_STRING && v->type == PIR_STRING) { + return sdata == v->sdata; + } + std::ostringstream msg; + msg << "Cannot compare " << type << " and " << v->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + /** + * Return a double value, whether the underlying + * quantity is integer or real. + */ + double doubleValue() { + if(type == PIR_REAL) + return ddata; + else if(type == PIR_INT) + return idata; + std::ostringstream msg; + msg << "Cannot convert " << type << " to double." << std::endl; + std::string par = get_parfile(); + CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + return 0; + } + bool intOrDouble() { + return type == PIR_INT || type == PIR_REAL; + } + /** + * This function converts a double to a real, but + * only if this can be done without loss of precision. + */ + void integerize() { + if(type == PIR_REAL) { + idata = ddata; + if(idata == ddata) { + type = PIR_INT; + } + } + } + void booleanize(smart_ptr gr) { + if(type == PIR_STRING) { + std::string s = mklower(sdata); + if(s == "yes" || s == "true") { + idata = 1; + type = PIR_BOOL; + } else if(s == "no" || s == "false") { + idata = 0; + type = PIR_BOOL; + } + } else if(type == PIR_INT) { + /// Steven R. Brandt would like to remove this + /// particular auto-conversion + if(idata == 1 || idata == 0) { + type = PIR_BOOL; + std::ostringstream msg; + msg << "Boolean variable is set with integer: " << gr->substring() << std::endl; + std::string par = get_parfile(); + CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } + } }; std::ostream& operator<<(std::ostream& o,const smart_ptr& val) { - if(!val.valid()) { - return o << "NULL"; - } - o << "(" << val->type << ")"; - if(val->type == PIR_REAL) { - o << val->ddata; - } else if(val->type == PIR_INT) { - o << val->idata; - } else if(val->type == PIR_BOOL) { - o << (val->idata ? "true" : "false"); - } else if(val->type == PIR_STRING) { - o << "\"" << val->sdata << "\""; - } else { - o << val->hold->substring(); - } - return o; + if(!val.valid()) { + return o << "NULL"; + } + o << "(" << val->type << ")"; + if(val->type == PIR_REAL) { + o << val->ddata; + } else if(val->type == PIR_INT) { + o << val->idata; + } else if(val->type == PIR_BOOL) { + o << (val->idata ? "true" : "false"); + } else if(val->type == PIR_STRING) { + o << "\"" << val->sdata << "\""; + } else { + o << val->hold->substring(); + } + return o; } typedef std::map > >::iterator th_iter; @@ -217,17 +217,17 @@ smart_ptr eval_expr(std::string inp); // If the value was already defined in this parameter file, look // it up in the map. Otherwise, get it from Cactus. smart_ptr find_val(smart_ptr gr,std::string thorn,std::string name) { - smart_ptr ret = new Value(gr); + smart_ptr ret = new Value(gr); int type; const void *result; result = CCTK_ParameterGet(name.c_str(),thorn.c_str(),&type); if(result == NULL) { - std::ostringstream msg; - msg << "Undefined or inaccessible variable: " << thorn << "::" << name << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + std::ostringstream msg; + msg << "Undefined or inaccessible variable: " << thorn << "::" << name << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); } - + switch(type) { case PARAMETER_REAL: ret->type = PIR_REAL; @@ -251,62 +251,62 @@ smart_ptr find_val(smart_ptr gr,std::string thorn,std::string name } break; default: - std::ostringstream msg; - msg << "Unexpected type result from ParameterGet=" << type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + std::ostringstream msg; + msg << "Unexpected type result from ParameterGet=" << type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); } //std::cout << "Piraha: GET: " << thorn << "::" << name << "=" << ret << std::endl; - return ret; + return ret; } smart_ptr lookup_var(smart_ptr gr) { - smart_ptr ret; - if(gr->group(0)->getPatternName() == "env") { - const char *env = getenv(gr->group(0)->group(0)->substring().c_str()); - if(env != NULL) { - ret = new Value(gr); - ret->type = PIR_STRING; - ret->sdata = env; - } - } else if(gr->group(0)->substring() == "parfile") { - ret = new Value(gr); - ret->type = PIR_STRING; - ret->sdata = get_parfile(); - } else if(gr->group(0)->substring() == "pi") { - ret = new Value(gr); - ret->type = PIR_REAL; - ret->ddata = 4.0*atan2(1.0,1.0); - } - if(!ret.valid()) { - std::ostringstream msg; - msg << "Unknown variable: " << gr->substring() << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - return ret; + smart_ptr ret; + if(gr->group(0)->getPatternName() == "env") { + const char *env = getenv(gr->group(0)->group(0)->substring().c_str()); + if(env != NULL) { + ret = new Value(gr); + ret->type = PIR_STRING; + ret->sdata = env; + } + } else if(gr->group(0)->substring() == "parfile") { + ret = new Value(gr); + ret->type = PIR_STRING; + ret->sdata = get_parfile(); + } else if(gr->group(0)->substring() == "pi") { + ret = new Value(gr); + ret->type = PIR_REAL; + ret->ddata = 4.0*atan2(1.0,1.0); + } + if(!ret.valid()) { + std::ostringstream msg; + msg << "Unknown variable: " << gr->substring() << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + return ret; } std::string string_reparser(std::string s) { - smart_ptr m = new Matcher(par_file_grammar,"stringparser",s.c_str(),s.length()); - if(m->matches()) { - std::string out = ""; - for(int i=0;i < m->groupCount(); i++) { - std::string pn = m->group(i)->getPatternName(); - if(pn == "any" || pn == "name") { - out += m->group(i)->substring(); - } else if(pn == "stringcomment") { - ; - } else { - smart_ptr val = lookup_var(m->group(i)); - out += val->copy(); - } - } - return out; - } else { - return s; - } + smart_ptr m = new Matcher(par_file_grammar,"stringparser",s.c_str(),s.length()); + if(m->matches()) { + std::string out = ""; + for(int i=0;i < m->groupCount(); i++) { + std::string pn = m->group(i)->getPatternName(); + if(pn == "any" || pn == "name") { + out += m->group(i)->substring(); + } else if(pn == "stringcomment") { + ; + } else { + smart_ptr val = lookup_var(m->group(i)); + out += val->copy(); + } + } + return out; + } else { + return s; + } } /** @@ -316,12 +316,12 @@ std::string string_reparser(std::string s) { * used recursively. **/ smart_ptr meval(smart_ptr gr) { - assert(gr.valid()); - std::string pn = gr->getPatternName(); - smart_ptr ret = new Value(gr); - if(pn == "num") { - std::string s = gr->substring(); - s = mklower(s); + assert(gr.valid()); + std::string pn = gr->getPatternName(); + smart_ptr ret = new Value(gr); + if(pn == "num") { + std::string s = gr->substring(); + s = mklower(s); std::replace(s.begin(),s.end(),'d','e'); std::istringstream iss(s); if(iss >> ret->ddata) { @@ -337,571 +337,595 @@ smart_ptr meval(smart_ptr gr) { std::string par = get_parfile(); CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); } - } else if(pn == "paren" || pn == "parindex") { - return meval(gr->group(0)); - } else if(pn == "func") { - std::string fn = gr->group(0)->substring(); - fn = mklower(fn); - smart_ptr val = meval(gr->group(1)); - if(val->type == PIR_REAL || val->type == PIR_INT) { - if(fn == "trunc") { - val->ddata = trunc(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "floor") { - val->ddata = floor(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "ceil") { - val->ddata = ceil(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "sqrt") { - val->ddata = sqrt(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "atan") { - val->ddata = atan(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "sin") { - val->ddata = sin(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "cos") { - val->ddata = cos(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "tan") { - val->ddata = tan(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "exp") { - val->ddata = exp(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "log") { - val->ddata = log(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "abs") { - val->ddata = fabs(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "acos") { - val->ddata = acos(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "asin") { - val->ddata = asin(val->doubleValue()); - val->type = PIR_REAL; - return val; - } else if(fn == "bool") { - if(val->type == PIR_REAL) { - val->idata = val->ddata; - } - val->type = PIR_BOOL; - return val; - } else if(fn == "int") { - if(val->type == PIR_REAL) { - val->idata = val->ddata; - val->type = PIR_INT; - } - return val; - } else if(fn == "real") { - if(val->type == PIR_INT) { - val->ddata = val->idata; - val->type = PIR_REAL; - } - return val; - } - } else if(val->type == PIR_BOOL) { - if(fn == "int") { - val->type = PIR_INT; - return val; - } else if(fn == "real") { - val->type = PIR_REAL; - val->ddata = val->idata; - return val; - } - } - std::ostringstream msg; - msg << "Unknown func: " << fn << "(" << val->type << ")" << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } else if(pn == "name"||pn == "dname") { - std::string s = gr->substring(); - s = mklower(s); - if(s == "nan") { - ret->ddata = NAN; - ret->type = PIR_REAL; - } else if(s == "inf") { - ret->ddata = INFINITY; - ret->type = PIR_REAL; - } else if(s == "no" || s == "false") { - ret->type = PIR_BOOL; - ret->idata = 0; - } else if(s == "yes" || s == "true") { - ret->type = PIR_BOOL; - ret->idata = 1; - } else { - ret->type = PIR_STRING; - ret->sdata = gr->substring(); - } - return ret; - } else if(pn == "par") { - std::string thorn = gr->group(0)->substring(); - std::string name = gr->group(1)->substring(); - if(gr->groupCount() == 3) { - std::ostringstream vn; - smart_ptr index = meval(gr->group(2)); - if(index->type == PIR_INT) { - std::stringstream o; - o << name << "[" << index->idata << "]"; - o << std::flush; - std::string keyi = o.str(); - ret = find_val(gr,thorn,keyi); - return ret; - } - } else { - ret = find_val(gr,thorn,name); - return ret; - } - std::ostringstream msg; - msg << "Unknown par: " << thorn << "::" << name << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } else if(pn == "var") { - ret = lookup_var(gr); - } else if(pn == "value") { - if(gr->groupCount()==2) { - std::string unop = gr->group(0)->substring(); - ret = meval(gr->group(1)); - if(unop == "-") { - if(ret->type == PIR_INT) { - ret->idata = -ret->idata; - } else if(ret->type == PIR_REAL) { - ret->ddata = -ret->ddata; - } else { - std::ostringstream msg; - msg << "Unknown operation: " << unop << ret->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(unop == "!") { - if(ret->type == PIR_BOOL) { - ret->idata = !ret->idata; - } else { - std::ostringstream msg; - msg << "Unknown operation: " << unop << ret->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else { - std::ostringstream msg; - msg << "Unknown operation: " << unop << ret->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else { - return meval(gr->group(0)); - } - } else if(pn == "quot") { - ret->type = PIR_STRING; - ret->sdata = string_reparser(gr->group(0)->substring()); - } else if(pn == "inquot") { - ret->type = PIR_STRING; - ret->sdata = gr->substring(); - } else if(pn == "expr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - smart_ptr v2 = meval(gr->group(1)); - v1->checkBool(); - v2->checkBool(); - ret->type = PIR_BOOL; - ret->idata = v1->idata || v2->idata; - } else if(pn == "powexpr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - smart_ptr v2 = meval(gr->group(1)); - ret->type = PIR_REAL; - ret->ddata = pow(v1->doubleValue(),v2->doubleValue()); - } else if(pn == "andexpr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - smart_ptr v2 = meval(gr->group(1)); - v1->checkBool(); - v2->checkBool(); - ret->type = PIR_BOOL; - ret->idata = v1->idata && v2->idata; - } else if(pn == "eqexpr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - std::string eqop = gr->group(1)->substring(); - smart_ptr v2 = meval(gr->group(2)); - ret->type = PIR_BOOL; - if(eqop == "==") { - ret->idata = v1->equals(v2); - } else if(eqop == "!=") { - ret->idata = !v1->equals(v2); - } else { - std::ostringstream msg; - msg << "Unknown equality operator: " << eqop << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(pn == "compexpr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - if(gr->groupCount()>0) { - std::string compop = gr->group(1)->substring(); - smart_ptr v2 = meval(gr->group(2)); - double d1 = v1->doubleValue(); - double d2 = v2->doubleValue(); - ret->type = PIR_BOOL; - if(compop == "<") { - ret->idata = (d1 < d2); - return ret; - } else if(compop == ">") { - ret->idata = (d1 > d2); - return ret; - } else if(compop == "<=") { - ret->idata = (d1 <= d2); - return ret; - } else if(compop == ">=") { - ret->idata = (d1 >= d2); - return ret; - } - std::ostringstream msg; - msg << "Unknown comparison operator: " << compop << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(pn == "aexpr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - for(int i=1;i+1groupCount();i+=2) { - std::string addop = gr->group(i)->substring(); - smart_ptr v2 = meval(gr->group(i+1)); - assert(v2.valid()); - if(v1->type == PIR_INT && v2->type == PIR_INT) { - ret->type = PIR_INT; - if(addop == "+") { - ret->idata = v1->idata + v2->idata; - } else if(addop == "-") { - ret->idata = v1->idata - v2->idata; - } else { - std::ostringstream msg; - msg << "Unknown add operator: " << addop << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(v1->type == PIR_STRING && v2->type == PIR_STRING) { - ret->type = PIR_STRING; - if(addop == "+") { - ret->sdata = v1->sdata + v2->sdata; - } else { - std::ostringstream msg; + } else if(pn == "paren" || pn == "parindex") { + return meval(gr->group(0)); + } else if(pn == "func") { + std::string fn = gr->group(0)->substring(); + fn = mklower(fn); + smart_ptr val = meval(gr->group(1)); + if(val->type == PIR_REAL || val->type == PIR_INT) { + if(fn == "trunc") { + val->ddata = trunc(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "floor") { + val->ddata = floor(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "ceil") { + val->ddata = ceil(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "sqrt") { + val->ddata = sqrt(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "atan") { + val->ddata = atan(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "sin") { + val->ddata = sin(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "cos") { + val->ddata = cos(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "tan") { + val->ddata = tan(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "exp") { + val->ddata = exp(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "log") { + val->ddata = log(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "abs") { + val->ddata = fabs(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "acos") { + val->ddata = acos(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "asin") { + val->ddata = asin(val->doubleValue()); + val->type = PIR_REAL; + return val; + } else if(fn == "bool") { + if(val->type == PIR_REAL) { + val->idata = val->ddata; + } + val->type = PIR_BOOL; + return val; + } else if(fn == "int") { + if(val->type == PIR_REAL) { + val->idata = val->ddata; + val->type = PIR_INT; + } + return val; + } else if(fn == "real") { + if(val->type == PIR_INT) { + val->ddata = val->idata; + val->type = PIR_REAL; + } + return val; + } + } else if(val->type == PIR_BOOL) { + if(fn == "int") { + val->type = PIR_INT; + return val; + } else if(fn == "real") { + val->type = PIR_REAL; + val->ddata = val->idata; + return val; + } + } + std::ostringstream msg; + msg << "Unknown func: " << fn << "(" << val->type << ")" << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } else if(pn == "name"||pn == "dname") { + std::string s = gr->substring(); + s = mklower(s); + if(s == "nan") { + ret->ddata = NAN; + ret->type = PIR_REAL; + } else if(s == "inf") { + ret->ddata = INFINITY; + ret->type = PIR_REAL; + } else if(s == "no" || s == "false") { + ret->type = PIR_BOOL; + ret->idata = 0; + } else if(s == "yes" || s == "true") { + ret->type = PIR_BOOL; + ret->idata = 1; + } else { + ret->type = PIR_STRING; + ret->sdata = gr->substring(); + } + return ret; + } else if(pn == "par") { + std::string thorn = gr->group(0)->substring(); + std::string name = gr->group(1)->substring(); + if(gr->groupCount() == 3) { + std::ostringstream vn; + smart_ptr index = meval(gr->group(2)); + if(index->type == PIR_INT) { + std::stringstream o; + o << name << "[" << index->idata << "]"; + o << std::flush; + std::string keyi = o.str(); + ret = find_val(gr,thorn,keyi); + return ret; + } + } else { + ret = find_val(gr,thorn,name); + return ret; + } + std::ostringstream msg; + msg << "Unknown par: " << thorn << "::" << name << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } else if(pn == "var") { + ret = lookup_var(gr); + } else if(pn == "value") { + if(gr->groupCount()==2) { + std::string unop = gr->group(0)->substring(); + ret = meval(gr->group(1)); + if(unop == "-") { + if(ret->type == PIR_INT) { + ret->idata = -ret->idata; + } else if(ret->type == PIR_REAL) { + ret->ddata = -ret->ddata; + } else { + std::ostringstream msg; + msg << "Unknown operation: " << unop << ret->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(unop == "!") { + if(ret->type == PIR_BOOL) { + ret->idata = !ret->idata; + } else { + std::ostringstream msg; + msg << "Unknown operation: " << unop << ret->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else { + std::ostringstream msg; + msg << "Unknown operation: " << unop << ret->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else { + return meval(gr->group(0)); + } + } else if(pn == "quot") { + ret->type = PIR_STRING; + ret->sdata = string_reparser(gr->group(0)->substring()); + } else if(pn == "inquot") { + ret->type = PIR_STRING; + ret->sdata = gr->substring(); + } else if(pn == "expr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + smart_ptr v2 = meval(gr->group(1)); + v1->checkBool(); + v2->checkBool(); + ret->type = PIR_BOOL; + ret->idata = v1->idata || v2->idata; + } else if(pn == "powexpr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + smart_ptr v2 = meval(gr->group(1)); + ret->type = PIR_REAL; + ret->ddata = pow(v1->doubleValue(),v2->doubleValue()); + } else if(pn == "andexpr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + smart_ptr v2 = meval(gr->group(1)); + v1->checkBool(); + v2->checkBool(); + ret->type = PIR_BOOL; + ret->idata = v1->idata && v2->idata; + } else if(pn == "eqexpr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + std::string eqop = gr->group(1)->substring(); + smart_ptr v2 = meval(gr->group(2)); + ret->type = PIR_BOOL; + if(eqop == "==") { + ret->idata = v1->equals(v2); + } else if(eqop == "!=") { + ret->idata = !v1->equals(v2); + } else { + std::ostringstream msg; + msg << "Unknown equality operator: " << eqop << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(pn == "compexpr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + if(gr->groupCount()>0) { + std::string compop = gr->group(1)->substring(); + smart_ptr v2 = meval(gr->group(2)); + double d1 = v1->doubleValue(); + double d2 = v2->doubleValue(); + ret->type = PIR_BOOL; + if(compop == "<") { + ret->idata = (d1 < d2); + return ret; + } else if(compop == ">") { + ret->idata = (d1 > d2); + return ret; + } else if(compop == "<=") { + ret->idata = (d1 <= d2); + return ret; + } else if(compop == ">=") { + ret->idata = (d1 >= d2); + return ret; + } + std::ostringstream msg; + msg << "Unknown comparison operator: " << compop << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(pn == "aexpr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + for(int i=1;i+1groupCount();i+=2) { + std::string addop = gr->group(i)->substring(); + smart_ptr v2 = meval(gr->group(i+1)); + assert(v2.valid()); + if(v1->type == PIR_INT && v2->type == PIR_INT) { + ret->type = PIR_INT; + if(addop == "+") { + ret->idata = v1->idata + v2->idata; + } else if(addop == "-") { + ret->idata = v1->idata - v2->idata; + } else { + std::ostringstream msg; + msg << "Unknown add operator: " << addop << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(v1->type == PIR_STRING && v2->type == PIR_STRING) { + ret->type = PIR_STRING; + if(addop == "+") { + ret->sdata = v1->sdata + v2->sdata; + } else { + std::ostringstream msg; ret->sdata = v1->sdata + addop + v2->sdata; - msg << "Unknown add operator: " << addop << std::endl; + msg << "Unknown add operator: " << addop << std::endl; msg << "Interpreting as literal string with value '" << ret->sdata << "'" << std::endl; - std::string par = get_parfile(); - CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(v1->intOrDouble() && v2->intOrDouble()) { - ret->type = PIR_REAL; - if(addop == "+") { - ret->ddata = v1->doubleValue()+v2->doubleValue(); - } else if(addop == "-") { - ret->ddata = v1->doubleValue()-v2->doubleValue(); - } else { - std::ostringstream msg; - msg << "Unknown add operator: " << addop << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else { - std::ostringstream msg; - msg << "Unknown operation: " << v1->type; - msg << " " << addop << v2->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - v1 = ret; - } - } else if(pn == "mexpr") { - if(gr->groupCount()==1) - return meval(gr->group(0)); - smart_ptr v1 = meval(gr->group(0)); - for(int i=1;i+1groupCount();i+=2) { - std::string mulop = gr->group(i)->substring(); - smart_ptr v2 = meval(gr->group(i+1)); - if(v1->type == PIR_INT && v2->type == PIR_INT) { - ret->type = PIR_INT; - if(mulop == "*") { - ret->idata = v1->idata * v2->idata; - } else if(mulop == "/") { - ret->idata = v1->idata / v2->idata; - } else if(mulop == "%") { - ret->idata = v1->idata % v2->idata; - } else { - std::ostringstream msg; - msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(v1->type == PIR_STRING && v2->type == PIR_INT) { - ret->type = PIR_STRING; - if(mulop == "*") { - ret->sdata = ""; - for(int i=0;iidata;i++) - ret->sdata += v1->sdata; - } else { - std::ostringstream msg; - msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(v1->intOrDouble() && v2->intOrDouble()) { - ret->type = PIR_REAL; - if(mulop == "*") { - ret->ddata = v1->doubleValue()*v2->doubleValue(); - } else if(mulop == "/") { - ret->ddata = v1->doubleValue()/v2->doubleValue(); - } else { - std::ostringstream msg; - msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - } else if(v1->type == PIR_STRING && v2->type == PIR_STRING) { - std::ostringstream msg; + std::string par = get_parfile(); + CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(v1->intOrDouble() && v2->intOrDouble()) { + ret->type = PIR_REAL; + if(addop == "+") { + ret->ddata = v1->doubleValue()+v2->doubleValue(); + } else if(addop == "-") { + ret->ddata = v1->doubleValue()-v2->doubleValue(); + } else { + std::ostringstream msg; + msg << "Unknown add operator: " << addop << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else { + std::ostringstream msg; + msg << "Unknown operation: " << v1->type; + msg << " " << addop << v2->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + v1 = ret; + } + } else if(pn == "mexpr") { + if(gr->groupCount()==1) + return meval(gr->group(0)); + smart_ptr v1 = meval(gr->group(0)); + for(int i=1;i+1groupCount();i+=2) { + std::string mulop = gr->group(i)->substring(); + smart_ptr v2 = meval(gr->group(i+1)); + if(v1->type == PIR_INT && v2->type == PIR_INT) { + ret->type = PIR_INT; + if(mulop == "*") { + ret->idata = v1->idata * v2->idata; + } else if(mulop == "/") { + ret->idata = v1->idata / v2->idata; + } else if(mulop == "%") { + ret->idata = v1->idata % v2->idata; + } else { + std::ostringstream msg; + msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(v1->type == PIR_STRING && v2->type == PIR_INT) { + ret->type = PIR_STRING; + if(mulop == "*") { + ret->sdata = ""; + for(int i=0;iidata;i++) + ret->sdata += v1->sdata; + } else { + std::ostringstream msg; + msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(v1->intOrDouble() && v2->intOrDouble()) { + ret->type = PIR_REAL; + if(mulop == "*") { + ret->ddata = v1->doubleValue()*v2->doubleValue(); + } else if(mulop == "/") { + ret->ddata = v1->doubleValue()/v2->doubleValue(); + } else { + std::ostringstream msg; + msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + } else if(v1->type == PIR_STRING && v2->type == PIR_STRING) { + std::ostringstream msg; ret->type = PIR_STRING; ret->sdata = v1->sdata + mulop + v2->sdata; - msg << "Unknown operation: " << v1->type << " " << mulop << v2->type << std::endl; + msg << "Unknown operation: " << v1->type << " " << mulop << v2->type << std::endl; msg << "Interpreting as literal string with value '" << ret->sdata << "'" << std::endl; - std::string par = get_parfile(); - CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } else { - std::ostringstream msg; - msg << "Unknown operation: " << v1->type << " " << mulop << v2->type << std::endl; - std::string par = get_parfile(); - CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); - } - v1 = ret; - } - } else { - std::ostringstream msg; - std::string par = get_parfile(); - msg << "Pattern not handled[" << gr->getPatternName() << "]=" << gr->substring() << - " at " << gr->line() << " in " << par << std::endl; - CCTK_Error(__LINE__,__FILE__,"piraha",msg.str().c_str()); - } - return ret; + std::string par = get_parfile(); + CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } else { + std::ostringstream msg; + msg << "Unknown operation: " << v1->type << " " << mulop << v2->type << std::endl; + std::string par = get_parfile(); + CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str()); + } + v1 = ret; + } + } else { + std::ostringstream msg; + std::string par = get_parfile(); + msg << "Pattern not handled[" << gr->getPatternName() << "]=" << gr->substring() << + " at " << gr->line() << " in " << par << std::endl; + CCTK_Error(__LINE__,__FILE__,"piraha",msg.str().c_str()); + } + return ret; } smart_ptr eval_expr(std::string input) { - smart_ptr m = new Matcher(par_file_grammar,"eval",input.c_str()); - smart_ptr ret; - if(m->matches()) { - ret = meval(m->group(0)); - } - return ret; + smart_ptr m = new Matcher(par_file_grammar,"eval",input.c_str()); + smart_ptr ret; + if(m->matches()) { + ret = meval(m->group(0)); + } + return ret; } void check_types(const char *thorn,int line,smart_ptr svm,int t) { ValueType v = svm->type; - bool ok = false; - if(v == PIR_STRING && (t == PARAMETER_STRING || t == PARAMETER_KEYWORD)) - ok = true; - else if(v == PIR_INT && t == PARAMETER_INT) - ok = true; - else if(v == PIR_BOOL && t == PARAMETER_BOOLEAN) - ok = true; - else if((v == PIR_INT || v == PIR_REAL) && t == PARAMETER_REAL) - ok = true; - if(!ok) { - std::string par = get_parfile(); - std::ostringstream msg; + bool ok = false; + if(v == PIR_STRING && (t == PARAMETER_STRING || t == PARAMETER_KEYWORD)) + ok = true; + else if(v == PIR_INT && t == PARAMETER_INT) + ok = true; + else if(v == PIR_BOOL && t == PARAMETER_BOOLEAN) + ok = true; + else if((v == PIR_INT || v == PIR_REAL) && t == PARAMETER_REAL) + ok = true; + if(!ok) { + std::string par = get_parfile(); + std::ostringstream msg; msg << "Invalid assignment: Attempting to set a variable of type "; - switch(t) { - case PARAMETER_BOOLEAN: - msg << "BOOL"; - break; - case PARAMETER_INT: - msg << "INT"; - break; - case PARAMETER_KEYWORD: - msg << "KEYWORD"; - break; - case PARAMETER_STRING: - msg << "STRING"; - break; - case PARAMETER_REAL: - msg << "REAL"; - break; - default: - msg << "type(" << t << ")"; - break; - } + switch(t) { + case PARAMETER_BOOLEAN: + msg << "BOOL"; + break; + case PARAMETER_INT: + msg << "INT"; + break; + case PARAMETER_KEYWORD: + msg << "KEYWORD"; + break; + case PARAMETER_STRING: + msg << "STRING"; + break; + case PARAMETER_REAL: + msg << "REAL"; + break; + default: + msg << "type(" << t << ")"; + break; + } msg << " with " << svm << std::endl; - CCTK_Error(line,par.c_str(),thorn,msg.str().c_str()); - } + CCTK_Error(line,par.c_str(),thorn,msg.str().c_str()); + } } extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int (*set_function)(const char *, const char *, int)) { - const char *par_file_src = - "skipper = ([ \\t\\r\\n]|\\#.*)*\n" - "# comment\n" - "skipeol = ([ \\t\\r]|\\#.*)*($|\\n)\n" - "any = [^]\n" - "stringcomment = #.*\n" - "stringparser = ^({stringcomment}|{var}|{name}|{any})*$\n" - - "# Note that / occurs in some par files. It is my\n" - "# feeling that this should require quote marks.\n" - - "name = [a-zA-Z][a-zA-Z0-9_]*\n" - "dname = [0-9][a-zA-Z_]{2,}\n" - "inquot = ({var}|\\\\.|[^\\\\\"])*\n" - "fname = \\.?/[-\\./0-9a-zA-Z_]+\n" - "quot = \"{inquot}\"|{fname}\n" - "num = ([0-9]+(\\.[0-9]*|)|\\.[0-9]+)([edDE][+-]?[0-9]+|)\n" - "env = ENV\\{{name}\\}\n" - "var = \\$({env}|{name}|\\{{name}\\})\n" - - "powexpr = {value}( \\*\\* {value})?\n" - "mulop = [*/%]\n" - "mexpr = {powexpr}( {mulop} {powexpr})*\n" - "addop = [+-]\n" - "aexpr = {mexpr}( {addop} {mexpr})*\n" - "compop = [<>]=?\n" - "compexpr = {aexpr}( {compop} {aexpr})?\n" - "eqop = [!=]=\n" - "eqexpr = {compexpr}( {eqop} {eqexpr})?\n" - "andexpr = {eqexpr}( && {eqexpr})?\n" - "expr = {andexpr}( \\|\\| {andexpr})?\n" - "eval = {expr}\n" - - "paren = \\( {expr} \\)\n" - "par = {name} :: {name}( {parindex})?\n" - "func = {name} \\( {expr} \\)\n" - "array = \\[ {expr}( , {expr})* \\]\n" - - "value = {unop}?({par}|{func}|{paren}|{dname}|{num}|{quot}|{name}|{var})\n" - "unop = [-!]\n" - - "int = [0-9]+\n" - "index = \\[ {int} \\]\n" - "parindex = \\[ {expr} \\]\n" - "active = (?i:ActiveThorns)\n" - "set = ({active} = ({quot}|{name})|{par}( {index}|) = ({array}|\\+?{expr})){-skipeol}\n" - "desc = !DESC {quot}\n" - "file = ^( ({desc}|{set}|{active}) )*$"; + const char *par_file_src = + "skipper = ([ \\t\\r\\n]|\\#.*)*\n" + "# comment\n" + "skipeol = ([ \\t\\r]|\\#.*)*($|\\n)\n" + "any = [^]\n" + "stringcomment = #.*\n" + "stringparser = ^({stringcomment}|{var}|{name}|{any})*$\n" + + "# Note that / occurs in some par files. It is my\n" + "# feeling that this should require quote marks.\n" + + "name = [a-zA-Z][a-zA-Z0-9_]*\n" + "dname = [0-9][a-zA-Z_]{2,}\n" + "inquot = ({var}|\\\\.|[^\\\\\"])*\n" + "fname = \\.?/[-\\./0-9a-zA-Z_]+\n" + "quot = \"{inquot}\"|{fname}\n" + "num = ([0-9]+(\\.[0-9]*|)|\\.[0-9]+)([edDE][+-]?[0-9]+|)\n" + "env = ENV\\{{name}\\}\n" + "var = \\$({env}|{name}|\\{{name}\\})\n" + + "powexpr = {value}( \\*\\* {value})?\n" + "mulop = [*/%]\n" + "mexpr = {powexpr}( {mulop} {powexpr})*\n" + "addop = [+-]\n" + "aexpr = {mexpr}( {addop} {mexpr})*\n" + "compop = [<>]=?\n" + "compexpr = {aexpr}( {compop} {aexpr})?\n" + "eqop = [!=]=\n" + "eqexpr = {compexpr}( {eqop} {eqexpr})?\n" + "andexpr = {eqexpr}( && {eqexpr})?\n" + "expr = {andexpr}( \\|\\| {andexpr})?\n" + "eval = {expr}\n" + + "paren = \\( {expr} \\)\n" + "par = {name} :: {name}( {parindex})?\n" + "func = {name} \\( {expr} \\)\n" + "array = \\[ {expr}( , {expr})* \\]\n" + + "value = {unop}?({par}|{func}|{paren}|{dname}|{num}|{quot}|{name}|{var})\n" + "unop = [-!]\n" + + "int = [0-9]+\n" + "index = \\[ {int} \\]\n" + "parindex = \\[ {expr} \\]\n" + "active = (?i:ActiveThorns)\n" + "set = ({active} = ({quot}|{name})|{par}( {index}|) = ({array}|\\+?{expr})){-skipeol}\n" + "desc = !DESC {quot}\n" + "file = ^( ({desc}|{set}|{active}) )*$"; //std::ofstream peg("/tmp/par.peg"); //peg << par_file_src; //peg.close(); - compileFile(par_file_grammar,par_file_src,strlen(par_file_src)); + compileFile(par_file_grammar,par_file_src,strlen(par_file_src)); - std::string active; + std::string active; smart_ptr m2 = new Matcher(par_file_grammar,"file",buffer,buffersize); if(m2->matches()) { - int line = -1; - for(int i=0;igroupCount();i++) { - smart_ptr gr = m2->group(i); - if(gr->group(0)->getPatternName() == "active") { - smart_ptr smv = meval(gr->group(1)); - std::string val = smv->copy(); - active += val; - active += ' '; - line = gr->line(); - } - } - set_function("ActiveThorns",active.c_str(),line); - for(int i=0;igroupCount();i++) { - smart_ptr gr = m2->group(i); - if(gr->getPatternName() != "set") - continue; - smart_ptr par = gr->group("par"); - if(par.valid()) { - // add value->quot->inquot - std::string key; - std::string thorn = par->group("name",0)->substring(); - std::string name = par->group("name",1)->substring(); - key += thorn; - key += "::"; - key += name; - const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str()); - - smart_ptr index = par->group("parindex"); - if(index.valid()) { - key += '['; - smart_ptr vv = meval(index); - if(vv->type != PIR_INT) { - std::ostringstream msg; - std::string par = get_parfile(); - msg << "bad index " << vv << std::endl; - CCTK_Error(index->line(),par.c_str(),thorn.c_str(),msg.str().c_str()); - } - std::string vvstr = vv->copy(); - key += vvstr; - key += ']'; - } - - std::string val; - smart_ptr aexpr = gr->group("expr"); - if(aexpr.valid()) { - current_thorn = thorn; - smart_ptr smv = meval(aexpr); - val = smv->copy(); - assert(smv.valid()); - smv->integerize(); - if(data != NULL) { - if(data->type == PARAMETER_REAL) - smv->integerize(); - if(data->type == PARAMETER_BOOLEAN) - smv->booleanize(gr); - check_types(thorn.c_str(),aexpr->line(),smv,data->type); - } - set_function( - strdup(key.c_str()), - strdup(val.c_str()), - gr->group(0)->line()); - } else { - smart_ptr arr = gr->group("array"); - for(int i=0;igroupCount();i++) { - aexpr = arr->group(i); - std::ostringstream keyi; - keyi << key << '[' << i << ']'; - smart_ptr smv = meval(aexpr); - val = smv->copy(); - if(data != NULL) { - if(data->type == PARAMETER_REAL) - smv->integerize(); - if(data->type == PARAMETER_BOOLEAN) - smv->booleanize(gr); - check_types(thorn.c_str(),aexpr->line(),smv,data->type); - } - set_function( - strdup(keyi.str().c_str()), - strdup(val.c_str()), - aexpr->line()); - } - } - } - } + int line = -1; + for(int i=0;igroupCount();i++) { + smart_ptr gr = m2->group(i); + if(gr->group(0)->getPatternName() == "active") { + smart_ptr smv = meval(gr->group(1)); + std::string val = smv->copy(); + active += val; + active += ' '; + line = gr->line(); + } + } + set_function("ActiveThorns",active.c_str(),line); + for(int i=0;igroupCount();i++) { + smart_ptr gr = m2->group(i); + if(gr->getPatternName() != "set") + continue; + smart_ptr par = gr->group("par"); + if(par.valid()) { + // add value->quot->inquot + std::string key; + std::string thorn = par->group("name",0)->substring(); + std::string name = par->group("name",1)->substring(); + key += thorn; + key += "::"; + key += name; + const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str()); + + smart_ptr index = par->group("parindex"); + if(index.valid()) { + key += '['; + smart_ptr vv = meval(index); + if(vv->type != PIR_INT) { + std::ostringstream msg; + std::string par = get_parfile(); + msg << "bad index " << vv << std::endl; + CCTK_Error(index->line(),par.c_str(),thorn.c_str(),msg.str().c_str()); + } + std::string vvstr = vv->copy(); + key += vvstr; + key += ']'; + } + + std::string val; + smart_ptr aexpr = gr->group("expr"); + if(aexpr.valid()) { + current_thorn = thorn; + smart_ptr smv = meval(aexpr); + val = smv->copy(); + assert(smv.valid()); + smv->integerize(); + if(data != NULL) { + if(data->type == PARAMETER_REAL) + smv->integerize(); + if(data->type == PARAMETER_BOOLEAN) + smv->booleanize(gr); + check_types(thorn.c_str(),aexpr->line(),smv,data->type); + } + set_function( + strdup(key.c_str()), + strdup(val.c_str()), + gr->group(0)->line()); + } else { + smart_ptr arr = gr->group("array"); + for(int i=0;igroupCount();i++) { + aexpr = arr->group(i); + std::ostringstream keyi; + keyi << key << '[' << i << ']'; + smart_ptr smv = meval(aexpr); + val = smv->copy(); + if(data != NULL) { + if(data->type == PARAMETER_REAL) + smv->integerize(); + if(data->type == PARAMETER_BOOLEAN) + smv->booleanize(gr); + check_types(thorn.c_str(),aexpr->line(),smv,data->type); + } + set_function( + strdup(keyi.str().c_str()), + strdup(val.c_str()), + aexpr->line()); + } + } + } + } } else { - // TODO: Fix this - std::cout << "ERROR IN PARAMETER FILE:" << std::endl; - m2->showError(); + std::ostringstream msg; + msg << "ERROR IN PARAMETER FILE:"; + if(m2->inrule_max == "file::set::par" && m2->foundChar() =='=') { + msg << std::endl; + msg << "Invalid assignment." << std::endl; + msg << "Valid assignments are: " << std::endl; + msg << "ActiveThorns = \"...\"" << std::endl; + msg << "Arrangement::Thorn = ..." << std::endl; + // Construct the parse tree for the partial match + if(m2->matchesTo(m2->max_pos)) { + // find the last element in the parse tree + smart_ptr gr = m2->group(m2->groupCount()-1); + while(true) { + int n = gr->groupCount(); + if(n > 0) + gr = gr->group(n-1); + else + break; + } + msg << "You wrote: " << gr->substring() << " = ..." << std::endl; + } + } else { + m2->showError(msg); + } + std::string par = get_parfile(); + par += ".par"; + CCTK_Warn(0,m2->line(),par.c_str(),"cactus",msg.str().c_str()); return 1; } return 0; diff --git a/src/piraha/Matcher.cc b/src/piraha/Matcher.cc index 9a37a06b..fd1b2355 100644 --- a/src/piraha/Matcher.cc +++ b/src/piraha/Matcher.cc @@ -6,13 +6,21 @@ using namespace cctki_piraha; Matcher::Matcher(smart_ptr g_,const char *pat_,const char *input_,int input_size_) : Group(pat_,input_), input(input_), g(g_), input_size(input_size_), - pos(0), max_pos(-1), pat(pat_), expected(), err_pos(-1) { + pos(0), max_pos(-1), match_to(-2), pat(pat_), expected(), err_pos(-1) { inrule = pat_; if(input_size < 0) input_size=strlen(input); } bool Matcher::matches() { + // -2 is used just to make sure + // we can't actually get to that + // position, even in an error + // condition. + return matchesTo(-2); +} + +bool Matcher::matchesTo(int match_to_) { smart_ptr p = g->patterns.get(pat); if(!p.valid()) { std::cout << "Grammar does not contain \"" << pat << "\"" << std::endl; @@ -21,6 +29,7 @@ bool Matcher::matches() { assert(p.valid()); pos = 0; max_pos = -1; + match_to = match_to_; err_pos = -1; children.clear(); bool b = p->match(this); @@ -45,6 +54,10 @@ void Matcher::fail(char lo,char hi) { } void Matcher::showError() { + showError(std::cout); +} + +void Matcher::showError(std::ostream& out) { int line = 1; int error_pos = -1; const int num_previous_lines = 4; @@ -56,7 +69,7 @@ void Matcher::showError() { if(i == max_pos) { error_pos = i; int column = i - start_of_previous_line[0]+1; - std::cout << "In rule '" << inrule_max + out << "In rule '" << inrule_max << "' Line=" << line << ", Column=" << column << std::endl; while(input[i] == '\n'||input[i] == '\r') { line++; @@ -79,15 +92,15 @@ void Matcher::showError() { } bool eol = false; for(int i=start_of_previous_line[0];i error_pos && input[i] == '\n') { eol = true; break; } } - if(!eol) std::cout << std::endl; + if(!eol) out << std::endl; for(int i=start_of_line;i<=error_pos;i++) - std::cout << ' '; - std::cout << "^" << std::endl; - std::cout << "Expected one of the following characters: " << expected << std::endl; + out << ' '; + out << "^" << std::endl; + out << "Expected one of the following characters: " << expected << std::endl; } diff --git a/src/piraha/Piraha.hpp b/src/piraha/Piraha.hpp index bd2d70a5..2e7dff90 100644 --- a/src/piraha/Piraha.hpp +++ b/src/piraha/Piraha.hpp @@ -355,15 +355,19 @@ public: int input_size; int pos; int max_pos; + int match_to; const char *pat; bool matches(); + bool matchesTo(int mt); Bracket expected; + void showError(std::ostream& out); void showError(); std::string inrule; std::string inrule_max; int err_pos; void fail(Bracket *ex); void fail(char lo,char hi); + char foundChar() { return input[max_pos+1]; } }; extern smart_ptr pegGrammar; diff --git a/src/piraha/Seq.cc b/src/piraha/Seq.cc index 80be5ace..cd65a71d 100644 --- a/src/piraha/Seq.cc +++ b/src/piraha/Seq.cc @@ -24,6 +24,8 @@ bool Seq::match(Matcher *m) { for(pattern_iter p = patterns.begin();p != patterns.end();++p) { if(!(*p)->match(m)) return false; + if(m->max_pos == m->match_to) + return true; } return true; } -- cgit v1.2.3