summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsbrandt <sbrandt@17b73243-c579-4c4c-a9d2-2d5706c11dac>2013-02-25 16:54:00 +0000
committersbrandt <sbrandt@17b73243-c579-4c4c-a9d2-2d5706c11dac>2013-02-25 16:54:00 +0000
commit4730bc03f50318da9432bbd17f7c9cc91de1eb21 (patch)
tree740a46e73a289157f7cc45e281ecfdfb686977e5 /src
parentf9f8fb05dc03fa339e37a04608009f62e4fcc3b0 (diff)
Change the parameter parser to Piraha
git-svn-id: http://svn.cactuscode.org/flesh/trunk@4960 17b73243-c579-4c4c-a9d2-2d5706c11dac
Diffstat (limited to 'src')
-rw-r--r--src/make.code.defn2
-rw-r--r--src/piraha/AutoGrammar.cc388
-rw-r--r--src/piraha/Bracket.cc114
-rw-r--r--src/piraha/Call.cc280
-rw-r--r--src/piraha/Dot.cc13
-rw-r--r--src/piraha/End.cc5
-rw-r--r--src/piraha/Generic.cc35
-rw-r--r--src/piraha/Grammar.cc24
-rw-r--r--src/piraha/Group.cc39
-rw-r--r--src/piraha/ILiteral.cc22
-rw-r--r--src/piraha/Literal.cc18
-rw-r--r--src/piraha/Lookup.cc30
-rw-r--r--src/piraha/Makefile12
-rw-r--r--src/piraha/Matcher.cc85
-rw-r--r--src/piraha/Multi.cc17
-rw-r--r--src/piraha/Or.cc32
-rw-r--r--src/piraha/Piraha.hpp294
-rw-r--r--src/piraha/ReParse.cc190
-rw-r--r--src/piraha/Seq.cc27
-rw-r--r--src/piraha/Start.cc5
-rw-r--r--src/piraha/make.code.defn6
-rw-r--r--src/piraha/size.py7
-rw-r--r--src/piraha/smart_ptr.cc3
-rw-r--r--src/piraha/smart_ptr.hpp177
-rw-r--r--src/util/ParseFile.c49
25 files changed, 1851 insertions, 23 deletions
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<Grammar> AutoGrammar::reparserGenerator() {
+ smart_ptr<Grammar> 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<Grammar> AutoGrammar::fileParserGenerator() {
+ smart_ptr<Grammar> 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<smart_ptr<Range> >::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<Range> 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<smart_ptr<Range> >::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 <iostream>
+#include <string.h>
+#include "Piraha.hpp"
+#include <stdlib.h>
+#include <sstream>
+#include "cctk_Parameter.h"
+#include <map>
+#include <math.h>
+
+#define VAR(X) " " #X "=" << X
+
+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;
+
+// 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<Group> 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<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();
+ }
+ }
+ 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<Grammar> g = new Grammar();
+ compileFile(g,par_file_src,strlen(par_file_src));
+
+ std::string active;
+ smart_ptr<Matcher> m2 = new Matcher(g,"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);
+ active += val;
+ active += ' ';
+ line = gr->line();
+ }
+ }
+ set_function("ActiveThorns",active.c_str(),line);
+ for(int i=0;i<m2->groupCount();i++) {
+ smart_ptr<Group> gr = m2->group(i);
+ if(gr->getPatternName() != "set")
+ continue;
+ smart_ptr<Group> 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<Group> index = gr->group("index");
+ if(index.valid()) {
+ key += '[';
+ key += index->group(0)->substring();
+ key += ']';
+ }
+
+ std::string val;
+ smart_ptr<Group> 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<Group> arr = gr->group("array");
+ 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;
+ 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 <fstream>
+
+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<Grammar> g = new Grammar();
+ compileFile(g,grammar_file.c_str());
+ smart_ptr<Matcher> 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<Pattern> compile(smart_ptr<Group> g,bool ignCase,smart_ptr<Grammar> gram);
+
+smart_ptr<Grammar> pegGrammar = AutoGrammar::reparserGenerator();
+
+void Grammar::compile(std::string name,smart_ptr<Group> g) {
+ default_rule = name;
+ smart_ptr<Pattern> p = ::compile(g,false,this);
+ patterns.put(name,p);
+}
+void Grammar::compile(std::string name,std::string pattern) {
+ default_rule = name;
+ smart_ptr<Matcher> m = new Matcher(pegGrammar,"pattern",pattern.c_str());
+ smart_ptr<Group> g = m.dup<Group>();
+ if(m->matches()) {
+ smart_ptr<Pattern> 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<indent;i++)
+ std::cout << ' ';
+ std::cout << pattern << ": ";
+ if(children.size()==0) {
+ for(int i=start_;i<end_;i++)
+ std::cout << input[i];
+ }
+ std::cout << std::endl;
+ typedef vector<smart_ptr<Group> >::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_;i<end_;i++) {
+ sub += input[i];
+ }
+ return sub;
+}
+
+std::string Group::getPatternName() {
+ return pattern;
+}
+
+int Group::line() {
+ int line = 1;
+ for(int i=0;i<start_;i++) {
+ if(input[i] == '\n')
+ line++;
+ }
+ return line;
+}
diff --git a/src/piraha/ILiteral.cc b/src/piraha/ILiteral.cc
new file mode 100644
index 00000000..f56d4414
--- /dev/null
+++ b/src/piraha/ILiteral.cc
@@ -0,0 +1,22 @@
+#include "Piraha.hpp"
+
+ILiteral::ILiteral(char b) : lc(lc_(b)), uc(uc_(b)) {}
+
+bool ILiteral::match(Matcher *m) {
+ if(m->pos >= (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<Grammar> g) : gram(g), name(name_), capture(true) {
+ if(name[0] == '-') {
+ capture = false;
+ name = name.substr(1);
+ }
+}
+
+bool Lookup::match(Matcher *m) {
+ smart_ptr<Pattern> p = gram->patterns.get(name);
+ if(!p.valid()) std::cout << "Lookup of pattern [" << name << "] failed. Jmap = " << gram->patterns << std::endl;
+ assert(p.valid());
+ vector<smart_ptr<Group> > 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<Group> 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 <string.h>
+#include "Piraha.hpp"
+
+Matcher::Matcher(smart_ptr<Grammar> 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<Pattern> 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;i<br->ranges.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<num_previous_lines;i++)
+ 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;
+ while(input[i] == '\n'||input[i] == '\r') {
+ line++;
+ for(int j=1;j<num_previous_lines;j++) {
+ start_of_previous_line[j-1] = start_of_previous_line[j];
+ }
+ start_of_previous_line[num_previous_lines-1] = start_of_line;
+ start_of_line = ++i;
+ }
+ break;
+ }
+ if(input[i] == '\n') {
+ line++;
+ for(int j=1;j<num_previous_lines;j++) {
+ start_of_previous_line[j-1] = start_of_previous_line[j];
+ }
+ start_of_previous_line[num_previous_lines-1] = start_of_line;
+ start_of_line = i+1;
+ }
+ }
+ for(int i=start_of_previous_line[0];i<input_size;i++) {
+ std::cout << input[i];
+ if(i > error_pos && input[i] == '\n')
+ break;
+ }
+ 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;
+}
diff --git a/src/piraha/Multi.cc b/src/piraha/Multi.cc
new file mode 100644
index 00000000..c7cfa447
--- /dev/null
+++ b/src/piraha/Multi.cc
@@ -0,0 +1,17 @@
+#include <iostream>
+#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 <iostream>
+#include <stdarg.h>
+#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<smart_ptr<Pattern> >::iterator pattern_iter;
+ int save = m->pos;
+ vector<smart_ptr<Group> > 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 <assert.h>
+#include <map>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <smart_ptr.hpp>
+
+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<smart_ptr<Group> > 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<smart_ptr<Group> > 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<Group> child(int i);
+ void dump(int indent=0);
+ int groupCount() { return children.size(); }
+ smart_ptr<Group> group(int i) { return children[i]; }
+ 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)
+ return children[i];
+ }
+ }
+ smart_ptr<Group> 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<std::string,smart_ptr<Pattern> > m;
+public:
+ JMap() : m() {}
+ smart_ptr<Pattern> get(std::string key) {
+ typedef map<std::string,smart_ptr<Pattern> >::iterator mit;
+ mit it = m.find(key);
+ mit me = m.end();
+ if(it == me) {
+ return NULL;
+ }
+ smart_ptr<Pattern> res = m[key];
+ assert(res.valid());
+ return res;
+ }
+ void put(std::string key,smart_ptr<Pattern> 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<std::string,smart_ptr<Pattern> >::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<Group> pattern);
+ std::string default_rule;
+};
+
+class Seq : public Pattern {
+ vector<smart_ptr<Pattern> > patterns;
+public:
+ Seq(Pattern *p,...);
+ Seq(vector<smart_ptr<Pattern> > patterns,bool ign,bool show);
+ virtual ~Seq() {}
+ bool match(Matcher *m);
+};
+
+class Or : public Pattern {
+public:
+ vector<smart_ptr<Pattern> > 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<Grammar> gram;
+ std::string name;
+ bool capture;
+public:
+ Lookup(std::string s,smart_ptr<Grammar> 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> 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<smart_ptr<Range> > 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> pattern;
+ NegLookAhead(smart_ptr<Pattern> p) : pattern(p) {}
+ virtual ~NegLookAhead() {}
+ bool match(Matcher *m) { return true; }//TODO: Fill in
+};
+
+class LookAhead : public Pattern {
+public:
+ smart_ptr<Pattern> pattern;
+ LookAhead(smart_ptr<Pattern> 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<Grammar> reparserGenerator();
+ static smart_ptr<Grammar> fileParserGenerator();
+};
+
+class Matcher : public Group {
+public:
+ Matcher(smart_ptr<Grammar> g,const char *pat_,const char *input_,int input_size=-1);
+ virtual ~Matcher() {}
+ const char *input;
+ smart_ptr<Grammar> 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<Grammar> pegGrammar;
+extern smart_ptr<Pattern> compile(smart_ptr<Group> g,bool ignCase,smart_ptr<Grammar> gram);
+extern void compileFile(smart_ptr<Grammar> 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 <stdlib.h>
+#include <string.h>
+
+char getChar(smart_ptr<Group> gr) {
+ if(gr->groupCount()==1) {
+ std::string sub = gr->group(0)->substring();
+ int n = 0;
+ for(unsigned int i=0;i<sub.size();i++) {
+ char c = sub[i];
+ if(c >= '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<Pattern> mkMulti(smart_ptr<Group> 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<Grammar> g,const char *buffer,signed long buffersize) {
+ if(buffersize < 0)
+ buffersize = strlen(buffer);
+ smart_ptr<Grammar> grammar = AutoGrammar::fileParserGenerator();
+ smart_ptr<Matcher> m = new Matcher(grammar,"file",buffer,buffersize);
+ bool b = m->matches();
+ if(!b) {
+ m->showError();
+ assert(false);
+ }
+
+ for(int i=0;i<m->groupCount();i++) {
+ smart_ptr<Group> rule = m->group(i);
+ smart_ptr<Pattern> 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<Pattern> compile(smart_ptr<Group> g,bool ignCase,smart_ptr<Grammar> 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<Pattern> 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<smart_ptr<Pattern> > li;
+ for(int i=0;i<g->groupCount();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<smart_ptr<Pattern> > li;
+ for(int i=0;i<g->groupCount();i++) {
+ li.push_back(compile(g->group(i),ignCase,gram));
+ }
+ Or *or_ = new Or(false,false);
+ or_->patterns = li;
+ smart_ptr<Pattern> orp = or_;
+ return orp;
+ } else if("group" == pn) {
+ Or *or_ = new Or(false,false);
+ smart_ptr<Pattern> orp_ = or_;
+ bool ignC = ignCase;
+ smart_ptr<Group> 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;i<inside->groupCount();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<Pattern> 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 <iostream>
+#include <stdarg.h>
+#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<smart_ptr<Pattern> > p,bool ign,bool show) : patterns(p) {}
+
+bool Seq::match(Matcher *m) {
+ typedef vector<smart_ptr<Pattern> >::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<void*> 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 <assert.h>
+#include <vector>
+#include <iostream>
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+extern std::vector<void*> ptrs;
+
+#ifndef NDEBUG
+inline void add(std::vector<void*>& v,void *t) {
+ if(t == NULL)
+ return;
+ typedef typename std::vector<void*>::iterator iter;
+ for(iter i=v.begin();i != v.end();++i) {
+ assert(*i != t);
+ }
+ v.push_back(t);
+}
+
+inline void remove(std::vector<void*>& v,void* t) {
+ if(t == NULL)
+ return;
+ typedef typename std::vector<void*>::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<void*>& v,void* t) {
+}
+inline void remove(std::vector<void*>& v,void* t) {
+}
+#endif
+
+template<typename T>
+class smart_ptr;
+
+template<typename T>
+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<typename T>
+class smart_ptr {
+ smart_ptr_guts<T> *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<T>(1,ptr,array_);
+ }
+ }
+ smart_ptr(const smart_ptr<T> &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<T>(1,t,false);
+ }
+ }
+ void set(T *t,bool array_) {
+ clean();
+ if(t == NULL) {
+ guts = NULL;
+ } else {
+ guts = new smart_ptr_guts<T>(1,t,array_);
+ }
+ }
+ void operator=(const smart_ptr<T>& 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<typename C>
+ smart_ptr<C> dup() {
+ smart_ptr<C> c;
+ c.guts = (smart_ptr_guts<C> *)guts;
+ guts->inc();
+ return c;
+ }
+ template<typename C>
+ 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;