summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsbrandt <sbrandt@17b73243-c579-4c4c-a9d2-2d5706c11dac>2013-04-03 19:12:46 +0000
committersbrandt <sbrandt@17b73243-c579-4c4c-a9d2-2d5706c11dac>2013-04-03 19:12:46 +0000
commita3cb4c5d02f0ee75094fc27814c71f8a025d034b (patch)
tree1dd1af38bf8ad0318f07dd2c8ae00216e942efb0
parent069e8f1d570cc373c843673be0acf7bc4dd10b6e (diff)
Add the basic grammar files, and the changes
to the piraha code necessary to parse all of Cactus. git-svn-id: http://svn.cactuscode.org/flesh/trunk@4990 17b73243-c579-4c4c-a9d2-2d5706c11dac
-rw-r--r--src/piraha/Boundary.cc20
-rw-r--r--src/piraha/Bracket.cc6
-rw-r--r--src/piraha/Generic.cc90
-rw-r--r--src/piraha/Group.cc73
-rw-r--r--src/piraha/Lookup.cc8
-rw-r--r--src/piraha/Makefile15
-rw-r--r--src/piraha/Multi.cc21
-rw-r--r--src/piraha/NegLookAhead.cc10
-rw-r--r--src/piraha/Piraha.hpp24
-rw-r--r--src/piraha/make.code.defn2
-rw-r--r--src/piraha/pegs/configuration.peg32
-rw-r--r--src/piraha/pegs/interface.peg73
-rw-r--r--src/piraha/pegs/param.peg141
-rw-r--r--src/piraha/pegs/schedule.peg70
14 files changed, 540 insertions, 45 deletions
diff --git a/src/piraha/Boundary.cc b/src/piraha/Boundary.cc
new file mode 100644
index 00000000..6c34335b
--- /dev/null
+++ b/src/piraha/Boundary.cc
@@ -0,0 +1,20 @@
+#include "Piraha.hpp"
+
+using namespace piraha;
+
+bool is_c_ident(char c) {
+ return ('a' <= c && c <= 'z')
+ || ('A' <= c && c <= 'Z')
+ || ('0' <= c && c <= '9')
+ || c == '_';
+}
+
+bool Boundary::match(Matcher *m) {
+ if(m->pos == 0 || m->pos == (int)m->input_size)
+ return true;
+ char c2 = m->input[m->pos];
+ char c1 = m->input[m->pos-1];
+ bool b1 = is_c_ident(c1);
+ bool b2 = is_c_ident(c2);
+ return !b1 || !b2;
+}
diff --git a/src/piraha/Bracket.cc b/src/piraha/Bracket.cc
index 47f5c443..d16d75da 100644
--- a/src/piraha/Bracket.cc
+++ b/src/piraha/Bracket.cc
@@ -95,7 +95,7 @@ bool Bracket::match(Matcher *m) {
}
}
-void insertc(std::ostream& o,char c) {
+void piraha::insertc(std::ostream& o,char c) {
if(c == '-') {
o << "\\-";
} else if(c == '\n') {
@@ -104,7 +104,9 @@ void insertc(std::ostream& o,char c) {
o << "\\r";
} else if(c == '\t') {
o << "\\t";
- } else if(strchr("[]-",c)>=0) {
+ } else if(c == '\b') {
+ o << "\\b";
+ } else if(strchr("\\\"[]-",c) != 0) {
o << "\\" << c;
} else {
o << c;
diff --git a/src/piraha/Generic.cc b/src/piraha/Generic.cc
index 1695b873..f60696ee 100644
--- a/src/piraha/Generic.cc
+++ b/src/piraha/Generic.cc
@@ -1,5 +1,6 @@
#include "Piraha.hpp"
#include <fstream>
+#include <stdlib.h>
using namespace piraha;
@@ -15,23 +16,98 @@ void read_file(const char *file,std::string& buf) {
in.close();
}
+void usage() {
+ std::cerr << "usage: generic [--perl] grammar input" << std::endl;
+ exit(2);
+}
+
+#define VAR(X) " " << #X << "=" << X
+
+bool newEnd(std::string& in,const char *new_end,std::string& out) {
+ out = "/dev/null";
+ int n = in.size();
+ int i;
+ for(i=n-1;i>0;i--) {
+ if(in[i] == '.') {
+ break;
+ }
+ if(in[i] == '/') {
+ std::cout << VAR(in) << VAR(i) << std::endl;
+ break;
+ }
+ }
+ if(in[i] != '.') {
+ std::cout << VAR(in) << VAR(i) << std::endl;
+ return false;
+ }
+ out.clear();
+ for(int j=0;j<i;j++)
+ out += in[j];
+ out += new_end;
+ return true;
+}
+
int main(int argc,char **argv) {
- if(argc != 3) {
- std::cerr << "usage: generic grammar input" << std::endl;
- return 2;
+ std::string grammarArg, inputArg;
+ bool perlFlag = false;
+ bool oFlag = false;
+ std::string outFile;
+ int narg = 0;
+ for(int n=1;n<argc;n++) {
+ std::string arg = argv[n];
+ if(arg == "--perl") {
+ perlFlag = true;
+ } else if(arg == "-o") {
+ outFile = argv[++n];
+ oFlag = true;
+ } else if(arg.size()>2 && arg[0]=='-' && arg[1]=='o') {
+ outFile = arg.substr(2,arg.size());
+ oFlag = true;
+ } else if(narg == 0) {
+ grammarArg = argv[n];
+ narg++;
+ } else if(narg == 1) {
+ inputArg = argv[n];
+ narg++;
+ } else {
+ usage();
+ }
+ }
+ if(!oFlag) {
+ if(perlFlag) {
+ newEnd(inputArg,".pm",outFile);
+ } else {
+ newEnd(inputArg,".pegout",outFile);
+ }
}
+ std::cout << "reading file: " << inputArg << std::endl;
std::string grammar_file, input_file;
- read_file(argv[1],grammar_file);
- read_file(argv[2],input_file);
+ read_file(grammarArg.c_str(),grammar_file);
+ read_file(inputArg.c_str(),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());
+ smart_ptr<Matcher> mg =
+ new Matcher (g,g->default_rule.c_str(),input_file.c_str());
if(mg->matches()) {
- mg->dump();
+ //std::vector<char> vec(4096);
+ std::ofstream o;
+ //o.rdbuf()->pubsetbuf(&vec.front(),vec.size());
+ o.open(outFile.c_str());
+ std::cout << "writing file: " << outFile << std::endl;
+ smart_ptr<Group> src_file =
+ new Group("annot:src_file",inputArg.c_str());
+ mg->children.push_back(src_file);
+ if(perlFlag) {
+ mg->dumpPerl(o);
+ } else {
+ mg->dump(o);
+ }
+ o.close();
} else {
mg->showError();
+ return 1;
}
return 0;
}
diff --git a/src/piraha/Group.cc b/src/piraha/Group.cc
index 544e12be..95079800 100644
--- a/src/piraha/Group.cc
+++ b/src/piraha/Group.cc
@@ -2,22 +2,83 @@
using namespace piraha;
-void Group::dump(int indent) {
+void Group::dump(std::ostream& o) {
+ dump(-1,o,0);
+}
+void Group::dump(int n,std::ostream& o,int indent) {
for(int i=0;i<indent;i++)
- std::cout << ' ';
- std::cout << pattern << ": ";
+ o << ' ';
+ if(n >= 0) {
+ o << "[" << n << "] ";
+ }
+ o << pattern << ": ";
if(children.size()==0) {
for(int i=start_;i<end_;i++)
- std::cout << input[i];
+ o << input[i];
}
- std::cout << std::endl;
+ o << std::endl;
typedef vector<smart_ptr<Group> >::iterator group_iter;
+ int nn = 0;
for(group_iter gi = children.begin();
gi != children.end();
++gi) {
- (*gi)->dump(indent+2);
+ (*gi)->dump(nn++,o,indent+2);
}
}
+void Group::dumpPerl(std::ostream& o) {
+ o << "$VAR = ";
+ dumpPerl(o,0);
+ o << ";" << std::endl;
+}
+void Group::dumpPerl(std::ostream &o,int indent) {
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "{" << std::endl;
+ indent += 2;
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "name=> \"" << getPatternName() << "\"," << std::endl;
+ if(children.size()==0) {
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "children=>[]," << std::endl;
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "text=>\"";
+ for(int i=start_;i<end_;i++)
+ insertc(o,input[i]);
+ o << "\"," << std::endl;
+ } else {
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "children=>[" << std::endl;
+ typedef vector<smart_ptr<Group> >::iterator group_iter;
+ for(group_iter gi = children.begin();
+ gi != children.end();
+ ++gi) {
+ (*gi)->dumpPerl(o,indent+2);
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "," << std::endl;
+ }
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "]," << std::endl;
+ }
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "start=>" << start() << "," << std::endl;
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "end=>" << end() << "," << std::endl;
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "line=>" << line() << "," << std::endl;
+ indent -= 2;
+ for(int i=0;i<indent;i++)
+ o << ' ';
+ o << "}" << std::endl;
+}
std::string Group::substring() {
std::string sub;
diff --git a/src/piraha/Lookup.cc b/src/piraha/Lookup.cc
index d2394c2a..3b442864 100644
--- a/src/piraha/Lookup.cc
+++ b/src/piraha/Lookup.cc
@@ -23,6 +23,14 @@ bool Lookup::match(Matcher *m) {
m->inrule = save_name;
int e = m->pos;
if(b) {
+ /*
+ if(capture) {
+ std::cout << "Matched: {" << name << "}={";
+ for(int i=s;i<e;i++)
+ insertc(std::cout,m->input[i]);
+ std::cout << "}" << std::endl;
+ }
+ */
smart_ptr<Group> g = new Group(name,m->input,s,e,m->children);
if(capture)
chSave.push_back(g);
diff --git a/src/piraha/Makefile b/src/piraha/Makefile
index 45e4f4dc..4657948e 100644
--- a/src/piraha/Makefile
+++ b/src/piraha/Makefile
@@ -1,14 +1,17 @@
# Build the standalone tool
#
-CXX = g++
-CXXFLAGS = -Wall -Wreturn-type
+BIN ?= .
+CXX ?= c++
+CXXFLAGS ?= -g -O2
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
+ Or.cc ReParse.cc Seq.cc smart_ptr.cc Start.cc \
+ Boundary.cc NegLookAhead.cc
-generic : $(SRCS) Piraha.hpp smart_ptr.hpp
- $(CXX) -I . -g -o generic $(SRCS)
+$(BIN)/generic : $(SRCS) Piraha.hpp smart_ptr.hpp
+ mkdir -p $(BIN)
+ $(CXX) $(CXXFLAGS) -I . -o $(BIN)/generic $(SRCS)
clean :
- rm -f generic
+ rm -f $(BIN)/generic
diff --git a/src/piraha/Multi.cc b/src/piraha/Multi.cc
index d0733618..ff03f7d9 100644
--- a/src/piraha/Multi.cc
+++ b/src/piraha/Multi.cc
@@ -4,24 +4,15 @@
using namespace piraha;
bool Multi::match(Matcher *m) {
- unsigned int save;
- int iter = 0;
vector<smart_ptr<Group> > chSave;
- while(true) {
- save = m->pos;
+ for(int i=0;i<maxv;i++) {
+ int save = m->pos;
chSave = m->children;
- if(!pattern->match(m)) {
- m->children = chSave;
+ if(!pattern->match(m) || m->pos == save) {
m->pos = save;
- break;
- }
- if(save - m->pos == 0) {
- std::cout << "ZERO ADVANCE IN MULTI!" << std::endl;
- return minv <= iter && iter <= maxv;
+ m->children = chSave;
+ return i >= minv;
}
- iter++;
- if(iter == maxv)
- break;
}
- return minv <= iter && iter <= maxv;
+ return true;
}
diff --git a/src/piraha/NegLookAhead.cc b/src/piraha/NegLookAhead.cc
new file mode 100644
index 00000000..a70e5539
--- /dev/null
+++ b/src/piraha/NegLookAhead.cc
@@ -0,0 +1,10 @@
+#include "Piraha.hpp"
+
+using namespace piraha;
+
+bool NegLookAhead::match(Matcher *m) {
+ int pos = m->pos;
+ bool b = pattern->match(m);
+ m->pos = pos;
+ return !b;
+}
diff --git a/src/piraha/Piraha.hpp b/src/piraha/Piraha.hpp
index 4308b1fc..b8af3b7a 100644
--- a/src/piraha/Piraha.hpp
+++ b/src/piraha/Piraha.hpp
@@ -35,6 +35,10 @@ public:
int start_,end_;
vector<smart_ptr<Group> > children;
+ Group(const char *p,const char *value)
+ : pattern(p), input(value), start_(0) {
+ for(end_=0;value[end_] != '\0';end_++);
+ }
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,
@@ -49,7 +53,10 @@ public:
std::string getPatternName();
std::string substring();
smart_ptr<Group> child(int i);
- void dump(int indent=0);
+ void dump(std::ostream& o=std::cout);
+ void dump(int n,std::ostream& o,int indent=0);
+ void dumpPerl(std::ostream&o=std::cout);
+ void dumpPerl(std::ostream&o,int indent);
int groupCount() { return children.size(); }
smart_ptr<Group> group(int i) { return children[i]; }
smart_ptr<Group> group(const char *nm,int ix=0) {
@@ -134,7 +141,7 @@ public:
virtual ~Seq() {}
bool match(Matcher *m);
virtual void insert(std::ostream& o) {
- for(int i=0;i<patterns.size();i++)
+ for(unsigned int i=0;i<patterns.size();i++)
o << *patterns[i];
}
};
@@ -149,7 +156,7 @@ public:
bool match(Matcher *m);
virtual void insert(std::ostream& o) {
o << "(";
- for(int i=0;i<patterns.size();i++) {
+ for(unsigned int i=0;i<patterns.size();i++) {
if(i > 0) o << "|";
o << *patterns[i];
}
@@ -304,7 +311,7 @@ public:
smart_ptr<Pattern> pattern;
NegLookAhead(smart_ptr<Pattern> p) : pattern(p) {}
virtual ~NegLookAhead() {}
- bool match(Matcher *m) { return true; }//TODO: Fill in
+ bool match(Matcher *m);
};
class LookAhead : public Pattern {
@@ -312,15 +319,15 @@ public:
smart_ptr<Pattern> pattern;
LookAhead(smart_ptr<Pattern> p) : pattern(p) {}
virtual ~LookAhead() {}
- bool match(Matcher *m) { return true; }//TODO: Fill in
+ bool match(Matcher *m) { assert(false); }//TODO: Fill in
};
class Boundary : public Pattern {
- bool match(Matcher *m) { return true; }//TODO: Fill in
+ virtual bool match(Matcher *m);
};
class Break : public Pattern {
- bool match(Matcher *m) { return true; }//TODO: Fill in
+ virtual bool match(Matcher *m) { assert(false); }//TODO: Fill in
};
class BackRef : public Pattern {
@@ -328,7 +335,7 @@ public:
int index;
bool ignCase;
BackRef(int in,bool ign) : index(in), ignCase(ign) {}
- bool match(Matcher *m) { return true; }//TODO: Fill in
+ virtual bool match(Matcher *m) { assert(false); }//TODO: Fill in
};
class AutoGrammar {
@@ -362,6 +369,7 @@ extern smart_ptr<Pattern> compile(smart_ptr<Group> g,bool ignCase,smart_ptr<Gram
extern void compileFile(smart_ptr<Grammar> g,const char *buffer,signed long buffersize=-1);
void compile(smart_ptr<Grammar> thisg,std::string name,std::string pattern);
void compile(smart_ptr<Grammar> thisg,std::string name,smart_ptr<Group> pattern);
+void insertc(std::ostream& o,char c);
}
diff --git a/src/piraha/make.code.defn b/src/piraha/make.code.defn
index cb30b552..f229672c 100644
--- a/src/piraha/make.code.defn
+++ b/src/piraha/make.code.defn
@@ -3,4 +3,4 @@ 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
+smart_ptr.cc Boundary.cc NegLookAhead.cc
diff --git a/src/piraha/pegs/configuration.peg b/src/piraha/pegs/configuration.peg
new file mode 100644
index 00000000..ade602bc
--- /dev/null
+++ b/src/piraha/pegs/configuration.peg
@@ -0,0 +1,32 @@
+# The skipper is a crucial sub-pattern
+# that is activated by any whitespace in the
+# grammar file
+skipper = \b([\ \t\n\r\b]|\#[^\n]*|\\[\r\n])*
+
+any = [^]
+keywords = \b(?i:script|lang|provides|requires|optional)\b
+name = (?!{-keywords})(?i:[a-z_][a-z0-9_\.]*\b)
+num = [+\-]?[0-9]+
+script = (?i: script( {name}|))
+lang = (?i: lang( {name}|))
+
+option = {name}
+
+provides = (?i:
+ provides {name} \{
+ ({script}?
+ {lang}
+ ( options {option}( {option})* |)|)
+ \}
+ )
+
+requires = (?i:
+ requires (thorns:|) {name}([ \t]*{name})*
+ )
+
+ifactive = (?i:_ifactive)
+optional = (?i:
+ optional{ifactive}? {name}([ \t]+{name})* \{ ( {name} )* \}
+ )
+
+config = ({provides} |{requires} |{optional} )* $
diff --git a/src/piraha/pegs/interface.peg b/src/piraha/pegs/interface.peg
new file mode 100644
index 00000000..99ba1508
--- /dev/null
+++ b/src/piraha/pegs/interface.peg
@@ -0,0 +1,73 @@
+skipper = (([ \t\n\r\b]|\#[^\n\r]*|\\[\r\n])+|\b)
+
+any = [^]
+name = (?i:[a-z_][a-z0-9_]*)
+filename = (?i:([.a-z0-9_]|\\[^])*)
+accname = {-name}(::{-name})*
+inum = [1248]
+rnum = [48]
+cnum = 8|16
+type = (void|CCTK_INT{inum}?|CCTK_REAL{rnum}?|CCTK_COMPLEX{cnum}?|CCTK|CCTK_POINTER|CCTK_TO_CONST)
+
+num = [0-9]+
+boolraw = (?i:true|t|yes|y|false|f|no|n|1|0)
+bool = {-boolraw}|"{-boolraw}"
+
+powexpr = \( {expr} \)|-{expr}|{accname}|{num}
+mulexpr = {powexpr}( \^ {powexpr})?
+mulop = [/*%]
+addexpr = {mulexpr}( {mulop} {mulexpr})*
+addop = [+-]
+expr = {addexpr}( {addop} {addexpr})*
+n = ([\ \t]|\\[\r\n])*
+
+IMPLEMENTS = (?i:implements):{-n}{name}
+INHERITS = (?i:inherits):{-n}({name}({-n},?{-n}{name})*)?
+FRIEND = (?i:friend):{-n}({name}({-n},?{-n}{name})*)?
+
+what = (?i:SOURCE|HEADER)
+INCLUDE = (?i:INCLUDE(S)? {what}?: {filename} in {filename})
+
+ret_type = (?i:void|CCTK_INT{num}?|CCTK_REAL|CCTK_COMPLEX|CCTK_POINTER_TO_CONST|CCTK_POINTER)
+arg_type = (?i:CCTK_STRING|CCTK_INT{num}?|CCTK_REAL|CCTK_COMPLEX|CCTK_POINTER_TO_CONST|CCTK_POINTER|STRING)
+intent = (?i:INOUT|OUT|IN)
+array = (?i:array)
+fpointer = ({intent} (?i:CCTK_FPOINTER)|(?i:CCTK_FPOINTER) {intent}|(?i:CCTK_FPOINTER)) {name} {args}
+arg = {arg_type} ({fpointer}|{array} {intent} {name}|{intent} {array} {name}|{intent} {name})
+args = \( ({arg}( , {arg})* )?\)
+
+FUNCTION_ALIAS = (?i:{ret_type} FUNCTION | SUBROUTINE ) {name} {args}
+FUNCTION_PTR = (?i:CCTK_FPOINTER {name} \( {arg_type} {intent} {name} (, {arg_type} {intent} {name} )*\))
+REQUIRES_FUN = (?i:REQUIRES FUNCTION {name})
+USES_FUN = (?i:USES FUNCTION {name}|USES INCLUDE {what}?: {filename}([ \t]+{filename})*)
+PROVIDES_FUN = (?i:PROVIDES FUNCTION {name} WITH {name} LANGUAGE (?i:C|FORTRAN))
+FUNCTION = ({FUNCTION_ALIAS}|{FUNCTION_PTR}|{REQUIRES_FUN}|{USES_FUN}|{PROVIDES_FUN})
+
+access = (?i:protected|public|private)
+vtype = (?i:(CHAR|BYTE|INT{inum}?|REAL{rnum}?|COMPLEX{cnum}?))
+VARS = ({name}( ,? {name} )*)( ,)?
+gtype = (?i:GF|ARRAY|SCALAR)
+dim = {-num}
+timelevels = {-num}
+size = {expr}( , {expr})*|" {expr}( , {expr})* "
+distrib = (?i:CONSTANT|DEFAULT)
+ghostsize = {-size}
+stagger = (?i:[MCP](,[MCP])*)
+tags = {-quote}
+
+GROUP_VARS = (?i:CCTK_|){vtype} {name}( \[ {expr} \])? (?i:TYPE = {gtype} | DIM = {dim} |
+ TIMELEVELS = {timelevels} | SIZE = {size} | DISTRIB = {distrib} |
+ GHOSTSIZE = {ghostsize} | STAGGER = {stagger} | TAGS = {tags})* {dquote}? (
+ \{
+ {VARS}
+ \} {dquote}?
+ )?
+
+
+FUNC_GROUP = ({FUNCTION} |{access}: |{GROUP_VARS} |{INCLUDE} |{IMPLEMENTS} |{INHERITS} |{FRIEND} )
+
+dquote = "(\\{-any}|[^"])*"
+squote = '(\\{-any}|[^'])*'
+quote = {dquote}|{squote}
+
+intr = ^(?i: {FUNC_GROUP}*)$
diff --git a/src/piraha/pegs/param.peg b/src/piraha/pegs/param.peg
new file mode 100644
index 00000000..e5b54cd3
--- /dev/null
+++ b/src/piraha/pegs/param.peg
@@ -0,0 +1,141 @@
+uses = (?i:uses|)
+
+# The skipper is a crucial sub-pattern
+# that is activated by any whitespace in the
+# grammar file
+skipper = \b([\ \t\n\r\b]|\#[^\n]*|\\[\r\n])*
+
+any = [^]
+name = (?i:[a-z_][a-z0-9_]*)
+accname = {-name}(::{-name})*
+steerable = (?i:never|always|recover)
+accumexpr = \( ([^()]+|{accumexpr}) \)
+
+# Note slop on shared
+access = (?i: global : | restricted : | private : | shares :([\ \t]*{name}|) )
+#access = (?i: global : | restricted : | private : | shares : {name} )
+
+quote = "(\\{any}|[^"])*"
+
+num = [+\-]?[0-9]+
+intbound = (\* | {num} | )
+intrange = ([\[\(]?{intbound} :(?!:) {intbound}[\]\)]? | {intbound} )
+
+real = [+\-]?([0-9]+\.[0-9]+|[0-9]+\.|\.[0-9]+|[0-9]+)([eEdD][+\-]?{num}|)
+realbound = (\*|{real}| )
+realrange = [\(\[]?{realbound} :(?!:) {realbound}[\)\]]? | {realbound}
+
+boolraw = (?i:true|t|yes|y|false|f|no|n|1|0)
+bool = {-boolraw}|"{-boolraw}"
+
+string = {quote}|{name}|(\\[^]|[^\\ \t\r\n\b}])+
+
+keyword = {name}|{quote}
+
+intguts = (?i:
+ (CCTK_|)INT {name}(\[{num}\]|)
+ ({quote}|)
+ (as {name} |)
+ (steerable = {steerable} |accumulator = {accumexpr} |accumulator-base = {accname} )*
+ )
+
+intpar = (?i:
+ (uses|extends) {intguts}
+ ( \{
+ ( {intrange} (:: {quote}|) )*
+ \} |)|
+ {intguts}
+ ( \{
+ # some special slop here
+ #( {intrange} (:: {quote}|:: [a-z][^\n]*|) )*
+ ( {intrange} (:: {quote}|) )*
+ \} {num}|)
+ )
+
+realguts = (?i:
+ (CCTK_|)REAL {name}( \[{num}\]|)
+ ({quote}|)
+ (as {name} |)
+ (steerable = {steerable}|)
+ (accumulator = {accumexpr} |)
+ (accumulator-base = {accname} |)
+ )
+
+realpar = (?i:
+ (uses|extends) {realguts}
+ (\{
+ ( {realrange} (:: {quote} |) )*
+ \}|)|
+ {realguts}
+ (\{
+ # Note that we allow for lots of slop here
+ #( {realrange} (:: {quote} | {quote} | :: [a-z][^\n]*) )*
+ ( ("{realrange}"|{realrange}) (:: {quote}|) )*
+ \} {real}|)
+ )
+
+keywordguts = (?i:
+ (CCTK_|)KEYWORD {name}(\[{num}\]|)
+ ({quote}|)
+ (as {name} |)
+ (steerable = {steerable}|)
+ (accumulator = {accumexpr} |)
+ (accumulator-base = {accname} |)
+ )
+
+keywordpar = (?i:
+ (extends|uses) {keywordguts}
+ (\{
+ ( {keyword} (, {keyword})* (:: {-quote}|) )*
+ \}|)|
+ {keywordguts}
+ (\{
+ ( {keyword} (, {keyword})* (:: {-quote}|) )*
+ \} {keyword}|)
+ )
+
+stringguts = (?i:
+ (CCTK_|)STRING {name}(\[{num}\]|)
+ ({quote}|)
+ (as {name} |)
+ (steerable = {steerable} |accumulator = {accumexpr} |accumulator-base = {accname} )*
+ )
+
+stringpar = (?i:
+ (uses|extends) {stringguts}
+ (\{
+ ( {string} (, {string})* (:: {quote}|) )*
+ \}|)|
+ {stringguts}
+ (\{
+ # first option is weird
+ ( :: {quote} |{string} (, {string})* (:: {quote}|) )*
+ #({string} (, {string})* (:: {quote}|) )*
+ # no default is permitted!
+ \} ({string}|$)|)
+ )
+
+boolguts = (?i:
+ (CCTK_|)BOOLEAN {name}(\[{num}\]|)
+ ({quote}|)
+ (as {name} |)
+ (steerable = {steerable}|)
+ (accumulator = {accumexpr} |)
+ (accumulator-base = {accname} |)
+ )
+
+boolpar = (?i:
+ (uses|extends) {boolguts}
+ (\{
+ ({bool} (:: {quote} |))*
+ \}|)|
+ {boolguts}
+ (\{
+ # Note the weird slop here
+ #({bool} (:: {quote} |)|: :: {quote}|:: {quote})*
+ (:: {quote}|{bool} (:: {quote} |) )*
+ ( : :: {quote} )*
+ \} {bool}|)
+ )
+
+pars = ^ ({access}|{intpar}|{realpar}|{keywordpar}|{stringpar}|{boolpar})* $
diff --git a/src/piraha/pegs/schedule.peg b/src/piraha/pegs/schedule.peg
new file mode 100644
index 00000000..4a19d046
--- /dev/null
+++ b/src/piraha/pegs/schedule.peg
@@ -0,0 +1,70 @@
+skipper = \b([\ \t\n\r\b]|{-ccomment}|\#[^\n]*|\\[\r\n])*
+
+any = [^]
+name = (?i:[a-zA-Z_][a-zA-Z0-9_\-]*\b)
+expr = {name}|{num}
+vname = {name}( :: {name})*( \[ {expr} \]|)
+quote = "(\\{any}|[^"])*"
+ccomment = /\*((?!\*/){-any})*\*/
+num = [+\-]?[0-9]+(\.[0-9]+)?
+string = {name}|{quote}
+term = {num}|{name}
+par = \b(?i:as|at|in|while|if|before|after|while)\b
+pararg = ({vname}|\( {vname}( ,? {vname} )* \))
+assign = {name} = {num}
+
+boolpar = \( {boolexpr} \)
+eqfun = (?i:CCTK_Equals)
+actfun = (?i:CCTK_IsThornActive)
+actifun = (?i:CCTK_IsImplementationActive)
+booleq = {eqfun} \( {string} , {string} \)
+boolact = ({actfun}|{actifun}) \( {string} \)
+boolstar = \* {name}
+boolneg = \! {boolexpr}
+boolterm = (?i:{boolneg}
+ | {boolpar}
+ | {booleq}
+ | {boolact}
+ | {boolstar}
+ | {name} )
+
+boolop = (&&|\|\|)
+boolcmp = (>=|<=|==|!=|<|>)
+boolexpr = {boolterm} ({boolop} {boolexpr} )+
+ | {term} {boolcmp} {term} | {boolterm}
+
+lang = (?i:lang(uage|) : {name})
+group = (?i:group)
+nogroup =
+prepositions = ({preposition} )*
+preposition = {par} {pararg}
+sync = (?i:sync) : {vname}( , {vname}|[ \t]{vname})*
+options = (?i:options?) : {vname}( , {vname}|[ \t]{vname})*
+storage = (?i:storage) : {vname}( , {vname}|[ \t]{vname})*
+triggers = (?i:triggers?) : {vname}( , {vname}|[ \t]{vname})*
+reads = (?i:reads) : {qname}( , {qname}|[ \t]{qname})*
+writes = (?i:writes) : {qname}( , {qname}|[ \t]{qname})*
+qname = {vname}(\({region}(;{region})*\))?
+region = (everywhere|interior|boundary_ghostzones|boundary|all_timelevels|all_maps|all_reflevels)
+tags = (?i:tags) : {assign}( , {assign}|[ \t]{assign})*
+schedule = (?i:
+ schedule ({group}|{nogroup}) {name} {prepositions} \{
+ ( {storage}
+ | {lang}
+ | {sync}
+ | {options}
+ | {triggers}
+ | {reads}
+ | {writes}
+ | {tags}
+ )*
+ \} {quote}
+ )
+if = (?i:
+ if \( {boolexpr} \) {block} (else {if}|else {block}|)
+ )
+storage = (?i:storage: {vname}( , {vname}|([ \t]|\\\r?\n)+{vname})* )
+block = \{ (({statement}|{block}) )* \} | {statement}
+
+statement = ({schedule} |{if} |{storage} )
+sched = {-skipper}({statement}|{block})*$