From 4730bc03f50318da9432bbd17f7c9cc91de1eb21 Mon Sep 17 00:00:00 2001 From: sbrandt Date: Mon, 25 Feb 2013 16:54:00 +0000 Subject: Change the parameter parser to Piraha git-svn-id: http://svn.cactuscode.org/flesh/trunk@4960 17b73243-c579-4c4c-a9d2-2d5706c11dac --- src/make.code.defn | 2 +- src/piraha/AutoGrammar.cc | 388 ++++++++++++++++++++++++++++++++++++++++++++++ src/piraha/Bracket.cc | 114 ++++++++++++++ src/piraha/Call.cc | 280 +++++++++++++++++++++++++++++++++ src/piraha/Dot.cc | 13 ++ src/piraha/End.cc | 5 + src/piraha/Generic.cc | 35 +++++ src/piraha/Grammar.cc | 24 +++ src/piraha/Group.cc | 39 +++++ src/piraha/ILiteral.cc | 22 +++ src/piraha/Literal.cc | 18 +++ src/piraha/Lookup.cc | 30 ++++ src/piraha/Makefile | 12 ++ src/piraha/Matcher.cc | 85 ++++++++++ src/piraha/Multi.cc | 17 ++ src/piraha/Or.cc | 32 ++++ src/piraha/Piraha.hpp | 294 +++++++++++++++++++++++++++++++++++ src/piraha/ReParse.cc | 190 +++++++++++++++++++++++ src/piraha/Seq.cc | 27 ++++ src/piraha/Start.cc | 5 + src/piraha/make.code.defn | 6 + src/piraha/size.py | 7 + src/piraha/smart_ptr.cc | 3 + src/piraha/smart_ptr.hpp | 177 +++++++++++++++++++++ src/util/ParseFile.c | 49 +++--- 25 files changed, 1851 insertions(+), 23 deletions(-) create mode 100644 src/piraha/AutoGrammar.cc create mode 100644 src/piraha/Bracket.cc create mode 100644 src/piraha/Call.cc create mode 100644 src/piraha/Dot.cc create mode 100644 src/piraha/End.cc create mode 100644 src/piraha/Generic.cc create mode 100644 src/piraha/Grammar.cc create mode 100644 src/piraha/Group.cc create mode 100644 src/piraha/ILiteral.cc create mode 100644 src/piraha/Literal.cc create mode 100644 src/piraha/Lookup.cc create mode 100644 src/piraha/Makefile create mode 100644 src/piraha/Matcher.cc create mode 100644 src/piraha/Multi.cc create mode 100644 src/piraha/Or.cc create mode 100644 src/piraha/Piraha.hpp create mode 100644 src/piraha/ReParse.cc create mode 100644 src/piraha/Seq.cc create mode 100644 src/piraha/Start.cc create mode 100644 src/piraha/make.code.defn create mode 100644 src/piraha/size.py create mode 100644 src/piraha/smart_ptr.cc create mode 100644 src/piraha/smart_ptr.hpp (limited to 'src') diff --git a/src/make.code.defn b/src/make.code.defn index f11a81f4..6d3374bc 100644 --- a/src/make.code.defn +++ b/src/make.code.defn @@ -1,3 +1,3 @@ # $Header$ SRCS = -SUBDIRS = IO comm util main schedule gnu +SUBDIRS = IO comm util main schedule gnu piraha diff --git a/src/piraha/AutoGrammar.cc b/src/piraha/AutoGrammar.cc new file mode 100644 index 00000000..2ecfb741 --- /dev/null +++ b/src/piraha/AutoGrammar.cc @@ -0,0 +1,388 @@ +#include "Piraha.hpp" + +smart_ptr AutoGrammar::reparserGenerator() { + smart_ptr g = new Grammar(); + g->patterns.put("named",new Seq( + new Literal('{'), + new Lookup("name",g), + new Literal('}'),NULL)); + g->patterns.put("neg",new Literal('^')); + g->patterns.put("backref",new Seq( + new Literal('\\'), + (new Bracket(false)) + ->addRange('1','9'),NULL)); + g->patterns.put("range",new Seq( + new Lookup("cchar",g), + new Literal('-'), + new Lookup("cchar",g),NULL)); + g->patterns.put("pelem",new Or( + new Seq( + new Or( + new Lookup("named",g), + new Lookup("dot",g), + new Lookup("backref",g), + new Lookup("literal",g), + new Lookup("charclass",g), + new Lookup("group",g),NULL), + new Or( + new Lookup("quant",g), + new Nothing(),NULL),NULL), + new Or( + new Lookup("start",g), + new Lookup("end",g), + new Lookup("boundary",g),NULL),NULL)); + g->patterns.put("group_inside",new Seq( + new Lookup("pelems",g), + new Multi(new Seq( + new Literal('|'), + new Lookup("pelems",g),NULL),0,max_int), + new Or( + new Seq( + new Lookup("nothing",g), + new Literal('|'),NULL), + new Nothing(),NULL),NULL)); + g->patterns.put("lookahead",new Seq( + new Literal('?'), + new Literal('='),NULL)); + g->patterns.put("boundary",new Seq( + new Literal('\\'), + new Literal('b'),NULL)); + g->patterns.put("dot",new Literal('.')); + g->patterns.put("ign_on",new Seq( + new Literal('?'), + new Literal('i'), + new Literal(':'),NULL)); + g->patterns.put("echar",new Literal('-')); + g->patterns.put("hex",new Multi((new Bracket(false)) + ->addRange('0','9') + ->addRange('A','F') + ->addRange('a','f') + ,4,4)); + g->patterns.put("name",new Seq( + new Multi(new Literal('-'),0,1), + (new Bracket(false)) + ->addRange(':',':') + ->addRange('A','Z') + ->addRange('_','_') + ->addRange('a','z') + , + new Multi((new Bracket(false)) + ->addRange('0',':') + ->addRange('A','Z') + ->addRange('_','_') + ->addRange('a','z') + ,0,max_int),NULL)); + g->patterns.put("end",new Literal('$')); + g->patterns.put("cchar",new Or( + new Seq( + new Literal('\\'), + new Literal('u'), + new Lookup("hex",g),NULL), + new Seq( + new Literal('\\'), + (new Bracket(true)),NULL), + (new Bracket(true)) + ->addRange('-','-') + ->addRange('\\',']') + ,NULL)); + g->patterns.put("neglookahead",new Seq( + new Literal('?'), + new Literal('!'),NULL)); + g->patterns.put("charclass",new Seq( + new Literal('['), + new Multi(new Lookup("neg",g),0,1), + new Multi(new Or( + new Lookup("range",g), + new Lookup("echar",g),NULL),0,1), + new Multi(new Or( + new Lookup("range",g), + new Lookup("cchar",g),NULL),0,max_int), + new Multi(new Lookup("echar",g),0,1), + new Literal(']'),NULL)); + g->patterns.put("quantmax",new Seq( + new Literal(','), + new Multi(new Lookup("num",g),0,1),NULL)); + g->patterns.put("pelems",new Seq( + new Lookup("pelem",g), + new Multi(new Lookup("pelem",g),0,max_int),NULL)); + g->patterns.put("ign_off",new Seq( + new Literal('?'), + new Literal('-'), + new Literal('i'), + new Literal(':'),NULL)); + g->patterns.put("num",new Multi((new Bracket(false)) + ->addRange('0','9') + ,1,max_int)); + g->patterns.put("pattern",new Seq( + new Start(), + new Or( + new Lookup("group_inside",g), + new Nothing(),NULL), + new End(),NULL)); + g->patterns.put("start",new Literal('^')); + g->patterns.put("quant",new Or( + new Literal('+'), + new Literal('*'), + new Literal('?'), + new Seq( + new Literal('{'), + new Lookup("num",g), + new Multi(new Lookup("quantmax",g),0,1), + new Literal('}'),NULL),NULL)); + g->patterns.put("nothing",new Nothing()); + g->patterns.put("group",new Seq( + new Literal('('), + new Or( + new Lookup("ign_on",g), + new Lookup("ign_off",g), + new Lookup("lookahead",g), + new Lookup("neglookahead",g), + new Nothing(),NULL), + new Or( + new Lookup("group_inside",g), + new Nothing(),NULL), + new Literal(')'),NULL)); + g->patterns.put("literal",new Or( + new Seq( + new Literal('\\'), + new Literal('u'), + new Lookup("hex",g),NULL), + new Seq( + new Literal('\\'), + (new Bracket(true)) + ->addRange('b','b'), + NULL + ), + (new Bracket(true)) + ->addRange('$','$') + ->addRange('(','+') + ->addRange('.','.') + ->addRange('?','?') + ->addRange('[','^') + ->addRange('{','}') + ,NULL)); + return g; +} + +smart_ptr AutoGrammar::fileParserGenerator() { + smart_ptr g = new Grammar(); + g->patterns.put("named",new Seq( + new Literal('{'), + new Lookup("name",g), + new Literal('}'),NULL)); + g->patterns.put("neg",new Literal('^')); + g->patterns.put("backref",new Seq( + new Literal('\\'), + (new Bracket(false)) + ->addRange('1','9'),NULL + )); + g->patterns.put("range",new Seq( + new Lookup("cchar",g), + new Literal('-'), + new Lookup("cchar",g),NULL)); + g->patterns.put("pelem",new Or( + new Seq( + new Or( + new Lookup("named",g), + new Lookup("dot",g), + new Lookup("backref",g), + new Lookup("literal",g), + new Lookup("charclass",g), + new Lookup("group",g),NULL), + new Or( + new Lookup("quant",g), + new Nothing(),NULL),NULL), + new Or( + new Lookup("start",g), + new Lookup("end",g), + new Lookup("boundary",g),NULL),NULL)); + g->patterns.put("pelems_next",new Seq( + new Multi(new Lookup("s",g),0,1), + new Literal('|'), + new Multi(new Lookup("s",g),0,1), + new Lookup("pelem",g), + new Multi(new Seq( + new Multi(new Lookup("s0",g),0,1), + new Lookup("pelem",g),NULL),0,max_int),NULL)); + g->patterns.put("group_inside",new Seq( + new Lookup("pelems",g), + new Multi(new Seq( + new Literal('|'), + new Lookup("pelems",g),NULL),0,max_int), + new Or( + new Seq( + new Multi(new Lookup("s0",g),0,1), + new Lookup("nothing",g), + new Literal('|'),NULL), + new Nothing(),NULL), + new Multi(new Lookup("s",g),0,1),NULL)); + g->patterns.put("lookahead",new Seq( + new Literal('?'), + new Literal('='),NULL)); + g->patterns.put("boundary",new Seq( + new Literal('\\'), + new Literal('b'),NULL)); + g->patterns.put("dot",new Literal('.')); + g->patterns.put("pelems_top",new Seq( + new Lookup("pelem",g), + new Multi(new Seq( + new Multi(new Lookup("s0",g),0,1), + new Lookup("pelem",g),NULL),0,max_int),NULL)); + g->patterns.put("ign_on",new Seq( + new Literal('?'), + new Literal('i'), + new Literal(':'),NULL)); + g->patterns.put("echar",new Literal('-')); + g->patterns.put("hex",new Multi((new Bracket(false)) + ->addRange('0','9') + ->addRange('A','F') + ->addRange('a','f') + ,4,4)); + g->patterns.put("file",new Seq( + new Start(), + new Multi(new Lookup("-s",g),0,1), + new Lookup("rule",g), + new Multi(new Seq( + new Multi(new Lookup("-s",g),0,1), + new Lookup("rule",g),NULL),0,max_int), + new Multi(new Lookup("-s",g),0,1), + new End(),NULL)); + g->patterns.put("name",new Seq( + new Multi(new Literal('-'),0,1), + (new Bracket(false)) + ->addRange(':',':') + ->addRange('A','Z') + ->addRange('_','_') + ->addRange('a','z') + , + new Multi((new Bracket(false)) + ->addRange('0',':') + ->addRange('A','Z') + ->addRange('_','_') + ->addRange('a','z') + ,0,max_int),NULL)); + g->patterns.put("rule",new Seq( + new Lookup("name",g), + new Lookup("-w",g), + new Literal('='), + new Lookup("-w",g), + new Lookup("pattern",g),NULL)); + g->patterns.put("end",new Literal('$')); + g->patterns.put("cchar",new Or( + new Seq( + new Literal('\\'), + new Literal('u'), + new Lookup("hex",g),NULL), + new Seq( + new Literal('\\'), + (new Bracket(true)) + ,NULL), + (new Bracket(true)) + ->addRange('-','-') + ->addRange('\\',']') + ,NULL)); + g->patterns.put("s0",new Multi((new Bracket(false)) + ->addRange('\t','\t') + ->addRange(' ',' ') + ,1,max_int)); + g->patterns.put("neglookahead",new Seq( + new Literal('?'), + new Literal('!'),NULL)); + g->patterns.put("charclass",new Seq( + new Literal('['), + new Multi(new Lookup("neg",g),0,1), + new Multi(new Or( + new Lookup("range",g), + new Lookup("echar",g),NULL),0,1), + new Multi(new Or( + new Lookup("range",g), + new Lookup("cchar",g),NULL),0,max_int), + new Multi(new Lookup("echar",g),0,1), + new Literal(']'),NULL)); + g->patterns.put("quantmax",new Seq( + new Literal(','), + new Multi(new Lookup("num",g),0,1),NULL)); + g->patterns.put("group_top",new Seq( + new Lookup("pelems_top",g), + new Multi(new Lookup("pelems_next",g),0,max_int), + new Or( + new Seq( + new Multi(new Lookup("s",g),0,1), + new Lookup("nothing",g), + new Literal('|'),NULL), + new Nothing(),NULL),NULL)); + g->patterns.put("pelems",new Seq( + new Multi(new Seq( + new Multi(new Lookup("s",g),0,1), + new Lookup("pelem",g),NULL),1,max_int), + new Multi(new Lookup("s",g),0,1),NULL)); + g->patterns.put("ign_off",new Seq( + new Literal('?'), + new Literal('-'), + new Literal('i'), + new Literal(':'),NULL)); + g->patterns.put("w",new Multi((new Bracket(false)) + ->addRange('\t','\t') + ->addRange(' ',' ') + ,0,max_int)); + g->patterns.put("num",new Multi((new Bracket(false)) + ->addRange('0','9') + ,1,max_int)); + g->patterns.put("s",new Multi(new Or( + (new Bracket(false)) + ->addRange('\t','\n') + ->addRange('\r','\r') + ->addRange(' ',' ') + , + new Seq( + new Literal('#'), + new Multi(new Dot(),0,max_int),NULL),NULL),1,max_int)); + g->patterns.put("pattern",new Or( + new Lookup("group_top",g), + new Nothing(),NULL)); + g->patterns.put("start",new Literal('^')); + g->patterns.put("quant",new Or( + new Literal('+'), + new Literal('*'), + new Literal('?'), + new Seq( + new Literal('{'), + new Lookup("num",g), + new Multi(new Lookup("quantmax",g),0,1), + new Literal('}'),NULL),NULL)); + g->patterns.put("nothing",new Nothing()); + g->patterns.put("group",new Seq( + new Literal('('), + new Or( + new Lookup("ign_on",g), + new Lookup("ign_off",g), + new Lookup("lookahead",g), + new Lookup("neglookahead",g), + new Nothing(),NULL), + new Or( + new Lookup("group_inside",g), + new Nothing(),NULL), + new Literal(')'),NULL)); + g->patterns.put("literal",new Or( + new Seq( + new Literal('\\'), + new Literal('u'), + new Lookup("hex",g),NULL), + new Seq( + new Literal('\\'), + (new Bracket(true)) + ->addRange('1','9') + ->addRange('b','b') + ,NULL), + (new Bracket(true)) + ->addRange('\n','\n') + ->addRange('\r','\r') + ->addRange('$','$') + ->addRange('(','+') + ->addRange('.','.') + ->addRange('?','?') + ->addRange('[','^') + ->addRange('{','}') + ,NULL)); + return g; +} diff --git a/src/piraha/Bracket.cc b/src/piraha/Bracket.cc new file mode 100644 index 00000000..2856a670 --- /dev/null +++ b/src/piraha/Bracket.cc @@ -0,0 +1,114 @@ +#include "Piraha.hpp" + +typedef vector >::iterator range_iter; + +bool Range::match(Matcher *m) { + if(m->pos - m->input_size >= 0) + return false; + char c = m->input[m->pos]; + if(lo <= c && c <= hi) { + return true; + } else { + return false; + } +} + +Bracket::Bracket(bool b) : neg(b), ranges() {} + +Bracket *Bracket::addRange(char lo,char hi) { + bool done = false; + while(!done) { + done = true; + for(range_iter ri = ranges.begin();ri != ranges.end(); ++ri) { + smart_ptr r = *ri; + if(hi < r->lo || r->hi < lo) { + // no intersection + continue; + } else { + lo = std::min(lo,r->lo); + hi = std::max(hi,r->hi); + ranges.erase(ri); + done = false; + break; + } + } + } + ranges.push_back(new Range(lo,hi)); + return this; +}; + +Bracket *Bracket::addRange(char lo,char hi,bool ign) { + if(ign) { + char lolc = lc_(lo); + char hilc = lc_(hi); + char louc = uc_(lo); + char hiuc = uc_(hi); + if(lolc == louc && hilc == hiuc) { + ranges.push_back(new Range(lo,hi)); + } else { + ranges.push_back(new Range(lolc,hilc)); + ranges.push_back(new Range(louc,hiuc)); + } + } else { + ranges.push_back(new Range(lo,hi)); + } + return this; +}; + +static void fail(Bracket *b,Matcher *m) { + typedef vector >::iterator range_iter; + Bracket bex; + if(m->pos == m->max_pos+1) { + for(range_iter r = b->ranges.begin();r != b->ranges.end(); ++r) { + bex.addRange((*r)->lo,(*r)->hi); + } + m->fail(&bex); + } +} + +bool Bracket::match(Matcher *m) { + if(m->pos >= (int)m->input_size) + return false; + for(range_iter r = ranges.begin();r != ranges.end(); ++r) { + if((*r)->match(m)) { + if(neg) { + fail(this,m); + return false; + } else { + m->max_pos = std::max(m->pos,m->max_pos); + m->pos++; + return true; + } + } + } + if(!neg) { + fail(this,m); + return false; + } else { + m->pos++; + m->max_pos = std::max(m->pos,m->max_pos); + return true; + } +} + +std::ostream& operator<<(std::ostream& o,Bracket& b) { + for(range_iter r = b.ranges.begin();r != b.ranges.end(); ++r) { + char lo = (*r)->lo, hi = (*r)->hi; + if(lo == hi) { + if(lo == '-') { + o << "\\-"; + } else if(lo == '\n') { + o << "\\n"; + } else if(lo == '\r') { + o << "\\r"; + } else if(lo == '\t') { + o << "\\t"; + } else { + o << lo; + } + } else { + o << lo << '-' << hi; + } + } + return o; +} diff --git a/src/piraha/Call.cc b/src/piraha/Call.cc new file mode 100644 index 00000000..766ebf9a --- /dev/null +++ b/src/piraha/Call.cc @@ -0,0 +1,280 @@ +#include +#include +#include "Piraha.hpp" +#include +#include +#include "cctk_Parameter.h" +#include +#include + +#define VAR(X) " " #X "=" << X + +extern "C" int CCTK_ParameterFilename(int len, char *filename); + +std::map > values; +typedef std::map >::iterator th_iter; +typedef std::map::iterator nm_iter; + +// 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) { + 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; + } + } + const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str()); + if(data == NULL) + return false; + ret = data->defval; + return true; +} + +bool lookup_var(smart_ptr gr,std::string& res) { + 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; + } + } 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; + } else if(gr->group(0)->substring() == "pi") { + std::ostringstream ostr; + ostr << (4.0*atan2(1,1)) << std::flush; + res = ostr.str(); + return true; + } + return false; +} + +// Converts a value to a string +void meval(smart_ptr 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 inquot = gr->group(0); + val = inquot->substring(); + int last = 0; + std::string nw; + for(int i=0;i < inquot->groupCount();i++) { + smart_ptr 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(); + } + } + if(last < val.size()) + nw += val.substr(last,val.size()-last); + val = nw; + } else if(gr->getPatternName() == "par") { + std::string thorn = gr->group(0)->substring(); + std::string name = gr->group(1)->substring(); + + bool found = find_val(thorn,name,val); + if(found) { + ; + } 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; + } + 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 { + v2 /= v3; + } +// std::cout << "MEXPR: " << v2 << gr->group(i)->substring() << v3 << std::endl; + } + 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; + } + 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 { + v2 -= v3; + } +// std::cout << "AEXPR: " << v2 << gr->group(i)->substring() << v3 << std::endl; + } + 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())); + } + ostr << std::flush; + val = ostr.str(); + } else { + std::cout << "Not handled[" << gr->getPatternName() << "]" << std::endl; + abort(); + } +} + +extern "C" int 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" + + "# 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" + "inquot = ({var}|\\\\.|[^\\\\\"])*\n" + "quot = \"{inquot}\"\n" + "num = [-+]?([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" + "addop = [+-]\n" + "aexpr = {mexpr}( {addop} {mexpr})*\n" + "paren = \\( {aexpr} \\)\n" + "par = {name} :: {name}\n" + "func = {name} \\( {aexpr} \\)\n" + "array = \\[ {aexpr}( , {aexpr})* \\]\n" + + "value = {func}|{paren}|{num}|{quot}|{par}|{name}|{var}\n" + + "int = [0-9]+\n" + "index = \\[ {int} \\]\n" + "active = (?i:ActiveThorns)\n" + "set = ({active}|{par}( {index}|)) = ({array}|{aexpr})\n" + "file = ( !DESC {quot}|)( ({set} )*)$\n"; + + smart_ptr g = new Grammar(); + compileFile(g,par_file_src,strlen(par_file_src)); + + std::string active; + smart_ptr m2 = new Matcher(g,"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") { + std::string val; + meval(gr->group(1),val); + 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; + + smart_ptr index = gr->group("index"); + if(index.valid()) { + key += '['; + key += index->group(0)->substring(); + key += ']'; + } + + std::string val; + smart_ptr aexpr = gr->group("aexpr"); + if(aexpr.valid()) { + meval(aexpr,val); + values[thorn][key] = val; + 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+1) << ']'; + meval(aexpr,val); + values[thorn][keyi.str()] = val; + set_function( + strdup(keyi.str().c_str()), + strdup(val.c_str()), + aexpr->line()); + } + } + } + } + } else { + std::cout << "ERROR IN PARAMETER FILE: "; + m2->showError(); + return 1; + } + return 0; +} diff --git a/src/piraha/Dot.cc b/src/piraha/Dot.cc new file mode 100644 index 00000000..be0a6e75 --- /dev/null +++ b/src/piraha/Dot.cc @@ -0,0 +1,13 @@ +#include "Piraha.hpp" + +bool Dot::match(Matcher *m) { + if(m->pos - m->input_size >= 0) + return false; + char c = m->input[m->pos]; + if(c == '\n') { + return false; + } else { + m->pos++; + return true; + } +} diff --git a/src/piraha/End.cc b/src/piraha/End.cc new file mode 100644 index 00000000..815f9bc7 --- /dev/null +++ b/src/piraha/End.cc @@ -0,0 +1,5 @@ +#include "Piraha.hpp" + +bool End::match(Matcher *m) { + return m->pos == (int)m->input_size; +} diff --git a/src/piraha/Generic.cc b/src/piraha/Generic.cc new file mode 100644 index 00000000..5026828b --- /dev/null +++ b/src/piraha/Generic.cc @@ -0,0 +1,35 @@ +#include "Piraha.hpp" +#include + +void read_file(const char *file,std::string& buf) { + std::ifstream in; + in.open(file); + while(true) { + int c = in.get(); + if(c < 0) + break; + buf += (char)c; + } + in.close(); +} + +int main(int argc,char **argv) { + if(argc != 3) { + std::cerr << "usage: generic grammar input" << std::endl; + return 2; + } + + std::string grammar_file, input_file; + read_file(argv[1],grammar_file); + read_file(argv[2],input_file); + + smart_ptr g = new Grammar(); + compileFile(g,grammar_file.c_str()); + smart_ptr mg = new Matcher (g,g->default_rule.c_str(),input_file.c_str()); + if(mg->matches()) { + mg->dump(); + } else { + mg->showError(); + } + return 0; +} diff --git a/src/piraha/Grammar.cc b/src/piraha/Grammar.cc new file mode 100644 index 00000000..9cb7f0b0 --- /dev/null +++ b/src/piraha/Grammar.cc @@ -0,0 +1,24 @@ +#include "Piraha.hpp" + +extern smart_ptr compile(smart_ptr g,bool ignCase,smart_ptr gram); + +smart_ptr pegGrammar = AutoGrammar::reparserGenerator(); + +void Grammar::compile(std::string name,smart_ptr g) { + default_rule = name; + smart_ptr p = ::compile(g,false,this); + patterns.put(name,p); +} +void Grammar::compile(std::string name,std::string pattern) { + default_rule = name; + smart_ptr m = new Matcher(pegGrammar,"pattern",pattern.c_str()); + smart_ptr g = m.dup(); + if(m->matches()) { + smart_ptr p = ::compile(g,false,this); + patterns.put(name,p); + } else { + std::cout << "Could not compile(" << name << "," << pattern << ")" << std::endl; + std::cout << "pos = " << m->pos << std::endl; + assert(false); + } +} diff --git a/src/piraha/Group.cc b/src/piraha/Group.cc new file mode 100644 index 00000000..732a637a --- /dev/null +++ b/src/piraha/Group.cc @@ -0,0 +1,39 @@ +#include "Piraha.hpp" + +void Group::dump(int indent) { + for(int i=0;i >::iterator group_iter; + for(group_iter gi = children.begin(); + gi != children.end(); + ++gi) { + (*gi)->dump(indent+2); + } +} + +std::string Group::substring() { + std::string sub; + for(int i=start_;ipos >= (int)m->input_size ) + return false; + char c = m->input[m->pos]; + if(c == uc || c == lc) { + m->max_pos = std::max(m->pos,m->max_pos); + m->pos++; + return true; + } else { + if(m->pos == m->max_pos+1) { + Bracket bex; + bex.addRange(lc,lc); + bex.addRange(uc,uc); + m->fail(&bex); + } + return false; + } +} diff --git a/src/piraha/Literal.cc b/src/piraha/Literal.cc new file mode 100644 index 00000000..eedae466 --- /dev/null +++ b/src/piraha/Literal.cc @@ -0,0 +1,18 @@ +#include "Piraha.hpp" + +bool Literal::match(Matcher *m) { + if(m->pos - m->input_size >= 0) + return false; + if(m->input[m->pos] == c) { + m->max_pos = std::max(m->pos,m->max_pos); + m->pos++; + return true; + } else { + if(m->pos == m->max_pos+1) { + Bracket bex; + bex.addRange(c,c); + m->fail(&bex); + } + return false; + } +} diff --git a/src/piraha/Lookup.cc b/src/piraha/Lookup.cc new file mode 100644 index 00000000..ed42e1d1 --- /dev/null +++ b/src/piraha/Lookup.cc @@ -0,0 +1,30 @@ +#include "Piraha.hpp" + +Lookup::Lookup(std::string name_,smart_ptr g) : gram(g), name(name_), capture(true) { + if(name[0] == '-') { + capture = false; + name = name.substr(1); + } +} + +bool Lookup::match(Matcher *m) { + smart_ptr p = gram->patterns.get(name); + if(!p.valid()) std::cout << "Lookup of pattern [" << name << "] failed. Jmap = " << gram->patterns << std::endl; + assert(p.valid()); + vector > chSave = m->children; + m->children.clear(); + int s = m->pos; + std::string save_name = m->inrule; + m->inrule += "::"; + m->inrule += name; + bool b = p->match(m); + m->inrule = save_name; + int e = m->pos; + if(b) { + smart_ptr g = new Group(name,m->input,s,e,m->children); + if(capture) + chSave.push_back(g); + } + m->children = chSave; + return b; +} diff --git a/src/piraha/Makefile b/src/piraha/Makefile new file mode 100644 index 00000000..4463a251 --- /dev/null +++ b/src/piraha/Makefile @@ -0,0 +1,12 @@ +# Build the standalone tool +# +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 \ + Or.cc ReParse.cc Seq.cc smart_ptr.cc Start.cc + +generic : $(SRCS) Piraha.hpp smart_ptr.hpp + g++ -Wall -I . -g -o generic $(SRCS) + +clean : + rm -f generic diff --git a/src/piraha/Matcher.cc b/src/piraha/Matcher.cc new file mode 100644 index 00000000..f1a24750 --- /dev/null +++ b/src/piraha/Matcher.cc @@ -0,0 +1,85 @@ +#include +#include "Piraha.hpp" + +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) { + inrule = pat_; + if(input_size < 0) + input_size=strlen(input); +} + +bool Matcher::matches() { + smart_ptr p = g->patterns.get(pat); + if(!p.valid()) { + std::cout << "Grammar does not contain \"" << pat << "\"" << std::endl; + } + assert(p.valid()); + pos = 0; + max_pos = -1; + err_pos = -1; + children.clear(); + bool b = p->match(this); + end_ = pos; + return b; +} + +void Matcher::fail(Bracket *br) { + for(unsigned int i=0;iranges.size();i++) { + fail(br->ranges[i]->lo,br->ranges[i]->hi); + } +} + +void Matcher::fail(char lo,char hi) { + if(pos == max_pos+1) { + if(err_pos < pos) + expected.ranges.clear(); + expected.addRange(lo,hi); + inrule_max = inrule; + err_pos = pos; + } +} + +void Matcher::showError() { + int line = 1; + int error_pos = -1; + const int num_previous_lines = 4; + int start_of_line = 0; + int start_of_previous_line[num_previous_lines]; + for(int i=0;i +#include "Piraha.hpp" + +bool Multi::match(Matcher *m) { + unsigned int save; + int iter = 0; + while(true) { + save = m->pos; + if(!pattern->match(m)) + break; + if(save-m->pos == 0) + return minv <= iter && iter <= maxv; + iter++; + } + m->pos = save; + return minv <= iter && iter <= maxv; +} diff --git a/src/piraha/Or.cc b/src/piraha/Or.cc new file mode 100644 index 00000000..eebf2e74 --- /dev/null +++ b/src/piraha/Or.cc @@ -0,0 +1,32 @@ +#include +#include +#include "Piraha.hpp" + +Or::Or(Pattern *p,...) : patterns() { + va_list ap; + va_start(ap,p); + patterns.push_back(p); + while(true) { + Pattern *pat = va_arg(ap,Pattern*); + if(pat == NULL) + break; + //std::cout << "pat=" << pat->fmt() << std::endl; + patterns.push_back(pat); + assert(patterns.size()<7); + } + va_end(ap); +} + +bool Or::match(Matcher *m) { + typedef vector >::iterator pattern_iter; + int save = m->pos; + vector > chSave; + chSave = m->children; + for(pattern_iter p = patterns.begin();p != patterns.end();++p) { + m->pos = save; + m->children = chSave; + if((*p)->match(m)) + return true; + } + return false; +} diff --git a/src/piraha/Piraha.hpp b/src/piraha/Piraha.hpp new file mode 100644 index 00000000..3ff07d6d --- /dev/null +++ b/src/piraha/Piraha.hpp @@ -0,0 +1,294 @@ +#ifndef PIRAHA_HPP +#define PIRAHA_HPP +#include +#include +#include +#include +#include +#include + +const int max_int = 10000; + +using std::map; +using std::vector; + +inline char uc_(char a) { + if(a >= 'a' && a <= 'z') + return a + 'A' - 'a'; + else + return a; +} + +inline char lc_(char a) { + if(a >= 'A' && a <= 'Z') + return a + 'a' - 'A'; + else + return a; +} + +class Group { +public: + std::string pattern; + const char *input; + int start_,end_; + vector > children; + + Group(std::string p,const char *input_) + : pattern(p), input(input_), start_(0), end_(0), children() {} + Group(std::string p,const char *input_,int s,int e, + vector > ch) + : pattern(p), input(input_), start_(s), end_(e), children(ch) {} + + virtual ~Group() {} + + int start() { return start_; } + int end() { return end_; } + int childCount(), line(); + std::string getPatternName(); + std::string substring(); + smart_ptr child(int i); + void dump(int indent=0); + int groupCount() { return children.size(); } + smart_ptr group(int i) { return children[i]; } + smart_ptr group(const char *nm,int ix=0) { + for(unsigned int i=0;igetPatternName() == nm) { + if(ix-- == 0) + return children[i]; + } + } + smart_ptr ret; + return ret; + } +}; + +class Grammar; + +class Matcher; + +class Pattern { +public: + virtual bool match(Matcher *m)=0; + Pattern() {} + virtual ~Pattern() {} + virtual std::string fmt() { return "blank"; } +}; + +class JMap { + map > m; +public: + JMap() : m() {} + smart_ptr get(std::string key) { + typedef map >::iterator mit; + mit it = m.find(key); + mit me = m.end(); + if(it == me) { + return NULL; + } + smart_ptr res = m[key]; + assert(res.valid()); + return res; + } + void put(std::string key,smart_ptr p) { + assert(p.valid()); + m[key] = p; + } + friend std::ostream& operator<<(std::ostream&,JMap&); +}; +inline std::ostream& operator<<(std::ostream& o,JMap& jmap) { + typedef map >::iterator mit; + mit mb = jmap.m.begin(); + mit me = jmap.m.begin(); + for(mit i = mb; i != me;++i) { + o << "[" << i->first << "]"; + } + return o; +} + + +class Grammar { +public: + Grammar() {} + virtual ~Grammar() {} + JMap patterns; + void compile(std::string name,std::string pattern); + void compile(std::string name,smart_ptr pattern); + std::string default_rule; +}; + +class Seq : public Pattern { + vector > patterns; +public: + Seq(Pattern *p,...); + Seq(vector > patterns,bool ign,bool show); + virtual ~Seq() {} + bool match(Matcher *m); +}; + +class Or : public Pattern { +public: + vector > patterns; + bool ignCase, igcShow; + Or(bool ign,bool show) : ignCase(ign), igcShow(show) {} + Or(Pattern *p,...); + virtual ~Or() {} + bool match(Matcher *m); +}; + +class Literal : public Pattern { +public: + const char c; + Literal(char b) : c(b) {} + bool match(Matcher *m); + std::string fmt() { + std::string s = "literal("; + s += c+")"; + return s; + } +}; + +class ILiteral : public Pattern { +public: + const char lc,uc; + ILiteral(char b); + bool match(Matcher *m); + std::string fmt() { + std::string s = "Iliteral("; + s += lc; + s += ","; + s += uc; + s += ")"; + return s; + } +}; + +class Lookup : public Pattern { + smart_ptr gram; + std::string name; + bool capture; +public: + Lookup(std::string s,smart_ptr g); + virtual ~Lookup() {} + bool match(Matcher *m); + std::string fmt() { + return "Literal:"+name; + } +}; + +class Nothing : public Pattern { +public: + Nothing() {} + bool match(Matcher *m) { return true; } +}; + +class Start : public Pattern { +public: + Start() {} + bool match(Matcher *m); +}; + +class End : public Pattern { +public: + End() {} + bool match(Matcher *m); +}; + +class Dot : public Pattern { +public: + Dot() {} + bool match(Matcher *m); +}; + +class Multi : public Pattern { + const int minv,maxv; +public: + smart_ptr pattern; + Multi(int min_,int max_) : minv(min_), maxv(max_), pattern(NULL) {} + Multi(Pattern *p,int min_,int max_) : minv(min_), maxv(max_), pattern(p) {} + virtual ~Multi() {} + bool match(Matcher *m); +}; + +class Range : public Pattern { +public: + char lo,hi; + bool match(Matcher *m); + Range(char lo_,char hi_) : lo(lo_), hi(hi_) {} +}; + +class Bracket : public Pattern { +public: + bool neg; + vector > ranges; + Bracket() : neg(false) {} + virtual ~Bracket() {} + Bracket(bool b); + Bracket *addRange(char lo,char hi); + Bracket *addRange(char lo,char hi,bool ign); + bool match(Matcher *m); +}; +extern std::ostream& operator<<(std::ostream&,Bracket&); + +class NegLookAhead : public Pattern { +public: + smart_ptr pattern; + NegLookAhead(smart_ptr p) : pattern(p) {} + virtual ~NegLookAhead() {} + bool match(Matcher *m) { return true; }//TODO: Fill in +}; + +class LookAhead : public Pattern { +public: + smart_ptr pattern; + LookAhead(smart_ptr p) : pattern(p) {} + virtual ~LookAhead() {} + bool match(Matcher *m) { return true; }//TODO: Fill in +}; + +class Boundary : public Pattern { + bool match(Matcher *m) { return true; }//TODO: Fill in +}; + +class Break : public Pattern { + bool match(Matcher *m) { return true; }//TODO: Fill in +}; + +class BackRef : public Pattern { +public: + int index; + bool ignCase; + BackRef(int in,bool ign) : index(in), ignCase(ign) {} + bool match(Matcher *m) { return true; }//TODO: Fill in +}; + +class AutoGrammar { +public: + static smart_ptr reparserGenerator(); + static smart_ptr fileParserGenerator(); +}; + +class Matcher : public Group { +public: + Matcher(smart_ptr g,const char *pat_,const char *input_,int input_size=-1); + virtual ~Matcher() {} + const char *input; + smart_ptr g; + int input_size; + int pos; + int max_pos; + const char *pat; + bool matches(); + Bracket expected; + void showError(); + std::string inrule; + std::string inrule_max; + int err_pos; + void fail(Bracket *ex); + void fail(char lo,char hi); +}; + +extern smart_ptr pegGrammar; +extern smart_ptr compile(smart_ptr g,bool ignCase,smart_ptr gram); +extern void compileFile(smart_ptr g,const char *buffer,signed long buffersize=-1); + +#endif diff --git a/src/piraha/ReParse.cc b/src/piraha/ReParse.cc new file mode 100644 index 00000000..634e1f10 --- /dev/null +++ b/src/piraha/ReParse.cc @@ -0,0 +1,190 @@ +#include "Piraha.hpp" +#include +#include + +char getChar(smart_ptr gr) { + if(gr->groupCount()==1) { + std::string sub = gr->group(0)->substring(); + int n = 0; + for(unsigned int i=0;i= '0' && c <= '9') + n = n*16+c-'0'; + else if(c >= 'a' && c <= 'f') + n = n*16+c-'a'+10; + else if(c >= 'A' && c <= 'F') + n = n*16+c-'A'+10; + } + } + std::string gs = gr->substring(); + if(gs.size()==2) { + char c = gs[1]; + if(c == 'n') + return '\n'; + else if(c == 'r') + return '\r'; + else if(c == 't') + return '\t'; + else if(c == 'b') + return '\b'; + else + return c; + } else { + return gs[0]; + } +} +smart_ptr mkMulti(smart_ptr g) { + if(g->groupCount()==0) { + std::string s = g->substring(); + if("*" == s) { + return new Multi(0,max_int); + } else if("+" == s) { + return new Multi(1,max_int); + } else if("?" == s) { + return new Multi(0,1); + } + } else if(g->groupCount()==1) { + int mn = atol(g->group(0)->substring().c_str()); + return new Multi(mn,mn); + } else if(g->groupCount()==2) { + int mn = atol(g->group(0)->substring().c_str()); + if(g->group(1)->groupCount()>0) { + int mx = atol(g->group(1)->group(0)->substring().c_str()); + return new Multi(mn,mx); + } else { + return new Multi(mn,max_int); + } + } + g->dump(); + return NULL; +} + + +void compileFile(smart_ptr g,const char *buffer,signed long buffersize) { + if(buffersize < 0) + buffersize = strlen(buffer); + smart_ptr grammar = AutoGrammar::fileParserGenerator(); + smart_ptr m = new Matcher(grammar,"file",buffer,buffersize); + bool b = m->matches(); + if(!b) { + m->showError(); + assert(false); + } + + for(int i=0;igroupCount();i++) { + smart_ptr rule = m->group(i); + smart_ptr ptmp = ::compile(rule->group(1), false, g); + std::string nm = rule->group(0)->substring(); + g->patterns.put(nm,ptmp); + g->default_rule = nm; + } +} + +smart_ptr compile(smart_ptr g,bool ignCase,smart_ptr gram) { + std::string pn = g->getPatternName(); + if("literal" == pn) { + char c = getChar(g); + if(ignCase) + return new ILiteral(c); + else + return new Literal(c); + } else if("pattern" == pn) { + if(g->groupCount()==0) + return new Nothing(); + return compile(g->group(0),ignCase,gram); + } else if("pelem" == pn) { + if(g->groupCount()==2) { + smart_ptr pm = mkMulti(g->group(1)); + Multi *m = (Multi *)pm.ptr(); + m->pattern = compile(g->group(0),ignCase,gram); + return pm; + } + return compile(g->group(0),ignCase,gram); + } else if("pelems" == pn||"pelems_top" == pn||"pelems_next" == pn) { + vector > li; + for(int i=0;igroupCount();i++) { + li.push_back(compile(g->group(i),ignCase,gram)); + } + if(li.size()==1) + return li[0]; + return new Seq(li,false,false); + } else if("group_inside" == pn||"group_top" == pn) { + if(g->groupCount()==1) + return compile(g->group(0),ignCase,gram); + vector > li; + for(int i=0;igroupCount();i++) { + li.push_back(compile(g->group(i),ignCase,gram)); + } + Or *or_ = new Or(false,false); + or_->patterns = li; + smart_ptr orp = or_; + return orp; + } else if("group" == pn) { + Or *or_ = new Or(false,false); + smart_ptr orp_ = or_; + bool ignC = ignCase; + smart_ptr inside = NULL; + if(g->groupCount()==2) { + ignC = or_->igcShow = true; + std::string ps = g->group(0)->getPatternName(); + if(ps == "ign_on") { + ignC = or_->ignCase = true; + } else if(ps == "ign_off") { + ignC = or_->ignCase = false; + } else if(ps == "neglookahead") { + return new NegLookAhead(compile(g->group(1),ignCase,gram)); + } else if(ps == "lookahead") { + return new LookAhead(compile(g->group(1),ignCase,gram)); + } + inside = g->group(1); + } else { + inside = g->group(0); + } + for(int i=0;igroupCount();i++) { + or_->patterns.push_back(compile(inside->group(i),ignC,gram)); + } + if(or_->igcShow == false && or_->patterns.size()==1) + return or_->patterns[0]; + return orp_; + } else if("start" == pn) { + return new Start(); + } else if("end" == pn) { + return new End(); + } else if("boundary" == pn) { + return new Boundary(); + } else if("charclass" == pn) { + Bracket *br = new Bracket(); + smart_ptr brp = br; + int i=0; + if(g->groupCount()>0 && g->group(0)->getPatternName() == "neg") { + i++; + br->neg = true; + } + for(;i < g->groupCount();i++) { + std::string gn = g->group(i)->getPatternName(); + if("range"==gn) { + char c0 = getChar(g->group(i)->group(0)); + char c1 = getChar(g->group(i)->group(1)); + br->addRange(c0, c1, ignCase); + } else { + char c = getChar(g->group(i)); + br->addRange(c,c, ignCase); + } + } + return brp; + } else if("named" == pn) { + std::string lookup = g->group(0)->substring(); + if("brk" == lookup) + return new Break(); + return new Lookup(lookup, gram); + } else if("nothing" == pn) { + return new Nothing(); + } else if("s" == pn||"s0" == pn) { + return new Lookup("-skipper", gram); + } else if("dot" == pn) { + return new Dot(); + } else if("backref" == pn) { + return new BackRef(g->substring()[1]-'0', ignCase); + } + return NULL; +} diff --git a/src/piraha/Seq.cc b/src/piraha/Seq.cc new file mode 100644 index 00000000..971c3e44 --- /dev/null +++ b/src/piraha/Seq.cc @@ -0,0 +1,27 @@ +#include +#include +#include "Piraha.hpp" + +Seq::Seq(Pattern *p,...) { + va_list ap; + va_start(ap,p); + patterns.push_back(p); + while(true) { + Pattern *pat = va_arg(ap,Pattern*); + if(pat == NULL) + break; + assert(patterns.size()<6); + patterns.push_back(pat); + } + va_end(ap); +} +Seq::Seq(vector > p,bool ign,bool show) : patterns(p) {} + +bool Seq::match(Matcher *m) { + typedef vector >::iterator pattern_iter; + for(pattern_iter p = patterns.begin();p != patterns.end();++p) { + if(!(*p)->match(m)) + return false; + } + return true; +} diff --git a/src/piraha/Start.cc b/src/piraha/Start.cc new file mode 100644 index 00000000..527a1b93 --- /dev/null +++ b/src/piraha/Start.cc @@ -0,0 +1,5 @@ +#include "Piraha.hpp" + +bool Start::match(Matcher *m) { + return m->pos == 0; +} diff --git a/src/piraha/make.code.defn b/src/piraha/make.code.defn new file mode 100644 index 00000000..cb30b552 --- /dev/null +++ b/src/piraha/make.code.defn @@ -0,0 +1,6 @@ +SRCS=\ +AutoGrammar.cc Bracket.cc Dot.cc End.cc \ +Grammar.cc Group.cc ILiteral.cc \ +Literal.cc Lookup.cc Matcher.cc Multi.cc \ +Or.cc ReParse.cc Seq.cc Start.cc Call.cc \ +smart_ptr.cc diff --git a/src/piraha/size.py b/src/piraha/size.py new file mode 100644 index 00000000..e81a2214 --- /dev/null +++ b/src/piraha/size.py @@ -0,0 +1,7 @@ +fac = 1+1/4.+1/16. +diff = 1+fac - fac**3 +print diff +init = 16 +nextv = init + (init>>2) + (init>>4) +print nextv +print 1.0*nextv/init diff --git a/src/piraha/smart_ptr.cc b/src/piraha/smart_ptr.cc new file mode 100644 index 00000000..e1d26b71 --- /dev/null +++ b/src/piraha/smart_ptr.cc @@ -0,0 +1,3 @@ +#include "smart_ptr.hpp" + +std::vector ptrs; diff --git a/src/piraha/smart_ptr.hpp b/src/piraha/smart_ptr.hpp new file mode 100644 index 00000000..0994a821 --- /dev/null +++ b/src/piraha/smart_ptr.hpp @@ -0,0 +1,177 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2011 Steve Brandt and Philip LeBlanc +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt) +//////////////////////////////////////////////////////////////////////////////// +#ifndef SMART_PTR_HPP +#define SMART_PTR_HPP +#include +#include +#include + +#ifndef NULL +#define NULL ((void*)0) +#endif + +extern std::vector ptrs; + +#ifndef NDEBUG +inline void add(std::vector& v,void *t) { + if(t == NULL) + return; + typedef typename std::vector::iterator iter; + for(iter i=v.begin();i != v.end();++i) { + assert(*i != t); + } + v.push_back(t); +} + +inline void remove(std::vector& v,void* t) { + if(t == NULL) + return; + typedef typename std::vector::iterator iter; + for(iter i=v.begin();i != v.end();++i) { + if(*i == t) { + v.erase(i); + return; + } + } + assert(false); +} +#else +inline void add(std::vector& v,void* t) { +} +inline void remove(std::vector& v,void* t) { +} +#endif + +template +class smart_ptr; + +template +class smart_ptr_guts { + int ref_count; + public: + T * const ptr; + 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); + } + } + ~smart_ptr_guts() { + if(ptr != NULL) { + remove(ptrs,(void*)ptr); + if(array) + delete[] ptr; + else + delete ptr; + } + } + void inc() { + ref_count++; + } + bool dec() { + int r = ref_count; + if(ref_count>0) + ref_count--; + return r==1; + } + int ref_count_() { + return ref_count; + } +}; + +// Count references to an object in a thread-safe +// way using pthreads and do automatic clean up. +template +class smart_ptr { + smart_ptr_guts *guts; + void clean() { + assert(this != NULL); + if(guts != NULL && guts->dec()) { + delete guts; + guts = NULL; + } + } + public: + void inc() { + if(valid()) + guts->inc(); + } + smart_ptr(T *ptr,bool array_=false) { + if(ptr == NULL) { + guts = NULL; + } else { + guts = new smart_ptr_guts(1,ptr,array_); + } + } + smart_ptr(const smart_ptr &sm) : guts(sm.guts) { + if(sm.guts != NULL) + guts->inc(); + } + smart_ptr() : guts(NULL) {} + ~smart_ptr() { + clean(); + } + void operator=(T *t) { + clean(); + if(t == NULL) { + guts = NULL; + } else { + guts = new smart_ptr_guts(1,t,false); + } + } + void set(T *t,bool array_) { + clean(); + if(t == NULL) { + guts = NULL; + } else { + guts = new smart_ptr_guts(1,t,array_); + } + } + void operator=(const smart_ptr& s) { + assert(this != NULL); + clean(); + guts = s.guts; + if(guts != NULL) + guts->inc(); + } + T& operator*() { + assert(guts != NULL); + return *guts->ptr; + } + T& operator[](unsigned int n) { + assert(guts != NULL); + assert(guts->array); + return guts->ptr[n]; + } + T *operator->() const { + if(guts == NULL) + return NULL; + else + return guts->ptr; + } + T *ptr() { + assert(guts != NULL); + return guts->ptr; + } + bool valid() { + return guts != NULL && guts->ptr != NULL; + } + int ref_count() { + assert(guts != NULL); + return guts->ref_count_(); + } + template + smart_ptr dup() { + smart_ptr c; + c.guts = (smart_ptr_guts *)guts; + guts->inc(); + return c; + } + template + friend class smart_ptr; +}; +#endif diff --git a/src/util/ParseFile.c b/src/util/ParseFile.c index 17a5253e..3d17e787 100644 --- a/src/util/ParseFile.c +++ b/src/util/ParseFile.c @@ -119,30 +119,42 @@ static int lineno = 1; @endreturndesc @@*/ +int PirahaParser(const char *buffer,unsigned long buffersize,int (*set_function)(const char *, const char *, int)); + int ParseFile(FILE *ifp, int (*set_function)(const char *, const char *, int), tFleshConfig *ConfigData) { - int retval; + int retval=1; unsigned long buffersize; char *buffer = ReadFile(ifp, &buffersize); if (!buffer) return 1; - /* Ensure Unix line endings */ - convert_crlf_to_lf(buffer); - buffersize = strlen(buffer); - - buffer = ParseDefines(buffer, &buffersize); - /* ParseBuffer can get confused with detecting the end of the buffer - (when in a comment or in a string), and may overrun. Therefore - we allocate a buffer that is a bit longer. */ - { - buffer = realloc (buffer, strlen(buffer) + 10); - memset (buffer+strlen(buffer), '\0', 10); + int piraha_active = 1; + + if(piraha_active) { + // the new way + buffersize = strlen(buffer); + + retval = PirahaParser(buffer,buffersize,set_function); + } else { + // The old way + /* Ensure Unix line endings */ + convert_crlf_to_lf(buffer); + buffersize = strlen(buffer); + + buffer = ParseDefines(buffer, &buffersize); + /* ParseBuffer can get confused with detecting the end of the buffer + (when in a comment or in a string), and may overrun. Therefore + we allocate a buffer that is a bit longer. */ + { + buffer = realloc (buffer, strlen(buffer) + 10); + memset (buffer+strlen(buffer), '\0', 10); + } + retval = ParseBuffer(buffer, set_function, ConfigData); + free(buffer); } - retval = ParseBuffer(buffer, set_function, ConfigData); - free(buffer); return retval; } @@ -316,7 +328,6 @@ int main(int argc, char *argv[]) static char *ReadFile(FILE *file, unsigned long *filesize) { char *buffer; - size_t bytes_read; if (!file) { @@ -335,13 +346,7 @@ static char *ReadFile(FILE *file, unsigned long *filesize) return NULL; } /* Read file into buffer and return */ - bytes_read = fread(buffer, 1, *filesize, file); - if (bytes_read != *filesize) - { - fprintf(stderr, "File size changed while reading.\n"); - free(buffer); - return NULL; - } + fread(buffer, *filesize, 1, file); /* Protect buffer for string operations */ buffer[*filesize] = '\0'; return buffer; -- cgit v1.2.3