summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsbrandt <sbrandt@17b73243-c579-4c4c-a9d2-2d5706c11dac>2013-03-04 23:50:30 +0000
committersbrandt <sbrandt@17b73243-c579-4c4c-a9d2-2d5706c11dac>2013-03-04 23:50:30 +0000
commit638398785d624541bb8bd0c0f70b9eb3f8820e9b (patch)
treed9675b8fee659b4fc2c49ce33f405658af6b8176 /src
parent421cadbef8c00ccd47f72c95d25f8553a4aae786 (diff)
Significant upgrade of Piraha:
It no longer uses strings to store intermediate values in expressions. It now supports everything that was supported by the old expression parser. Comments added. Numerous pieces of error checking added. git-svn-id: http://svn.cactuscode.org/flesh/trunk@4974 17b73243-c579-4c4c-a9d2-2d5706c11dac
Diffstat (limited to 'src')
-rw-r--r--src/piraha/Call.cc838
-rw-r--r--src/piraha/Makefile2
-rw-r--r--src/piraha/Matcher.cc5
-rw-r--r--src/piraha/Piraha.hpp8
-rw-r--r--src/piraha/smart_ptr.cc2
-rw-r--r--src/piraha/smart_ptr.hpp38
6 files changed, 715 insertions, 178 deletions
diff --git a/src/piraha/Call.cc b/src/piraha/Call.cc
index 9df8fd10..ef981fd6 100644
--- a/src/piraha/Call.cc
+++ b/src/piraha/Call.cc
@@ -1,11 +1,14 @@
#include <iostream>
+#include <iomanip>
#include <string.h>
#include "Piraha.hpp"
#include <stdlib.h>
#include <sstream>
+#include "cctk_core.h"
#include "cctk_Parameter.h"
#include <map>
#include <math.h>
+#include <algorithm>
namespace piraha {
@@ -13,168 +16,665 @@ namespace piraha {
extern "C" int CCTK_ParameterFilename(int len, char *filename);
-std::map<std::string,std::map<std::string,std::string> > values;
-typedef std::map<std::string,std::map<std::string,std::string> >::iterator th_iter;
-typedef std::map<std::string,std::string>::iterator nm_iter;
+/**
+ * This holds the structure required for parsing
+ * a Cactus par file.
+ */
+static smart_ptr<Grammar> 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;
+}
+
+enum ValueType { PIR_STRING,PIR_INT,PIR_REAL,PIR_BOOL,PIR_VOID };
+
+std::string get_parfile() {
+ char path[500];
+ CCTK_ParameterFilename(500, path);
+ char *value = strrchr (path, '/');
+ if (value == NULL) {
+ value = path;
+ } else {
+ value++;
+ }
+ int n = strlen(value);
+ if(n > 4 && strcmp(value+n-4,".par")==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;
+}
+
+std::string current_thorn;
+
+/**
+ * The Value class is something like a union. It holds
+ * integer, real, and string data and has a type field
+ * that identifies which field is currently valid.
+ */
+struct Value {
+ /** This field holds the parse tree element associated with this Value. */
+ smart_ptr<Group> hold;
+ double ddata;
+ int idata;
+ std::string sdata;
+ ValueType type;
+ Value(smart_ptr<Group> 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<Value> 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<Group> 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<Value>& 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;
+}
+
+std::map<std::string,std::map<std::string,smart_ptr<Value> > > values;
+typedef std::map<std::string,std::map<std::string,smart_ptr<Value> > >::iterator th_iter;
+typedef std::map<std::string,smart_ptr<Value> >::iterator nm_iter;
+
+smart_ptr<Value> 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.
-bool find_val(std::string thorn,std::string name,std::string& ret) {
+smart_ptr<Value> find_val(std::string thorn,std::string name) {
+ smart_ptr<Value> ret;
th_iter th = values.find(thorn);
if(th != values.end()) {
nm_iter nm = th->second.find(name);
if(nm != th->second.end()) {
ret = nm->second;
- return true;
+ return ret;
}
}
const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str());
- if(data == NULL)
- return false;
- ret = data->defval;
- return true;
+ if(data != NULL) {
+ std::string expr = data->defval;
+ ret = eval_expr(expr);
+ }
+ return ret;
}
-bool lookup_var(smart_ptr<Group> gr,std::string& res) {
+smart_ptr<Value> lookup_var(smart_ptr<Group> gr) {
+ smart_ptr<Value> ret;
if(gr->group(0)->getPatternName() == "env") {
const char *env = getenv(gr->group(0)->group(0)->substring().c_str());
if(env != NULL) {
- res = env;
- return true;
+ ret = new Value(gr);
+ ret->type = PIR_STRING;
+ ret->sdata = env;
}
} else if(gr->group(0)->substring() == "parfile") {
- char path[500];
- CCTK_ParameterFilename(500, path);
- char *value = strrchr (path, '/');
- if (value == NULL) {
- value = path;
- } else {
- value++;
- }
- /* skip the parameter file extension */
- if (strcmp (value + strlen (value) - 4, ".par") == 0)
- {
- value[strlen (value) - 4] = '\0';
- }
- res = value;
- return true;
+ ret = new Value(gr);
+ ret->type = PIR_STRING;
+ ret->sdata = get_parfile();
} else if(gr->group(0)->substring() == "pi") {
- std::ostringstream ostr;
- ostr << (4.0*atan2(1.,1.)) << std::flush;
- res = ostr.str();
- return true;
+ 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 false;
+ return ret;
}
-// Converts a value to a string
-void meval(smart_ptr<Group> gr,std::string& val) {
- val.clear();
- if(gr->getPatternName() == "value" || gr->getPatternName() == "paren") {
- meval(gr->group(0),val);
- } else if(gr->getPatternName() == "quot") {
- smart_ptr<Group> inquot = gr->group(0);
- val = inquot->substring();
- int last = 0;
- std::string nw;
- for(int i=0;i < inquot->groupCount();i++) {
- smart_ptr<Group> vr = inquot->group(i);
- std::string sub;
- if(lookup_var(vr,sub)) {
- int start = vr->start() - inquot->start();
- nw += val.substr(last,start-last);
- nw += sub;
- last = vr->end() - inquot->start();
+/**
+ * The meval() function takes any node within
+ * the parse tree and creates a Value object
+ * from it. It is, therefore, designed to be
+ * used recursively.
+ **/
+smart_ptr<Value> meval(smart_ptr<Group> gr) {
+ assert(gr.valid());
+ std::string pn = gr->getPatternName();
+ smart_ptr<Value> ret = new Value(gr);
+ if(pn == "num") {
+ std::string s = gr->substring();
+ ret->ddata = atof(s.c_str());
+ ret->idata = ret->ddata;
+ if(ret->idata == ret->ddata && (s.find('.') == std::string::npos))
+ ret->type = PIR_INT;
+ else
+ ret->type = PIR_REAL;
+ } 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<Value> 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") {
+ std::string s = gr->substring();
+ s = mklower(s);
+ 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();
}
- if(last < val.size())
- nw += val.substr(last,val.size()-last);
- val = nw;
- } else if(gr->getPatternName() == "par") {
+ return ret;
+ } else if(pn == "par") {
std::string thorn = gr->group(0)->substring();
std::string name = gr->group(1)->substring();
-
- bool found = find_val(thorn,name,val);
- if(found) {
- ;
+ if(gr->groupCount() == 3) {
+ std::ostringstream vn;
+ smart_ptr<Value> 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(thorn,keyi);
+ return ret;
+ }
} else {
- val += thorn;
- val += "::";
- val += name;
- }
- } else if(gr->getPatternName() == "name") {
- val += gr->substring();
- } else if(gr->getPatternName() == "num") {
- val += gr->substring();
- } else if(gr->getPatternName() == "var") {
- lookup_var(gr,val);
- } else if(gr->getPatternName() == "mexpr") {
- if(gr->groupCount()==1) {
- meval(gr->group(0),val);
- return;
+ ret = find_val(thorn,name);
+ return ret;
}
- std::string val2;
- meval(gr->group(0),val2);
- double v2 = atof(val2.c_str());
- for(int i=1;i < gr->groupCount();i += 2) {
- std::string val3;
- meval(gr->group(i+1),val3);
- double v3 = atof(val3.c_str());
- if(gr->group(i)->substring() == "*") {
- v2 *= v3;
+ 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 {
- v2 /= v3;
+ 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());
}
-// std::cout << "MEXPR: " << v2 << gr->group(i)->substring() << v3 << std::endl;
+ } else {
+ return meval(gr->group(0));
}
- std::ostringstream ostr;
- ostr << v2 << std::flush;
- val = ostr.str();
- } else if(gr->getPatternName() == "aexpr") {
- if(gr->groupCount()==1) {
- meval(gr->group(0),val);
- return;
+ } else if(pn == "quot") {
+ ret->type = PIR_STRING;
+ ret->sdata = 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<Value> v1 = meval(gr->group(0));
+ smart_ptr<Value> 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<Value> v1 = meval(gr->group(0));
+ smart_ptr<Value> 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<Value> v1 = meval(gr->group(0));
+ smart_ptr<Value> 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<Value> v1 = meval(gr->group(0));
+ std::string eqop = gr->group(1)->substring();
+ smart_ptr<Value> 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());
}
- std::string val2;
- meval(gr->group(0),val2);
- double v2 = atof(val2.c_str());
- for(int i=1;i < gr->groupCount();i += 2) {
- std::string val3;
- meval(gr->group(i+1),val3);
- double v3 = atof(val3.c_str());
- if(gr->group(i)->substring() == "+") {
- v2 += v3;
+ } else if(pn == "compexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ if(gr->groupCount()>0) {
+ std::string compop = gr->group(1)->substring();
+ smart_ptr<Value> 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<Value> v1 = meval(gr->group(0));
+ for(int i=1;i+1<gr->groupCount();i+=2) {
+ std::string addop = gr->group(i)->substring();
+ smart_ptr<Value> 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;
+ 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->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 {
- v2 -= v3;
+ 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());
}
-// std::cout << "AEXPR: " << v2 << gr->group(i)->substring() << v3 << std::endl;
+ v1 = ret;
}
- std::ostringstream ostr;
- ostr << v2 << std::flush;
- val = ostr.str();
- } else if(gr->getPatternName() == "func") {
- std::string func_name = gr->group(0)->substring();
- std::string arg;
- meval(gr->group(1),arg);
- std::stringstream ostr;
- if(func_name == "sin") {
- ostr << sin(atof(arg.c_str()));
- } else if(func_name == "cos") {
- ostr << cos(atof(arg.c_str()));
- } else if(func_name == "sqrt") {
- ostr << sqrt(atof(arg.c_str()));
- } else if(func_name == "tan") {
- ostr << tan(atof(arg.c_str()));
- } else if(func_name == "log") {
- ostr << log(atof(arg.c_str()));
- } else if(func_name == "exp") {
- ostr << exp(atof(arg.c_str()));
+ } else if(pn == "mexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ for(int i=1;i+1<gr->groupCount();i+=2) {
+ std::string mulop = gr->group(i)->substring();
+ smart_ptr<Value> 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 = v1->sdata + v2->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 {
+ 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;
}
- ostr << std::flush;
- val = ostr.str();
} else {
- std::cout << "Not handled[" << gr->getPatternName() << "]" << std::endl;
- abort();
+ 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<Value> eval_expr(std::string input) {
+ smart_ptr<Matcher> m = new Matcher(par_file_grammar,"eval",input.c_str());
+ smart_ptr<Value> ret;
+ if(m->matches()) {
+ ret = meval(m->group(0));
+ }
+ return ret;
+}
+
+void check_types(const char *thorn,int line,ValueType v,int t) {
+ 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 << "Parameter type mismatch ";
+ 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 << " != " << v << std::endl;
+ CCTK_Error(line,par.c_str(),thorn,msg.str().c_str());
}
}
@@ -190,39 +690,49 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
"inquot = ({var}|\\\\.|[^\\\\\"])*\n"
"fname = \\.?/[-\\./0-9a-zA-Z_]+\n"
"quot = \"{inquot}\"|{fname}\n"
- "num = [-+]?([0-9]+(\\.[0-9]*|)|\\.[0-9]+)(e[+-]?[0-9]+|)\n"
+ "num = (inf|([0-9]+(\\.[0-9]*|)|\\.[0-9]+)(e[+-]?[0-9]+|))\n"
"env = ENV\\{{name}\\}\n"
"var = \\$({env}|{name}|\\{{name}\\})\n"
- "mulop = [*/]\n"
- "mexpr = {value}( {mulop} {value})*\n"
+ "powexpr = {value}( \\*\\* {value})?\n"
+ "mulop = [*/%]\n"
+ "mexpr = {powexpr}( {mulop} {powexpr})*\n"
"addop = [+-]\n"
"aexpr = {mexpr}( {addop} {mexpr})*\n"
- "paren = \\( {aexpr} \\)\n"
- "par = {name} :: {name}\n"
- "func = {name} \\( {aexpr} \\)\n"
- "array = \\[ {aexpr}( , {aexpr})* \\]\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"
- "value = {func}|{paren}|{num}|{quot}|{par}|{name}|{var}\n"
+ "paren = \\( {expr} \\)\n"
+ "par = {name} :: {name}( {parindex})?\n"
+ "func = {name} \\( {expr} \\)\n"
+ "array = \\[ {expr}( , {expr})* \\]\n"
+
+ "value = {unop}?({par}|{func}|{paren}|{num}|{quot}|{name}|{var})\n"
+ "unop = [-!]\n"
"int = [0-9]+\n"
"index = \\[ {int} \\]\n"
+ "parindex = \\[ {expr} \\]\n"
"active = (?i:ActiveThorns)\n"
- "set = ({active}|{par}( {index}|)) = ({array}|{aexpr}){-skipeol}\n"
- "file = ( !DESC {quot}|)( ({set} )*)$\n";
+ "set = ({active} = ({quot}|{name})|{par}( {index}|) = ({array}|\\+?{expr})){-skipeol}\n"
+ "file = ^( !DESC {quot}|)( ({set}|{active}) )*$\n";
- smart_ptr<Grammar> g = new Grammar();
- compileFile(g,par_file_src,strlen(par_file_src));
+ compileFile(par_file_grammar,par_file_src,strlen(par_file_src));
std::string active;
- smart_ptr<Matcher> m2 = new Matcher(g,"file",buffer,buffersize);
+ smart_ptr<Matcher> m2 = new Matcher(par_file_grammar,"file",buffer,buffersize);
if(m2->matches()) {
int line = -1;
for(int i=0;i<m2->groupCount();i++) {
smart_ptr<Group> gr = m2->group(i);
if(gr->group(0)->getPatternName() == "active") {
- std::string val;
- meval(gr->group(1),val);
+ smart_ptr<Value> smv = meval(gr->group(1));
+ std::string val = smv->copy();
active += val;
active += ' ';
line = gr->line();
@@ -242,19 +752,40 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
key += thorn;
key += "::";
key += name;
+ const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str());
- smart_ptr<Group> index = gr->group("index");
+ smart_ptr<Group> index = par->group("parindex");
if(index.valid()) {
key += '[';
- key += index->group(0)->substring();
+ smart_ptr<Value> 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<Group> aexpr = gr->group("aexpr");
+ smart_ptr<Group> aexpr = gr->group("expr");
if(aexpr.valid()) {
- meval(aexpr,val);
- values[thorn][key] = val;
+ current_thorn = thorn;
+ smart_ptr<Value> smv = meval(aexpr);
+ val = smv->copy();
+ assert(smv.valid());
+ values[thorn][key] = smv;
+ std::cout << "set_function(" << key << "," << val << ")" << std::endl;
+ 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->type,data->type);
+ }
set_function(
strdup(key.c_str()),
strdup(val.c_str()),
@@ -264,9 +795,18 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
for(int i=0;i<arr->groupCount();i++) {
aexpr = arr->group(i);
std::ostringstream keyi;
- keyi << key << '[' << (i+1) << ']';
- meval(aexpr,val);
- values[thorn][keyi.str()] = val;
+ keyi << key << '[' << i << ']';
+ smart_ptr<Value> smv = meval(aexpr);
+ val = smv->copy();
+ values[thorn][keyi.str()] = smv;
+ std::cout << "set_function_array(" << keyi.str() << "," << val << ")" << std::endl;
+ 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->type,data->type);
+ }
set_function(
strdup(keyi.str().c_str()),
strdup(val.c_str()),
@@ -276,7 +816,7 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
}
}
} else {
- std::cout << "ERROR IN PARAMETER FILE: ";
+ std::cout << "ERROR IN PARAMETER FILE:" << std::endl;
m2->showError();
return 1;
}
diff --git a/src/piraha/Makefile b/src/piraha/Makefile
index 7528fc54..45e4f4dc 100644
--- a/src/piraha/Makefile
+++ b/src/piraha/Makefile
@@ -1,7 +1,7 @@
# Build the standalone tool
#
CXX = g++
-CXXFLAGS = -Wall
+CXXFLAGS = -Wall -Wreturn-type
SRCS = AutoGrammar.cc Bracket.cc Dot.cc End.cc \
Generic.cc Grammar.cc Group.cc ILiteral.cc \
Literal.cc Lookup.cc Matcher.cc Multi.cc \
diff --git a/src/piraha/Matcher.cc b/src/piraha/Matcher.cc
index dad67a67..55f042be 100644
--- a/src/piraha/Matcher.cc
+++ b/src/piraha/Matcher.cc
@@ -16,6 +16,7 @@ bool Matcher::matches() {
smart_ptr<Pattern> p = g->patterns.get(pat);
if(!p.valid()) {
std::cout << "Grammar does not contain \"" << pat << "\"" << std::endl;
+ std::cout << g->patterns << std::endl;
}
assert(p.valid());
pos = 0;
@@ -53,9 +54,9 @@ void Matcher::showError() {
start_of_previous_line[i] = 0;
for(int i=0;i<input_size;i++) {
if(i == max_pos) {
- std::cout << "In rule '" << inrule_max
- << "' Line=" << line << std::endl;
error_pos = i;
+ std::cout << "In rule '" << inrule_max
+ << "' Line=" << line << std::endl;
while(input[i] == '\n'||input[i] == '\r') {
line++;
for(int j=1;j<num_previous_lines;j++) {
diff --git a/src/piraha/Piraha.hpp b/src/piraha/Piraha.hpp
index 25892fbc..f16b6ae0 100644
--- a/src/piraha/Piraha.hpp
+++ b/src/piraha/Piraha.hpp
@@ -55,8 +55,10 @@ public:
smart_ptr<Group> group(const char *nm,int ix=0) {
for(unsigned int i=0;i<children.size();i++) {
if(children[i]->getPatternName() == nm) {
- if(ix-- == 0)
+ if(ix == 0) {
return children[i];
+ }
+ ix--;
}
}
smart_ptr<Group> ret;
@@ -100,10 +102,12 @@ public:
inline std::ostream& operator<<(std::ostream& o,JMap& jmap) {
typedef map<std::string,smart_ptr<Pattern> >::iterator mit;
mit mb = jmap.m.begin();
- mit me = jmap.m.begin();
+ mit me = jmap.m.end();
+ o << "{";
for(mit i = mb; i != me;++i) {
o << "[" << i->first << "]";
}
+ o << "}";
return o;
}
diff --git a/src/piraha/smart_ptr.cc b/src/piraha/smart_ptr.cc
index e1d26b71..b2e5a826 100644
--- a/src/piraha/smart_ptr.cc
+++ b/src/piraha/smart_ptr.cc
@@ -1,3 +1,3 @@
#include "smart_ptr.hpp"
-std::vector<void*> ptrs;
+std::set<void*> *ptrs = new std::set<void*>();
diff --git a/src/piraha/smart_ptr.hpp b/src/piraha/smart_ptr.hpp
index 0ac761b3..2c6f7d28 100644
--- a/src/piraha/smart_ptr.hpp
+++ b/src/piraha/smart_ptr.hpp
@@ -7,40 +7,32 @@
#ifndef SMART_PTR_HPP
#define SMART_PTR_HPP
#include <assert.h>
-#include <vector>
+#include <set>
#include <iostream>
#ifndef NULL
#define NULL ((void*)0)
#endif
-extern std::vector<void*> ptrs;
+extern std::set<void*> *ptrs;
-#ifndef NDEBUG
-inline void add(std::vector<void*>& v,void *t) {
+#ifdef NDEBUG
+inline void add(std::set<void*>& v,void *t) {
if(t == NULL)
return;
- for(std::vector<void*>::iterator i=v.begin();i != v.end();++i) {
- assert(*i != t);
- }
- v.push_back(t);
+ assert(v.find(t) == v.end());
+ v.insert(t);
}
-inline void remove(std::vector<void*>& v,void* t) {
- if(t == NULL)
- return;
- for(std::vector<void*>::iterator i=v.begin();i != v.end();++i) {
- if(*i == t) {
- v.erase(i);
- return;
- }
- }
- assert(false);
+inline void remove(std::set<void*>& v,void* t) {
+ std::set<void*>::iterator it = v.find(t);
+ assert(it != v.end());
+ v.erase(it);
}
#else
-inline void add(std::vector<void*>& v,void* t) {
+inline void add(std::set<void*>& v,void* t) {
}
-inline void remove(std::vector<void*>& v,void* t) {
+inline void remove(std::set<void*>& v,void* t) {
}
#endif
@@ -55,12 +47,12 @@ class smart_ptr_guts {
bool array;
smart_ptr_guts(int rc,T *p,bool array_) : ref_count(rc), ptr(p), array(array_) {
if(ptr != NULL) {
- add(ptrs,(void*)ptr);
+ add(*ptrs,(void*)ptr);
}
}
~smart_ptr_guts() {
if(ptr != NULL) {
- remove(ptrs,(void*)ptr);
+ remove(*ptrs,(void*)ptr);
if(array)
delete[] ptr;
else
@@ -155,7 +147,7 @@ class smart_ptr {
assert(guts != NULL);
return guts->ptr;
}
- bool valid() {
+ bool valid() const {
return guts != NULL && guts->ptr != NULL;
}
int ref_count() {