diff --git a/.gitignore b/.gitignore index 23e910dd..6c8fc759 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,12 @@ build/* .vscode/ +# Emacs +*# +*.parked + +# Pegged self generator +pegged/dev/peggedgrammar + +# Test .done +.done diff --git a/dub.json b/dub.json index 630af664..412260fe 100644 --- a/dub.json +++ b/dub.json @@ -8,6 +8,8 @@ "pegged/peg.d", "pegged/grammar.d", "pegged/parser.d", + "pegged/parsetree.d", + "pegged/defaultparsetree.d", "pegged/introspection.d", "pegged/tohtml.d", "pegged/dynamic/grammar.d", diff --git a/examples/arithmetic/src/pegged/examples/arithmetic.d b/examples/arithmetic/src/pegged/examples/arithmetic.d index 5138ece9..e2c016a3 100644 --- a/examples/arithmetic/src/pegged/examples/arithmetic.d +++ b/examples/arithmetic/src/pegged/examples/arithmetic.d @@ -7,6 +7,7 @@ module pegged.examples.arithmetic; import std.conv: to; import pegged.grammar; +import pegged.defaultparsetree : ParseTree = DefaultParseTree; mixin(grammar(` # Arithmetic grammar with variable terminal diff --git a/examples/c/src/pegged/examples/cparser.d b/examples/c/src/pegged/examples/cparser.d index 42a607ca..b7225989 100644 --- a/examples/c/src/pegged/examples/cparser.d +++ b/examples/c/src/pegged/examples/cparser.d @@ -2,7 +2,7 @@ module pegged.examples.cparser; import pegged.grammar; -struct C +@safe struct C { enum names = [`TranslationUnit`:true, `ExternalDeclaration`:true, `FunctionDefinition`:true, `PrimaryExpression`:true, `PostfixExpression`:true, `ArgumentExpressionList`:true, `UnaryExpression`:true, `IncrementExpression`:true, `PlusPlus`:true, @@ -21,7 +21,9 @@ struct C `Keyword`:true, `Spacing`:true, `Comment`:true, `StringLiteral`:true, `DQChar`:true, `EscapeSequence`:true, `CharLiteral`:true, `IntegerLiteral`:true, `Integer`:true, `IntegerSuffix`:true, `FloatLiteral`:true, `Sign`:true]; - mixin decimateTree; + import pegged.defaultparsetree : ParseTree = DefaultParseTree; + mixin decimateTree!ParseTree; + mixin DefaultPatters!ParseTree; static ParseTree TranslationUnit(ParseTree p) { diff --git a/examples/parameterized/src/pegged/examples/parameterized.d b/examples/parameterized/src/pegged/examples/parameterized.d index 938e61c9..0b76e6ee 100644 --- a/examples/parameterized/src/pegged/examples/parameterized.d +++ b/examples/parameterized/src/pegged/examples/parameterized.d @@ -113,7 +113,7 @@ unittest A <- Parameterized.LineComment ")); - ParseTree p5 = ParamTest5("// This is a comment! + auto p5 = ParamTest5("// This is a comment! This is not a comment. End."); assert(p5.successful); diff --git a/examples/simple_arithmetic/src/pegged/examples/simple_arithmetic.d b/examples/simple_arithmetic/src/pegged/examples/simple_arithmetic.d index 29bd0d31..9a1ef2be 100644 --- a/examples/simple_arithmetic/src/pegged/examples/simple_arithmetic.d +++ b/examples/simple_arithmetic/src/pegged/examples/simple_arithmetic.d @@ -7,7 +7,7 @@ module pegged.examples.simple_arithmetic; import std.conv: to; import pegged.grammar; - +import pegged.defaultparsetree : ParseTree = DefaultParseTree; mixin(grammar(` Arithmetic: Term < Factor (Add / Sub)* diff --git a/makefile b/makefile index 73c975b0..724b1fbf 100644 --- a/makefile +++ b/makefile @@ -1,11 +1,47 @@ +include setup.mk + all: if [ -x /usr/bin/dmd ]; then \ - dmd -w -wi -O -release -noboundscheck -lib -oflibpegged.a pegged/peg.d pegged/grammar.d pegged/parser.d pegged/introspection.d pegged/dynamic/grammar.d pegged/dynamic/peg.d; \ + dmd -w -wi -O -release -noboundscheck -lib -oflibpegged.a $(DFILES); \ elif [ -x /usr/bin/ldc2 ]; then \ - ldc2 -w -wi -O2 -release -boundscheck=off -c -of=libpegged.a pegged/peg.d pegged/grammar.d pegged/parser.d pegged/dynamic/grammar.d pegged/dynamic/peg.d; \ + ldc2 -w -wi -O2 -release -boundscheck=off -c -of=libpegged.a $(DFILES); \ elif [ -x /usr/bin/gdc ]; then \ - gdc -Wall -O2 -frelease -fbounds-check=off -c -olibpegged.a pegged/peg.d pegged/grammar.d pegged/parser.d pegged/dynamic/grammar.d pegged/dynamic/peg.d; \ + gdc -Wall -O2 -frelease -fbounds-check=off -c -olibpegged.a $(DFILES); \ fi clean: rm -f libpegged.a + +info: + @echo "DFILES = $(DFILES)" + +ALL_PEG:=${shell find examples -maxdepth 1 -type d -not -path examples} + +define Pegs +$1/.done: + cd $1; dub test + touch $1/.done + +endef + +${foreach DONE,$(ALL_PEG), ${eval ${call Pegs,$(DONE)}}} + +DO_ALL := ${addsuffix /.done,$(ALL_PEG)} + +test-all: $(DO_ALL) + +test-clean: + rm -f $(DO_ALL) + +export DO_ALL_PEG=${foreach DONE,$(ALL_PEG), ${call Pegs,$(DONE)}} + + +CALL_PEG:=${call Pegs,c}} + +export CALL_PEG + +show: + @echo "$$CALL_PEG" + @echo "$$DO_ALL_PEG" + @echo $(ALL_PEG) + @echo $(DO_ALL) diff --git a/pegged/defaultparsetree.d b/pegged/defaultparsetree.d new file mode 100644 index 00000000..88931a5f --- /dev/null +++ b/pegged/defaultparsetree.d @@ -0,0 +1,32 @@ +/** + This module contaits functions and parameter for ParseTree data element + */ +module pegged.defaultparsetree; + +import std.traits : isType, ReturnType, ForeachType, isCallable, Unqual; + +private import pegged.peg : ParseCollectionsM; +private import pegged.dynamic.peg : DynamicPeg; +import pegged.parsetree : isParseTree, ParseTreeM; +/** + The basic parse tree, as used throughout the project. + You can define your own parse tree node, but respect the basic layout. + Example: + struct MyParseTree { + mixin ParseTreeM; + ... My own stuff + } +*/ + +struct DefaultParseTree { + mixin ParseTreeM; + mixin ParseCollectionsM; + alias DPEG=DynamicPeg!(ParseTree); +// mixin DynamicParseCollectionsM; + +} + +//mixin DynmicParseCollectionM!(ParseTree); + + +static assert(isParseTree!DefaultParseTree); diff --git a/pegged/dev/Makefile b/pegged/dev/Makefile new file mode 100644 index 00000000..512eabf1 --- /dev/null +++ b/pegged/dev/Makefile @@ -0,0 +1,11 @@ + +DCFALGS+=-I../../ +DCFALGS+=-I../../examples/peggedgrammar/src/ +LDFLAGS+=../../libpegged.a +DFILES+=../../examples/peggedgrammar/src/pegged/examples/peggedgrammar.d + +all: + dmd $(DCFALGS) $(DFILES) regenerate.d $(LDFLAGS) + +clean: + rm -f regenerate diff --git a/pegged/dev/regenerate.d b/pegged/dev/regenerate.d index 961118b9..51418853 100644 --- a/pegged/dev/regenerate.d +++ b/pegged/dev/regenerate.d @@ -5,7 +5,7 @@ module pegged.dev.regenerate; import pegged.grammar; import pegged.examples.peggedgrammar; -import pegged.examples.testergrammar; +//import pegged.examples.testergrammar; void main() { diff --git a/pegged/dynamic/grammar.d b/pegged/dynamic/grammar.d index a40d1bb0..2493abcb 100644 --- a/pegged/dynamic/grammar.d +++ b/pegged/dynamic/grammar.d @@ -15,15 +15,23 @@ import std.algorithm : startsWith; import std.array; import std.stdio; -import pegged.peg; import pegged.parser; import pegged.dynamic.peg; -struct ParameterizedRule +private import pegged.parsetree : isParseTree; + +struct ParameterizedRule(ParseTree) { size_t numArgs; - Dynamic delegate(Dynamic[]) code; - + alias Dynamic=ParseTree.Dynamic; + alias DynamicModifier = Dynamic delegate(Dynamic[]); + DynamicModifier code; + +// @disbale this(); + this(const size_t num, DynamicModifier code) { + numArgs = num; + this.code=code; + } Dynamic opCall(D...)(D rules) { Dynamic[] args; @@ -64,20 +72,14 @@ struct ParameterizedRule } } -ParameterizedRule parameterizedRule(size_t n, Dynamic delegate(Dynamic[] d) code) -{ - ParameterizedRule pr; - pr.numArgs = n; - pr.code = code; - return pr; -} - -struct DynamicGrammar +struct DynamicGrammar(ParseTree) { + alias DPEG=ParseTree.DPEG; string grammarName; string startingRule; + alias Dynamic = ParseTree.Dynamic; Dynamic[string] rules; - ParameterizedRule[string] paramRules; + ParameterizedRule!ParseTree[string] paramRules; ParseTree decimateTree(ParseTree p) { @@ -132,7 +134,7 @@ struct DynamicGrammar void opIndexAssign(D)(D code, string s) { - rules[s]= named(code, grammarName ~ "." ~ s); + rules[s]= DPEG.named(code, grammarName ~ "." ~ s); } Dynamic opIndex(string s) @@ -142,7 +144,7 @@ struct DynamicGrammar } // Helper to insert 'Spacing' before and after Primaries -ParseTree spaceArrow(ParseTree input) +ParseTree spaceArrow(ParseTree)(ParseTree input) if (isParseTree!ParseTree) { ParseTree wrapInSpaces(ParseTree p) { @@ -160,21 +162,25 @@ ParseTree spaceArrow(ParseTree input) result.children = spacer ~ result.children ~ spacer; return result; } - return modify!( p => p.name == "Pegged.Primary", + import pegged.peg : modify; + return modify!(ParseTree, p => p.name == "Pegged.Primary", wrapInSpaces)(input); } -Dynamic makeRule(string def, Dynamic[string] context) +ParseTree.Dynamic makeRule(ParseTree)(string def, Dynamic[string] context) if(isParseTree!ParseTree) { ParseTree p = Pegged.decimateTree(Pegged.Definition(def)); return makeRule(p, context); } -Dynamic makeRule(ParseTree def, Dynamic[string] context) + + +ParseTree.Dynamic makeRule(ParseTree)(ParseTree def, ParseTree.Dynamic[string] context) if (isParseTree!ParseTree) { - Dynamic code; + alias DPEG=ParseTree.DPEG; + ParseTree.Dynamic code; - Dynamic getDyn(string name) + ParseTree.Dynamic getDyn(string name) { if (name in context) return context[name]; @@ -182,7 +188,7 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) throw new Exception("Unknown name: " ~ name); } - Dynamic ruleFromTree(ParseTree p) + ParseTree.Dynamic ruleFromTree(ParseTree p) { //writeln("rfT: ", p.name, " ", p.matches); //Dynamic result; @@ -191,10 +197,10 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) case "Pegged.Expression": //if (p.children.length > 1) // OR expression //{ - Dynamic[] children; + ParseTree.Dynamic[] children; foreach(seq; p.children) children ~= ruleFromTree(seq); - return distribute!(or)(children); + return distribute!(ParseTree, DPEG.or)(children); //} //else // One child -> just a sequence, no need for a or!( , ) //{ @@ -204,10 +210,10 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) case "Pegged.Sequence": //if (p.children.length > 1) // real sequence //{ - Dynamic[] children; + ParseTree.Dynamic[] children; foreach(seq; p.children) children ~= ruleFromTree(seq); - return distribute!(pegged.dynamic.peg.and)(children); + return distribute!(ParseTree, DPEG.and)(children); /+} else // One child -> just a Suffix, no need for a and!( , ) { @@ -241,16 +247,16 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) case "Pegged.Literal": //writeln("Literal: ", p.matches); if(p.matches.length == 3) // standard case - return literal(p.matches[1]); + return DPEG.literal(p.matches[1]); else // only two children -> empty literal - return eps(); + return DPEG.eps(); case "Pegged.CharClass": if (p.children.length > 1) { - Dynamic[] children; + ParseTree.Dynamic[] children; foreach(seq; p.children) children ~= ruleFromTree(seq); - return distribute!(pegged.dynamic.peg.or)(children); + return distribute!(ParseTree, DPEG.or)(children); } else // One child -> just a sequence, no need for a or!( , ) { @@ -261,7 +267,7 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) /// Make the generation at the Char level: directly what is needed, be it `` or "" or whatever if (p.children.length > 1) // a-b range { - return charRange(p.matches[0].front, p.matches[2].front); + return DPEG.charRange(p.matches[0].front, p.matches[2].front); } else // lone char { @@ -272,23 +278,23 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) case "\\[": case "\\]": case "\\-": - return literal(ch[0..1]); + return DPEG.literal(ch[0..1]); case "\\\'": - return literal("\'"); + return DPEG.literal("\'"); case "\\`": - return literal("`"); + return DPEG.literal("`"); case "\\": case "\\\\": - return literal("\\"); + return DPEG.literal("\\"); case "\"": case "\\\"": - return literal("\""); + return DPEG.literal("\""); case "\n": case "\r": case "\t": - return literal(ch); + return DPEG.literal(ch); default: - return literal(ch); + return DPEG.literal(ch); } } case "Pegged.Char": @@ -303,44 +309,44 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) case "\\\"": case "\\`": case "\\\\": - return literal(ch[1..$]); + return DPEG.literal(ch[1..$]); case "\n": case "\r": case "\t": - return literal(ch); + return DPEG.literal(ch); default: - return literal(ch); + return DPEG.literal(ch); } //break; case "Pegged.POS": - return posLookahead(ruleFromTree(p.children[0])); + return DPEG.posLookahead(ruleFromTree(p.children[0])); case "Pegged.NEG": - return negLookahead(ruleFromTree(p.children[0])); + return DPEG.negLookahead(ruleFromTree(p.children[0])); case "Pegged.FUSE": - return fuse(ruleFromTree(p.children[0])); + return DPEG.fuse(ruleFromTree(p.children[0])); case "Pegged.DISCARD": - return discard(ruleFromTree(p.children[0])); + return DPEG.discard(ruleFromTree(p.children[0])); case "Pegged.KEEP": - return keep(ruleFromTree(p.children[0])); + return DPEG.keep(ruleFromTree(p.children[0])); case "Pegged.DROP": - return drop(ruleFromTree(p.children[0])); + return DPEG.drop(ruleFromTree(p.children[0])); case "Pegged.PROPAGATE": - return propagate(ruleFromTree(p.children[0])); + return DPEG.propagate(ruleFromTree(p.children[0])); case "Pegged.OPTION": - return option(ruleFromTree(p.children[0])); + return DPEG.option(ruleFromTree(p.children[0])); case "Pegged.ZEROORMORE": - return zeroOrMore(ruleFromTree(p.children[0])); + return DPEG.zeroOrMore(ruleFromTree(p.children[0])); case "Pegged.ONEORMORE": - return oneOrMore(ruleFromTree(p.children[0])); + return DPEG.oneOrMore(ruleFromTree(p.children[0])); case "Pegged.Action": - Dynamic result = ruleFromTree(p.children[0]); + ParseTree.Dynamic result = ruleFromTree(p.children[0]); foreach(act; p.matches[1..$]) - result = action(result, getDyn(act)); + result = DPEG.action(result, getDyn(act)); return result; case "Pegged.ANY": - return any(); + return DPEG.any(); case "Pegged.WrapAround": - return wrapAround( ruleFromTree(p.children[0]) + return DPEG.wrapAround( ruleFromTree(p.children[0]) , ruleFromTree(p.children[1]) , ruleFromTree(p.children[2])); default: @@ -354,28 +360,28 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) code = ruleFromTree(def.children[2]); break; case "Pegged.FUSEARROW": - code = fuse(ruleFromTree(def.children[2])); + code = DPEG.fuse(ruleFromTree(def.children[2])); break; case "Pegged.DISCARDARROW": - code = discard(ruleFromTree(def.children[2])); + code = DPEG.discard(ruleFromTree(def.children[2])); break; case "Pegged.KEEPARROW": - code = keep(ruleFromTree(def.children[2])); + code = DPEG.keep(ruleFromTree(def.children[2])); break; case "Pegged.DROPARROW": - code = drop(ruleFromTree(def.children[2])); + code = DPEG.drop(ruleFromTree(def.children[2])); break; case "Pegged.PROPAGATEARROW": - code = propagate(ruleFromTree(def.children[2])); + code = DPEG.propagate(ruleFromTree(def.children[2])); break; case "Pegged.SPACEARROW": ParseTree modified = spaceArrow(def.children[2]); code = ruleFromTree(modified); break; case "Pegged.ACTIONARROW": - Dynamic actionResult = ruleFromTree(def.children[2]); + ParseTree.Dynamic actionResult = ruleFromTree(def.children[2]); foreach(act; def.children[1].matches[1..$]) - actionResult = action(actionResult, getDyn(act)); + actionResult = DPEG.action(actionResult, getDyn(act)); code = actionResult; break; default: @@ -383,13 +389,14 @@ Dynamic makeRule(ParseTree def, Dynamic[string] context) //break; } - return named(code, def.matches[0]); + return DPEG.named(code, def.matches[0]); } -DynamicGrammar grammar(string definition, Dynamic[string] context = null) +DynamicGrammar!ParseTree grammar(ParseTree)(string definition, ParseTree.Dynamic[string] context = null) if(isParseTree!ParseTree) { + alias DPEG=ParseTree.DPEG; //writeln("Entering dyn gram"); - ParseTree defAsParseTree = Pegged(definition); + ParseTree defAsParseTree = GenericPegged!(ParseTree).Pegged(definition); //writeln(defAsParseTree); if (!defAsParseTree.successful) { @@ -397,7 +404,7 @@ DynamicGrammar grammar(string definition, Dynamic[string] context = null) throw new Exception("Bad grammar input: " ~ defAsParseTree.toString("")); } - DynamicGrammar gram; + DynamicGrammar!ParseTree gram; foreach(name, rule; context) { gram.rules[name] = rule; @@ -410,13 +417,13 @@ DynamicGrammar grammar(string definition, Dynamic[string] context = null) gram.grammarName = shortGrammarName; // Predefined spacing - gram.rules["Spacing"] = discard(zeroOrMore(or(literal(" "), literal("\t"), literal("\n"), literal("\r")))); + gram.rules["Spacing"] = DPEG.discard(DPEG.zeroOrMore(DPEG.or(DPEG.literal(" "), DPEG.literal("\t"), DPEG.literal("\n"), DPEG.literal("\r")))); ParseTree[] definitions = p.children[1 .. $]; foreach(i,def; definitions) { - gram[def.matches[0]] = fail(); + gram[def.matches[0]] = DPEG.fail(); } foreach(i,def; definitions) @@ -427,13 +434,13 @@ DynamicGrammar grammar(string definition, Dynamic[string] context = null) gram.startingRule = shortName; // prepending the global grammar name, to get a qualified-name rule 'Gram.Rule' def.matches[0] = shortGrammarName ~ "." ~ def.matches[0]; - gram.rules[shortName] = makeRule(def, gram.rules); + gram.rules[shortName] = makeRule!ParseTree(def, gram.rules); } return gram; } -Dynamic distribute(alias fun)(Dynamic[] args) +ParseTree.Dynamic distribute(ParseTree, alias fun)(ParseTree.Dynamic[] args) if(isParseTree!ParseTree) { //mixin(makeSwitch(40)); switch(args.length) @@ -451,6 +458,6 @@ Dynamic distribute(alias fun)(Dynamic[] args) case 6: return fun(args[0], args[1], args[2], args[3], args[4], args[5]); default: - return fun(fun(args[0], args[1], args[2], args[3], args[4], args[5]), distribute!fun(args[6..$])); + return fun(fun(args[0], args[1], args[2], args[3], args[4], args[5]), distribute!(ParseTree, fun)(args[6..$])); } } diff --git a/pegged/dynamic/peg.d b/pegged/dynamic/peg.d index 9e929f81..4070409c 100644 --- a/pegged/dynamic/peg.d +++ b/pegged/dynamic/peg.d @@ -8,446 +8,454 @@ import std.stdio; import pegged.peg; -alias ParseTree delegate(ParseTree) Dynamic; -string getName(D)(D rule) -{ - return callDynamic(rule, ParseTree()).name; -} +private import pegged.parsetree : isParseTree; +// private alias ParseTree=DefaultParseTree; +// alias ParseTree delegate(ParseTree) Dynamic; -ParseTree callDynamic(D)(D d, string s) -{ - static if (is(typeof(d) : ParseTree delegate(ParseTree)) || is(typeof(d) : ParseTree function(ParseTree))) - return d(ParseTree("",false,[], s)); - else static if (is(typeof(d) : ParseTree delegate(ParseTree) delegate()) || is(typeof(d) : ParseTree function(ParseTree) delegate())) - return d()(ParseTree("",false,[], s)); - else static if (is(typeof(d) : ParseTree delegate(string)) || is(typeof(d) : ParseTree function(string))) - return d(s); - else static if (is(typeof(d) : ParseTree delegate(string) delegate()) || is(typeof(d) : ParseTree function(string) delegate())) - return d()(s); - else - static assert(false, "Bad callDynamic, with type " ~ D.stringof); -} +@safe struct DynamicPeg(ParseTree) { + static { + string getName(D)(D rule) + { + return callDynamic(rule, ParseTree()).name; + } -ParseTree callDynamic(D)(D d, ParseTree p) -{ - static if (is(typeof(d) : ParseTree delegate(ParseTree)) || is(typeof(d) : ParseTree function(ParseTree))) - return d(p); - else static if (is(typeof(d) : ParseTree delegate(ParseTree) delegate()) || is(typeof(d) : ParseTree function(ParseTree) delegate())) - return d()(p); - else static if (is(typeof(d) : ParseTree delegate(string)) || is(typeof(d) : ParseTree function(string))) - return d(p.input[p.end..$]); - else static if (is(typeof(d) : ParseTree delegate(string) delegate()) || is(typeof(d) : ParseTree function(string) delegate())) - return d()(p.input[p.end..$]); - else - static assert(false, "Bad callDynamic, with type " ~ D.stringof); -} + ParseTree callDynamic(D)(D d, string s) + { + static if (is(typeof(d) : ParseTree delegate(ParseTree)) || is(typeof(d) : ParseTree function(ParseTree))) + return d(ParseTree("",false,[], s)); + else static if (is(typeof(d) : ParseTree delegate(ParseTree) delegate()) || is(typeof(d) : ParseTree function(ParseTree) delegate())) + return d()(ParseTree("",false,[], s)); + else static if (is(typeof(d) : ParseTree delegate(string)) || is(typeof(d) : ParseTree function(string))) + return d(s); + else static if (is(typeof(d) : ParseTree delegate(string) delegate()) || is(typeof(d) : ParseTree function(string) delegate())) + return d()(s); + else + assert(false, "Bad callDynamic, with type " ~ D.stringof); + } -Dynamic fail() -{ - return (ParseTree p) - { - return ParseTree("fail", false, ["fail"], p.input, p.end, p.end); - }; -} + ParseTree callDynamic(D)(D d, ParseTree p) + { + static if (is(typeof(d) : ParseTree delegate(ParseTree)) || is(typeof(d) : ParseTree function(ParseTree))) + return d(p); + else static if (is(typeof(d) : ParseTree delegate(ParseTree) delegate()) || is(typeof(d) : ParseTree function(ParseTree) delegate())) + return d()(p); + else static if (is(typeof(d) : ParseTree delegate(string)) || is(typeof(d) : ParseTree function(string))) + return d(p.input[p.end..$]); + else static if (is(typeof(d) : ParseTree delegate(string) delegate()) || is(typeof(d) : ParseTree function(string) delegate())) + return d()(p.input[p.end..$]); + else + static assert(false, "Bad callDynamic, with type " ~ D.stringof); + } -Dynamic eoi() -{ - return (ParseTree p) - { - if (p.end == p.input.length) - return ParseTree("eoi", true, [], p.input, p.end, p.end); - else - return ParseTree("eoi", false, ["end of input"], p.input, p.end, p.end); - }; -} + ParseTree.Dynamic fail() + { + return (ParseTree p) + { + return ParseTree("fail", false, ["fail"], p.input, p.end, p.end); + }; + } -Dynamic eps() -{ - return (ParseTree p) - { - return ParseTree("eps", true, [""], p.input, p.end, p.end); - }; -} + ParseTree.Dynamic eoi() + { + return (ParseTree p) + { + if (p.end == p.input.length) + return ParseTree("eoi", true, [], p.input, p.end, p.end); + else + return ParseTree("eoi", false, ["end of input"], p.input, p.end, p.end); + }; + } -Dynamic any() -{ - return(ParseTree p) - { - if (p.end < p.input.length) - return ParseTree("any", true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); - else - return ParseTree("any", false, ["any char"], p.input, p.end, p.end); - }; -} + ParseTree.Dynamic eps() + { + return (ParseTree p) + { + return ParseTree("eps", true, [""], p.input, p.end, p.end); + }; + } -Dynamic literal(string s) -{ - return (ParseTree p) - { - if (p.end+s.length <= p.input.length && p.input[p.end..p.end+s.length] == s) - return ParseTree("literal!(\"" ~ s ~ "\")", true, [s], p.input, p.end, p.end+s.length); - else - return ParseTree("literal!(\"" ~ s ~ "\")", false, [`"` ~ s ~ `"`], p.input, p.end, p.end); + ParseTree.Dynamic any() + { + return(ParseTree p) + { + if (p.end < p.input.length) + return ParseTree("any", true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); + else + return ParseTree("any", false, ["any char"], p.input, p.end, p.end); + }; + } - }; -} + ParseTree.Dynamic literal(string s) + { + return (ParseTree p) + { + if (p.end+s.length <= p.input.length && p.input[p.end..p.end+s.length] == s) + return ParseTree("literal!(\"" ~ s ~ "\")", true, [s], p.input, p.end, p.end+s.length); + else + return ParseTree("literal!(\"" ~ s ~ "\")", false, [`"` ~ s ~ `"`], p.input, p.end, p.end); -Dynamic charRange(dchar begin, dchar end) -{ - return (ParseTree p) - { - string longName = "a char between '"~to!string(begin)~"' and '"~to!string(end)~"'"; - if (p.end < p.input.length && p.input[p.end] >= begin && p.input[p.end] <= end) - return ParseTree("charRange!(" ~ to!string(begin) ~ ", " ~ to!string(end) ~ ")", true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); - else - return ParseTree("charRange!(" ~ to!string(begin) ~ ", " ~ to!string(end) ~ ")", false, [longName], p.input, p.end, p.end); - }; + }; + } -} + ParseTree.Dynamic charRange(dchar begin, dchar end) + { + return (ParseTree p) + { + string longName = "a char between '"~to!string(begin)~"' and '"~to!string(end)~"'"; + if (p.end < p.input.length && p.input[p.end] >= begin && p.input[p.end] <= end) + return ParseTree("charRange!(" ~ to!string(begin) ~ ", " ~ to!string(end) ~ ")", true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); + else + return ParseTree("charRange!(" ~ to!string(begin) ~ ", " ~ to!string(end) ~ ")", false, [longName], p.input, p.end, p.end); + }; -Dynamic wrapAround(B, M, A)(B before, M middle, A after) -{ - return(ParseTree p) - { - ParseTree temp = callDynamic(before,p); - if (!temp.successful) - return temp; - - ParseTree result = callDynamic(middle,temp); - if (!result.successful) - return result; - result.begin = temp.begin; - - temp = callDynamic(after,result); - if (!temp.successful) - return temp; - - result.end = temp.end; - return result; - }; -} + } -Dynamic zeroOrMore(D)(D d) -{ - return (ParseTree p) - { - string name = "zeroOrMore!(" ~ getName(d) ~ ")"; - ParseTree result = ParseTree(name, true, [], p.input, p.end, p.end); - ParseTree temp = callDynamic(d,result); - while(temp.successful - && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules - || temp.name.startsWith("discard!("))) + ParseTree.Dynamic wrapAround(B, M, A)(B before, M middle, A after) { - result.matches ~= temp.matches; - result.children ~= temp; - result.end = temp.end; - temp = callDynamic(d, result); - } - result.successful = true; - return result; - }; -} + return(ParseTree p) + { + ParseTree temp = callDynamic(before,p); + if (!temp.successful) + return temp; -Dynamic oneOrMore(D)(D d) -{ - return(ParseTree p) - { - string name = "oneOrMore!(" ~ getName(d) ~ ")"; - ParseTree result = ParseTree(name, false, [], p.input, p.end, p.end); - ParseTree temp = callDynamic(d, result); + ParseTree result = callDynamic(middle,temp); + if (!result.successful) + return result; + result.begin = temp.begin; - if (!temp.successful) - { - result.matches = temp.matches; - result.children = [temp]; - result.end = temp.end; + temp = callDynamic(after,result); + if (!temp.successful) + return temp; + + result.end = temp.end; + return result; + }; } - else + + ParseTree.Dynamic zeroOrMore(D)(D d) { - while( temp.successful - && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules - || temp.name.startsWith("discard!("))) + return (ParseTree p) { - result.matches ~= temp.matches; - result.children ~= temp; - result.end = temp.end; - temp = callDynamic(d, result); - } - result.successful = true; + string name = "zeroOrMore!(" ~ getName(d) ~ ")"; + ParseTree result = ParseTree(name, true, [], p.input, p.end, p.end); + ParseTree temp = callDynamic(d,result); + while(temp.successful + && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules + || temp.name.startsWith("discard!("))) + { + result.matches ~= temp.matches; + result.children ~= temp; + result.end = temp.end; + temp = callDynamic(d, result); + } + result.successful = true; + return result; + }; } - return result; - }; -} -Dynamic option(D)(D d) -{ - return (ParseTree p) - { - string name = "option!(" ~ getName(d) ~ ")"; - ParseTree result = callDynamic(d, p); - if (result.successful) - return ParseTree(name, true, result.matches, result.input, result.begin, result.end, [result]); - else - return ParseTree(name, true, [], p.input, p.end, p.end, null); - }; -} + ParseTree.Dynamic oneOrMore(D)(D d) + { + return(ParseTree p) + { + string name = "oneOrMore!(" ~ getName(d) ~ ")"; + ParseTree result = ParseTree(name, false, [], p.input, p.end, p.end); + ParseTree temp = callDynamic(d, result); -Dynamic and(T...)(T rules) if (T.length) -{ - return (ParseTree p) - { - bool keepNode(ParseTree node) + if (!temp.successful) + { + result.matches = temp.matches; + result.children = [temp]; + result.end = temp.end; + } + else + { + while( temp.successful + && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules + || temp.name.startsWith("discard!("))) + { + result.matches ~= temp.matches; + result.children ~= temp; + result.end = temp.end; + temp = callDynamic(d, result); + } + result.successful = true; + } + return result; + }; + } + + ParseTree.Dynamic option(D)(D d) { - return node.name.startsWith("keep!(") - || ( !node.name.startsWith("discard!(") - //&& !node.name.startsWith("drop!(") - && node.matches !is null - //&& node.begin != node.end - ); + return (ParseTree p) + { + string name = "option!(" ~ getName(d) ~ ")"; + ParseTree result = callDynamic(d, p); + if (result.successful) + return ParseTree(name, true, result.matches, result.input, result.begin, result.end, [result]); + else + return ParseTree(name, true, [], p.input, p.end, p.end, null); + }; } + ParseTree.Dynamic and(T...)(T rules) if (T.length) + { + return (ParseTree p) + { + bool keepNode(ParseTree node) + { + return node.name.startsWith("keep!(") + || ( !node.name.startsWith("discard!(") + //&& !node.name.startsWith("drop!(") + && node.matches !is null + //&& node.begin != node.end + ); + } - string name = "and!(" ~ ")"; - ParseTree result = ParseTree(name, false, [], p.input, p.end, p.end, []); + string name = "and!(" ~ ")"; - foreach(i,r; rules) - { - ParseTree temp = callDynamic(r, result); + ParseTree result = ParseTree(name, false, [], p.input, p.end, p.end, []); - result.end = temp.end; - if (temp.successful) - { - if (keepNode(temp)) + foreach(i,r; rules) { - result.matches ~= temp.matches; - if (temp.name.startsWith("drop!(")) - {} - else if (temp.name.startsWith("propagate!(")) - result.children ~= temp.children; + ParseTree temp = callDynamic(r, result); + + result.end = temp.end; + if (temp.successful) + { + if (keepNode(temp)) + { + result.matches ~= temp.matches; + if (temp.name.startsWith("drop!(")) + {} + else if (temp.name.startsWith("propagate!(")) + result.children ~= temp.children; + else + result.children ~= temp; + } + } else - result.children ~= temp; + { + result.children ~= temp;// add the failed node, to indicate which failed + if (temp.matches.length > 0) + result.matches ~= temp.matches[$-1]; + return result; // and end the parsing attempt right there + } } - } - else - { - result.children ~= temp;// add the failed node, to indicate which failed - if (temp.matches.length > 0) - result.matches ~= temp.matches[$-1]; - return result; // and end the parsing attempt right there - } + result.successful = true; + return result; + }; } - result.successful = true; - return result; - }; -} -Dynamic or(T...)(T rules) -{ - return (ParseTree p) - { - // error-management - ParseTree longestFail = ParseTree("or", false, [], p.input, p.end, 0); - string[] errorStrings; - size_t errorStringChars; - string orErrorString; - - ParseTree[rules.length] results; - string[rules.length] names; - size_t[rules.length] failedLength; - size_t maxFailedLength; - - // Real 'or' loop - foreach(i,r; rules) + ParseTree.Dynamic or(T...)(T rules) { - ParseTree temp = callDynamic(r, p); - if (temp.successful) - { - temp.children = [temp]; - temp.name = "or"; - return temp; - } - else + return (ParseTree p) @safe { - enum errName = " (" ~")"; - failedLength[i] = temp.end; - if (temp.end >= longestFail.end) + // error-management + ParseTree longestFail = ParseTree("or", false, [], p.input, p.end, 0); + string[] errorStrings; + size_t errorStringChars; + //string orErrorString; + + ParseTree[rules.length] results; + string[rules.length] names; + size_t[rules.length] failedLength; + size_t maxFailedLength; + + // Real 'or' loop + foreach(i,r; rules) { - maxFailedLength = temp.end; - longestFail = temp; - names[i] = errName; - results[i] = temp; - - if (temp.end == longestFail.end) - errorStringChars += temp.matches[$-1].length + errName.length + 4; + ParseTree temp = callDynamic(r, p); + if (temp.successful) + { + temp.children = [temp]; + temp.name = "or"; + return temp; + } else - errorStringChars = temp.matches[$-1].length + errName.length + 4; + { + enum errName = " (" ~")"; + failedLength[i] = temp.end; + if (temp.end >= longestFail.end) + { + maxFailedLength = temp.end; + longestFail = temp; + names[i] = errName; + results[i] = temp; + + if (temp.end == longestFail.end) + errorStringChars += temp.matches[$-1].length + errName.length + 4; + else + errorStringChars = temp.matches[$-1].length + errName.length + 4; + } + // Else, this error parsed less input than another one: we discard it. + } } - // Else, this error parsed less input than another one: we discard it. - } - } - // All subrules failed, we will take the longest match as the result - // If more than one node failed at the same (farthest) position, we concatenate their error messages + // All subrules failed, we will take the longest match as the result + // If more than one node failed at the same (farthest) position, we concatenate their error messages + + char[] errString;// = new char[](errorStringChars); + errString.length = errorStringChars; + uint start = 0; + foreach(i; 0..rules.length) + { + if (failedLength[i] == maxFailedLength) + { + auto temp = results[i]; + auto len = temp.matches[$-1].length; + auto nlen = names[i].length; + errString[start .. start+len] = temp.matches[$-1][]; + errString[start+len .. start+len+names[i].length] = names[i][]; + errString[start+len+nlen .. start+len+nlen+4] = " or "; + start += len + names[i].length + 4; + } + } + (() @trusted { + string orErrorString = cast(string)errString[0..$-4]; + longestFail.matches = longestFail.matches[0..$-1] // discarding longestFail error message + ~ [orErrorString]; // and replacing it by the new, concatenated one. + })(); + longestFail.name = "or"; + longestFail.begin = p.end; + return longestFail; + }; + } - char[] errString;// = new char[](errorStringChars); - errString.length = errorStringChars; - uint start = 0; - foreach(i; 0..rules.length) + ParseTree.Dynamic posLookahead(D)(D d) { - if (failedLength[i] == maxFailedLength) + return (ParseTree p) { - auto temp = results[i]; - auto len = temp.matches[$-1].length; - auto nlen = names[i].length; - errString[start .. start+len] = temp.matches[$-1][]; - errString[start+len .. start+len+names[i].length] = names[i][]; - errString[start+len+nlen .. start+len+nlen+4] = " or "; - start += len + names[i].length + 4; - } + string name = "posLookahead!(" ~ getName(d) ~ ")"; + ParseTree temp = callDynamic(d,p); + if (temp.successful) + return ParseTree(name, temp.successful, [], p.input, p.end, p.end); + else + return ParseTree(name, temp.successful, [temp.matches[$-1]], p.input, p.end, p.end); + }; } - orErrorString = cast(string)(errString[0..$-4]); - - longestFail.matches = longestFail.matches[0..$-1] // discarding longestFail error message - ~ [orErrorString]; // and replacing it by the new, concatenated one. - longestFail.name = "or"; - longestFail.begin = p.end; - return longestFail; - }; -} -Dynamic posLookahead(D)(D d) -{ - return (ParseTree p) - { - string name = "posLookahead!(" ~ getName(d) ~ ")"; - ParseTree temp = callDynamic(d,p); - if (temp.successful) - return ParseTree(name, temp.successful, [], p.input, p.end, p.end); - else - return ParseTree(name, temp.successful, [temp.matches[$-1]], p.input, p.end, p.end); - }; -} - -Dynamic negLookahead(D)(D d) -{ - return (ParseTree p) - { - string name = "negLookahead!(" ~ getName(d) ~ ")"; - ParseTree temp = callDynamic(d,p); - if (temp.successful) - return ParseTree(name, false, ["anything but \"" ~ p.input[temp.begin..temp.end] ~ "\""], p.input, p.end, p.end); - else - return ParseTree(name, true, [], p.input, p.end, p.end); - }; -} + ParseTree.Dynamic negLookahead(D)(D d) + { + return (ParseTree p) + { + string name = "negLookahead!(" ~ getName(d) ~ ")"; + ParseTree temp = callDynamic(d,p); + if (temp.successful) + return ParseTree(name, false, ["anything but \"" ~ p.input[temp.begin..temp.end] ~ "\""], p.input, p.end, p.end); + else + return ParseTree(name, true, [], p.input, p.end, p.end); + }; + } -Dynamic named(D)(D d, string name) -{ - return (ParseTree p) - { - ParseTree result = callDynamic(d,p); - result.name = name; - return result; - }; -} + ParseTree.Dynamic named(D)(D d, string name) + { + return (ParseTree p) + { + ParseTree result = callDynamic(d,p); + result.name = name; + return result; + }; + } -Dynamic action(D, A)(D d, A act) -{ - return (ParseTree p) - { - return callDynamic(act, callDynamic(d,p)); - }; -} + ParseTree.Dynamic action(D, A)(D d, A act) + { + return (ParseTree p) + { + return callDynamic(act, callDynamic(d,p)); + }; + } -Dynamic fuse(D)(D d) -{ - return(ParseTree p) - { - p = callDynamic(d,p); - if (p.successful) + ParseTree.Dynamic fuse(D)(D d) { - if (p.matches.length != 0) - p.matches = [join(p.matches)]; + return(ParseTree p) + { + p = callDynamic(d,p); + if (p.successful) + { + if (p.matches.length != 0) + p.matches = [join(p.matches)]; - p.children = null; // also discard children + p.children = null; // also discard children + } + return p; + }; } - return p; - }; -} -Dynamic discardChildren(D)(D d) -{ - return (ParseTree p) - { - p = callDynamic(d,p); - p.children = null; - return p; - }; -} + ParseTree.Dynamic discardChildren(D)(D d) + { + return (ParseTree p) + { + p = callDynamic(d,p); + p.children = null; + return p; + }; + } -Dynamic discardMatches(D)(D d) -{ - return (ParseTree p) - { - p = callDynamic(d,p); - if (p.successful) - p.matches = null; - return p; - }; -} + ParseTree.Dynamic discardMatches(D)(D d) + { + return (ParseTree p) + { + p = callDynamic(d,p); + if (p.successful) + p.matches = null; + return p; + }; + } -Dynamic discard(D)(D d) -{ - return (ParseTree p) - { - ParseTree result = callDynamic(d,p); - result.name = "discard!(" ~ getName(d) ~ ")"; - //result.begin = result.end; - result.children = null; - if (result.successful) - result.matches = null;//to keep error messages, if any - - return result; - }; -} + static ParseTree.Dynamic discard(D)(D d) + { + return (ParseTree p) + { + ParseTree result = callDynamic(d,p); + result.name = "discard!(" ~ getName(d) ~ ")"; + //result.begin = result.end; + result.children = null; + if (result.successful) + result.matches = null;//to keep error messages, if any + + return result; + }; + } -Dynamic drop(D)(D d) -{ - return (ParseTree p) - { - ParseTree result = callDynamic(d,p); - result.children = null; - if (result.successful) - result.name = "drop!(" ~ getName(d) ~ ")"; - return result; - }; -} + ParseTree.Dynamic drop(D)(D d) + { + return (ParseTree p) + { + ParseTree result = callDynamic(d,p); + result.children = null; + if (result.successful) + result.name = "drop!(" ~ getName(d) ~ ")"; + return result; + }; + } -Dynamic propagate(D)(D d) -{ - return (ParseTree p) - { - ParseTree result = callDynamic(d,p); - if (result.successful) - result.name = "propagate!(" ~ getName(d) ~ ")"; - return result; - }; -} + ParseTree.Dynamic propagate(D)(D d) + { + return (ParseTree p) + { + ParseTree result = callDynamic(d,p); + if (result.successful) + result.name = "propagate!(" ~ getName(d) ~ ")"; + return result; + }; + } -Dynamic keep(D)(D d) -{ - return (ParseTree p) - { - ParseTree result = callDynamic(d,p); - if (result.successful) + ParseTree.Dynamic keep(D)(D d) { - result.children = [result]; - result.name = "keep!(" ~ getName(d) ~ ")"; + return (ParseTree p) + { + ParseTree result = callDynamic(d,p); + if (result.successful) + { + result.children = [result]; + result.name = "keep!(" ~ getName(d) ~ ")"; + } + return result; + }; } - return result; - }; + } } diff --git a/pegged/grammar.d b/pegged/grammar.d index 67acc820..6e345912 100644 --- a/pegged/grammar.d +++ b/pegged/grammar.d @@ -1,8 +1,8 @@ /** -Parser generation module for Pegged. -The Pegged parser itself is in pegged.parser, generated from pegged.examples.peggedgrammar. + Parser generation module for Pegged. + The Pegged parser itself is in pegged.parser, generated from pegged.examples.peggedgrammar. -The documentation is in the /docs directory. + The documentation is in the /docs directory. */ module pegged.grammar; @@ -13,19 +13,26 @@ import std.stdio; public import pegged.peg; import pegged.parser; +package import pegged.defaultparsetree : DefaultParseTree; +package import pegged.parsetree : isParseTree; +struct GrammarOptions { + string parsetreeName; +} + +enum defaultGrammarOptions = GrammarOptions(DefaultParseTree.stringof); /** -Option enum to get internal memoization (parse results storing). + Option enum to get internal memoization (parse results storing). */ enum Memoization { no, yes } /** -This function takes a (future) module name, a (future) file name and a grammar as a string or a file. -It writes the corresponding parser inside a module with the given name. + This function takes a (future) module name, a (future) file name and a grammar as a string or a file. + It writes the corresponding parser inside a module with the given name. */ -void asModule(Memoization withMemo = Memoization.yes)(string moduleName, string fileName, string grammarString, string optHeader = "") +void asModule(Memoization withMemo = Memoization.yes, ParseTree=DefaultParseTree)(string moduleName, string fileName, string grammarString, string optHeader = "", immutable GrammarOptions optGrammar=defaultGrammarOptions) if (isParseTree!ParseTree) { import std.stdio; auto f = File(fileName ~ ".d","w"); @@ -39,64 +46,73 @@ void asModule(Memoization withMemo = Memoization.yes)(string moduleName, string if (optHeader.length > 0) f.write(optHeader ~ "\n\n"); + static if (is(ParseTree == DefaultParseTree)) { + f.writeln("public import pegged.defaultparsetree;"); + } + else { + f.writefln("import pegged.parsetree : isParseTree;"); + f.writefln(`static assert(is(%s), "ParseTree %s must be defined");`, ParseTree.stringof, ParseTree.stringof); + f.writefln(`static assert(isParseTree!(%s), "%s must compile with isParseTree");`, ParseTree.stringof, ParseTree.stringof); + } f.write("public import pegged.peg;\n"); f.write("import std.algorithm: startsWith;\n"); f.write("import std.functional: toDelegate;\n\n"); - f.write(grammar!(withMemo)(grammarString)); + f.write(grammar!(withMemo)(grammarString, optGrammar)); } /// ditto -void asModule(Memoization withMemo = Memoization.yes)(string moduleName, File file, string optHeader = "") +void asModule(Memoization withMemo = Memoization.yes)(string moduleName, File file, string optHeader = "", immutable GrammarOptions optGrammar=defaultGrammarOptions) { string grammarDefinition; foreach(line; file.byLine) { grammarDefinition ~= line ~ '\n'; } - asModule!(withMemo)(moduleName, grammarDefinition, optHeader); + asModule!(withMemo)(moduleName, grammarDefinition, optHeader, optGrammar); } // Helper to insert 'Spacing' before and after Primaries -ParseTree spaceArrow(ParseTree input) +ParseTree spaceArrow(ParseTree)(ParseTree input) { ParseTree wrapInSpaces(ParseTree p) { ParseTree spacer = - ParseTree("Pegged.Prefix", true, null, null, 0,0, [ - ParseTree("Pegged.Suffix", true, null, null, 0, 0, [ - ParseTree("Pegged.Primary", true, null, null, 0, 0, [ - ParseTree("Pegged.RhsName", true, null, null, 0,0, [ - ParseTree("Pegged.Identifier", true, ["Spacing"]) - ]) - ]) - ]) - ]); + ParseTree("Pegged.Prefix", true, null, null, 0,0, [ + ParseTree("Pegged.Suffix", true, null, null, 0, 0, [ + ParseTree("Pegged.Primary", true, null, null, 0, 0, [ + ParseTree("Pegged.RhsName", true, null, null, 0,0, [ + ParseTree("Pegged.Identifier", true, ["Spacing"]) + ]) + ]) + ]) + ]); ParseTree result = ParseTree("Pegged.WrapAround", true, p.matches, p.input, p.begin, p.end, p.children); result.children = spacer ~ result.children ~ spacer; return result; } - return modify!( p => p.name == "Pegged.Primary", - wrapInSpaces)(input); + return modify!(ParseTree, p => p.name == "Pegged.Primary", + wrapInSpaces)(input); } /** -Generate a parser from a PEG definition. -The parser is a string containing D code, to be mixed in or written in a file. - ----- -enum string def = " -Gram: - A <- 'a' B* - B <- 'b' / 'c' -"; + Generate a parser from a PEG definition. + The parser is a string containing D code, to be mixed in or written in a file. -mixin(grammar(def)); + ---- + enum string def = " + Gram: + A <- 'a' B* + B <- 'b' / 'c' + "; -ParseTree p = Gram("abcbccbcd"); ----- + mixin(grammar(def)); + + ParseTree p = Gram("abcbccbcd"); + ---- */ -string grammar(Memoization withMemo = Memoization.yes)(string definition) +string grammar(Memoization withMemo = Memoization.yes, ParseTree=DefaultParseTree)(string definition, + GrammarOptions optGrammar=defaultGrammarOptions) if (isParseTree!ParseTree) { ParseTree defAsParseTree = Pegged(definition); @@ -106,10 +122,11 @@ string grammar(Memoization withMemo = Memoization.yes)(string definition) string result = "static assert(false, `" ~ defAsParseTree.toString("") ~ "`);"; return result; } - return grammar!(withMemo)(defAsParseTree); + return grammar!(ParseTree, withMemo)(defAsParseTree, optGrammar); } /// ditto -string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) +string grammar(ParseTree, Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree, + GrammarOptions optGrammar=defaultGrammarOptions) if (isParseTree!ParseTree) { string[] composedGrammars; @@ -122,14 +139,14 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) // rules for which memoization needs to be blocked. /* - I once considered that if two left-recursive cycles intersect, unbounded left-recursion - would be prevented in both cycles if only the intersection rule would be a stopper. Although - true, it causes other problems, as documented in the "Mutual left-recursion" unittest below. - Therefore, we simply make the first rule in every left-recursive cycle a stopper. - Also, one might think that it suffices to prevent ordinary memoization in just the rules - that are part of the cycle. However, some larger input files for pegged/examples/extended_pascal - would fail to parse. So memoization for all left-recursive rules is disabled during - left-recursion. + I once considered that if two left-recursive cycles intersect, unbounded left-recursion + would be prevented in both cycles if only the intersection rule would be a stopper. Although + true, it causes other problems, as documented in the "Mutual left-recursion" unittest below. + Therefore, we simply make the first rule in every left-recursive cycle a stopper. + Also, one might think that it suffices to prevent ordinary memoization in just the rules + that are part of the cycle. However, some larger input files for pegged/examples/extended_pascal + would fail to parse. So memoization for all left-recursive rules is disabled during + left-recursion. */ string[] allLeftRecursiveRules; foreach (cycle; grammarInfo.leftRecursiveCycles) @@ -163,7 +180,7 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) result ~= stopper ~ ": " ~ allLeftRecursiveRules.join(", ") ~ "\n"; return result.length > 0 ? "/** Rules that stop left-recursive cycles, followed by rules for which\n" - ~ " * memoization is blocked during recursion:\n" ~ result ~ "*/\n\n" : ""; + ~ " * memoization is blocked during recursion:\n" ~ result ~ "*/\n\n" : ""; } // Analysis completed. @@ -194,60 +211,72 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) switch (p.name) { - case "Pegged": - result = generateCode(p.children[0]); - break; - case "Pegged.Grammar": - string grammarName = generateCode(p.children[0]); - string shortGrammarName = p.children[0].matches[0]; - //string invokedGrammarName = generateCode(transformName(p.children[0])); - string firstRuleName = generateCode(p.children[1].children[0]); - - result = -"struct Generic" ~ shortGrammarName ~ "(TParseTree) + case "Pegged": + result = generateCode(p.children[0]); + break; + case "Pegged.Grammar": + string grammarName = generateCode(p.children[0]); + string shortGrammarName = p.children[0].matches[0]; + //string invokedGrammarName = generateCode(transformName(p.children[0])); + string firstRuleName = generateCode(p.children[1].children[0]); + + if (optGrammar.parsetreeName == DefaultParseTree.stringof) { + + result = "import pegged.defaultparsetree;\n"; + } + result ~= + "@safe struct Generic" ~ shortGrammarName ~ "(ParseTree) { +// static if (is(ParseTree == DefaultParseTree)) { + alias PEG=ParseTree; +// } + import std.functional : toDelegate; import pegged.dynamic.grammar; static import pegged.peg; - struct " ~ grammarName ~ "\n { - enum name = \"" ~ shortGrammarName ~ "\"; - static ParseTree delegate(ParseTree)[string] before; - static ParseTree delegate(ParseTree)[string] after; - static ParseTree delegate(ParseTree)[string] rules;"; + mixin DefaultPatters!ParseTree; + //alias PEG=PeggedT!ParseTree; - if (withMemo == Memoization.yes) { + @safe struct " ~ grammarName ~ "\n { + enum name = \"" ~ shortGrammarName ~ "\"; + static ParseTree.Dynamic[string] before; + static ParseTree.Dynamic[string] after; + static ParseTree.Dynamic[string] rules;"; + + if (withMemo == Memoization.yes) { + result ~= " + import std.typecons:Tuple, tuple; + static ParseTree[Tuple!(string, size_t)] memo;"; + if (grammarInfo.leftRecursiveCycles.length > 0) result ~= " - import std.typecons:Tuple, tuple; - static TParseTree[Tuple!(string, size_t)] memo;"; - if (grammarInfo.leftRecursiveCycles.length > 0) - result ~= " import std.algorithm: canFind, countUntil, remove; static size_t[] blockMemoAtPos;"; - } + } - result ~= " - static this()\n {\n"; + result ~= " + static this() @trusted\n {\n"; - ParseTree[] definitions = p.children[1 .. $]; - bool userDefinedSpacing; - foreach(i,def; definitions) + ParseTree[] definitions = p.children[1 .. $]; + bool userDefinedSpacing; + foreach(i,def; definitions) + { + if (def.children[0].children.length == 1) // Non-parameterized ruleName + result ~= " rules[\"" ~ def.matches[0] ~ "\"] = toDelegate(&" ~ def.matches[0] ~ ");\n"; + if (def.matches[0] == "Spacing") // user-defined spacing { - if (def.children[0].children.length == 1) // Non-parameterized ruleName - result ~= " rules[\"" ~ def.matches[0] ~ "\"] = toDelegate(&" ~ def.matches[0] ~ ");\n"; - if (def.matches[0] == "Spacing") // user-defined spacing - { - userDefinedSpacing = true; - break; - } + userDefinedSpacing = true; + break; } - if(!userDefinedSpacing) - result ~= " rules[\"Spacing\"] = toDelegate(&Spacing);\n"; + } + if(!userDefinedSpacing) + result ~= " rules[\"Spacing\"] = toDelegate(&Spacing);\n"; - result ~= -" } + result ~= + " } template hooked(alias r, string name) { + @safe { static ParseTree hooked(ParseTree p) { ParseTree result; @@ -271,12 +300,13 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) { return hooked!(r, name)(ParseTree(\"\",false,[],input)); } + } } static void addRuleBefore(string parentRule, string ruleSyntax) { // enum name is the current grammar name - DynamicGrammar dg = pegged.dynamic.grammar.grammar(name ~ \": \" ~ ruleSyntax, rules); + auto dg = pegged.dynamic.grammar.grammar!ParseTree(name ~ \": \" ~ ruleSyntax, rules); foreach(ruleName,rule; dg.rules) if (ruleName != \"Spacing\") // Keep the local Spacing rule, do not overwrite it rules[ruleName] = rule; @@ -286,7 +316,7 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) static void addRuleAfter(string parentRule, string ruleSyntax) { // enum name is the current grammar named - DynamicGrammar dg = pegged.dynamic.grammar.grammar(name ~ \": \" ~ ruleSyntax, rules); + auto dg = pegged.dynamic.grammar.grammar!ParseTree(name ~ \": \" ~ ruleSyntax, rules); foreach(ruleName,rule; dg.rules) { if (ruleName != \"Spacing\") @@ -303,181 +333,181 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) "; - /+ - ~ " switch(s)\n" - ~ " {\n"; - - bool[string] ruleNames; // to avoid duplicates, when using parameterized rules - string parameterizedRulesSpecialCode; // because param rules need to be put in the 'default' part of the switch - - string paramRuleHandler(string target) - { - return "if (s.length >= "~to!string(shortGrammarName.length + target.length + 3) - ~" && s[0.."~to!string(shortGrammarName.length + target.length + 3)~"] == \"" - ~shortGrammarName ~ "." ~ target~"!(\") return true;"; - } - - foreach(i,def; definitions) - { - /* - if (def.matches[0] !in ruleNames) - { - ruleNames[def.matches[0]] = true; - - if (def.children[0].children.length > 1) // Parameterized rule - parameterizedRulesSpecialCode ~= " " ~ paramRuleHandler(def.matches[0])~ "\n"; - else - result ~= " case \"" ~ shortGrammarName ~ "." ~ def.matches[0] ~ "\":\n"; - } - */ - if (def.matches[0] == "Spacing") // user-defined spacing - { - userDefinedSpacing = true; - break; - } - } - result ~= " return true;\n" - ~ " default:\n" - ~ parameterizedRulesSpecialCode - ~ " return false;\n }\n }\n"; - +/ - result ~= " mixin decimateTree;\n\n"; - - // If the grammar provides a Spacing rule, then this will be used. - // else, the predefined 'spacing' rule is used. - result ~= userDefinedSpacing ? "" : " alias spacing Spacing;\n\n"; - - // Creating the inner functions, each corresponding to a grammar rule - foreach(def; definitions) - result ~= generateCode(def, shortGrammarName); - - // if the first rule is parameterized (a template), it's impossible to get an opCall - // because we don't know with which template arguments it should be called. - // So no opCall is generated in this case. - if (p.children[1].children[0].children.length == 1) - { - // General calling interface - result ~= " static TParseTree opCall(TParseTree p)\n" - ~ " {\n" - ~ " TParseTree result = decimateTree(" ~ firstRuleName ~ "(p));\n" - ~ " result.children = [result];\n" - ~ " result.name = \"" ~ shortGrammarName ~ "\";\n" - ~ " return result;\n" - ~ " }\n\n" - ~ " static TParseTree opCall(string input)\n" - ~ " {\n"; + /+ + ~ " switch(s)\n" + ~ " {\n"; + + bool[string] ruleNames; // to avoid duplicates, when using parameterized rules + string parameterizedRulesSpecialCode; // because param rules need to be put in the 'default' part of the switch + + string paramRuleHandler(string target) + { + return "if (s.length >= "~to!string(shortGrammarName.length + target.length + 3) + ~" && s[0.."~to!string(shortGrammarName.length + target.length + 3)~"] == \"" + ~shortGrammarName ~ "." ~ target~"!(\") return true;"; + } + + foreach(i,def; definitions) + { + /* + if (def.matches[0] !in ruleNames) + { + ruleNames[def.matches[0]] = true; + + if (def.children[0].children.length > 1) // Parameterized rule + parameterizedRulesSpecialCode ~= " " ~ paramRuleHandler(def.matches[0])~ "\n"; + else + result ~= " case \"" ~ shortGrammarName ~ "." ~ def.matches[0] ~ "\":\n"; + } + */ + if (def.matches[0] == "Spacing") // user-defined spacing + { + userDefinedSpacing = true; + break; + } + } + result ~= " return true;\n" + ~ " default:\n" + ~ parameterizedRulesSpecialCode + ~ " return false;\n }\n }\n"; + +/ + result ~= " mixin decimateTree!ParseTree;\n\n"; + + // If the grammar provides a Spacing rule, then this will be used. + // else, the predefined 'spacing' rule is used. + result ~= userDefinedSpacing ? "" : " alias spacing Spacing;\n\n"; + + // Creating the inner functions, each corresponding to a grammar rule + foreach(def; definitions) + result ~= generateCode(def, shortGrammarName); + + // if the first rule is parameterized (a template), it's impossible to get an opCall + // because we don't know with which template arguments it should be called. + // So no opCall is generated in this case. + if (p.children[1].children[0].children.length == 1) + { + // General calling interface + result ~= " static ParseTree opCall(ParseTree p)\n" + ~ " {\n" + ~ " ParseTree result = decimateTree(" ~ firstRuleName ~ "(p));\n" + ~ " result.children = [result];\n" + ~ " result.name = \"" ~ shortGrammarName ~ "\";\n" + ~ " return result;\n" + ~ " }\n\n" + ~ " static ParseTree opCall(string input)\n" + ~ " {\n"; - if (withMemo == Memoization.no) - result ~= " forgetMemo();\n" - ~ " return " ~ shortGrammarName ~ "(TParseTree(``, false, [], input, 0, 0));\n" - ~ " }\n"; - else - result ~= " if(__ctfe)\n" - ~ " {\n" - ~ " return " ~ shortGrammarName ~ "(TParseTree(``, false, [], input, 0, 0));\n" - ~ " }\n" - ~ " else\n" - ~ " {\n" - ~ " forgetMemo();\n" - ~ " return " ~ shortGrammarName ~ "(TParseTree(``, false, [], input, 0, 0));\n" - ~ " }\n" - ~ " }\n"; - - result ~= " static string opCall(GetName g)\n" - ~ " {\n" - ~ " return \"" ~ shortGrammarName ~ "\";\n" - ~ " }\n\n"; - } - result ~= generateForgetMemo(); - result ~= " }\n" // end of grammar struct definition - ~ "}\n\n" // end of template definition - ~ "alias Generic" ~ shortGrammarName ~ "!(ParseTree)." - ~ shortGrammarName ~ " " ~ shortGrammarName ~ ";\n\n"; + if (withMemo == Memoization.no) + result ~= " forgetMemo();\n" + ~ " return " ~ shortGrammarName ~ "(ParseTree(``, false, [], input, 0, 0));\n" + ~ " }\n"; + else + result ~= " if(__ctfe)\n" + ~ " {\n" + ~ " return " ~ shortGrammarName ~ "(ParseTree(``, false, [], input, 0, 0));\n" + ~ " }\n" + ~ " else\n" + ~ " {\n" + ~ " forgetMemo();\n" + ~ " return " ~ shortGrammarName ~ "(ParseTree(``, false, [], input, 0, 0));\n" + ~ " }\n" + ~ " }\n"; + + result ~= " static string opCall(GetName g)\n" + ~ " {\n" + ~ " return \"" ~ shortGrammarName ~ "\";\n" + ~ " }\n\n"; + } + result ~= generateForgetMemo(); + result ~= " }\n" // end of grammar struct definition + ~ "}\n\n" // end of template definition + ~ "alias Generic" ~ shortGrammarName ~ "!(" ~ optGrammar.parsetreeName ~ ")." + ~ shortGrammarName ~ " " ~ shortGrammarName ~ ";\n\n"; + break; + case "Pegged.Definition": + // children[0]: name + // children[1]: arrow (arrow type as first child) + // children[2]: description + + string code; + + switch(p.children[1].children[0].name) + { + case "Pegged.LEFTARROW": + code ~= generateCode(p.children[2]); break; - case "Pegged.Definition": - // children[0]: name - // children[1]: arrow (arrow type as first child) - // children[2]: description - - string code; - - switch(p.children[1].children[0].name) - { - case "Pegged.LEFTARROW": - code ~= generateCode(p.children[2]); - break; - case "Pegged.FUSEARROW": - code ~= "pegged.peg.fuse!(" ~ generateCode(p.children[2]) ~ ")"; - break; - case "Pegged.DISCARDARROW": - code ~= "pegged.peg.discard!(" ~ generateCode(p.children[2]) ~ ")"; - break; - case "Pegged.KEEPARROW": - code ~= "pegged.peg.keep!("~ generateCode(p.children[2]) ~ ")"; - break; - case "Pegged.DROPARROW": - code ~= "pegged.peg.drop!("~ generateCode(p.children[2]) ~ ")"; - break; - case "Pegged.PROPAGATEARROW": - code ~= "pegged.peg.propagate!("~ generateCode(p.children[2]) ~ ")"; - break; - case "Pegged.SPACEARROW": - ParseTree modified = spaceArrow(p.children[2]); - code ~= generateCode(modified); - break; - case "Pegged.ACTIONARROW": - auto actionResult = generateCode(p.children[2]); - foreach(action; p.children[1].matches[1..$]) - actionResult = "pegged.peg.action!(" ~ actionResult ~ ", " ~ action ~ ")"; - code ~= actionResult; - break; - default: - break; - } + case "Pegged.FUSEARROW": + code ~= "PEG.fuse!(" ~ generateCode(p.children[2]) ~ ")"; + break; + case "Pegged.DISCARDARROW": + code ~= "PEG.discard!(" ~ generateCode(p.children[2]) ~ ")"; + break; + case "Pegged.KEEPARROW": + code ~= "PEG.keep!("~ generateCode(p.children[2]) ~ ")"; + break; + case "Pegged.DROPARROW": + code ~= "PEG.drop!("~ generateCode(p.children[2]) ~ ")"; + break; + case "Pegged.PROPAGATEARROW": + code ~= "PEG.propagate!("~ generateCode(p.children[2]) ~ ")"; + break; + case "Pegged.SPACEARROW": + ParseTree modified = spaceArrow(p.children[2]); + code ~= generateCode(modified); + break; + case "Pegged.ACTIONARROW": + auto actionResult = generateCode(p.children[2]); + foreach(action; p.children[1].matches[1..$]) + actionResult = "PEG.action!(" ~ actionResult ~ ", " ~ action ~ ")"; + code ~= actionResult; + break; + default: + break; + } - bool parameterizedRule = p.children[0].children.length > 1; - string completeName = generateCode(p.children[0]); - string shortName = p.matches[0]; - string innerName; - string hookedName = p.matches[0]; + bool parameterizedRule = p.children[0].children.length > 1; + string completeName = generateCode(p.children[0]); + string shortName = p.matches[0]; + string innerName; + string hookedName = p.matches[0]; - if (parameterizedRule) - { - result = " template " ~ completeName ~ "\n" - ~ " {\n"; - innerName ~= "\"" ~ shortName ~ "!(\" ~ "; - hookedName ~= "_" ~ to!string(p.children[0].children[1].children.length); - foreach(i,param; p.children[0].children[1].children) - innerName ~= "pegged.peg.getName!("~ param.children[0].matches[0] - ~ (i 1) // real sequence { - result = "pegged.peg.and!("; + result = "PEG.and!("; foreach(seq; p.children) { string elementCode = generateCode(seq); // flattening inner sequences - if (elementCode.length > 6 && elementCode[0..5] == "pegged.peg.and!(") + if (elementCode.length > 6 && elementCode[0..5] == "PEG.and!(") elementCode = elementCode[5..$-1]; // cutting 'and!(' and ')' result ~= elementCode ~ ", "; } @@ -709,17 +739,17 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) switch (child.name) { case "Pegged.OPTION": - result = "pegged.peg.option!(" ~ result ~ ")"; + result = "PEG.option!(" ~ result ~ ")"; break; case "Pegged.ZEROORMORE": - result = "pegged.peg.zeroOrMore!(" ~ result ~ ")"; + result = "PEG.zeroOrMore!(" ~ result ~ ")"; break; case "Pegged.ONEORMORE": - result = "pegged.peg.oneOrMore!(" ~ result ~ ")"; + result = "PEG.oneOrMore!(" ~ result ~ ")"; break; case "Pegged.Action": foreach(action; child.matches) - result = "pegged.peg.action!(" ~ result ~ ", " ~ action ~ ")"; + result = "PEG.action!(" ~ result ~ ", " ~ action ~ ")"; break; default: break; @@ -755,20 +785,20 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) break; case "Pegged.Literal": if(p.matches.length == 3) // standard case - result = "pegged.peg.literal!(\"" ~ p.matches[1] ~ "\")"; + result = "PEG.literal!(\"" ~ p.matches[1] ~ "\")"; else // only two children -> empty literal - result = "pegged.peg.literal!(``)"; + result = "PEG.literal!(``)"; break; case "Pegged.CILiteral": if(p.matches.length == 3) // standard case - result = "pegged.peg.caseInsensitiveLiteral!(\"" ~ p.matches[1] ~ "\")"; + result = "PEG.caseInsensitiveLiteral!(\"" ~ p.matches[1] ~ "\")"; else // only two children -> empty literal - result = "pegged.peg.caseInsensitiveLiteral!(``)"; + result = "PEG.caseInsensitiveLiteral!(``)"; break; case "Pegged.CharClass": if (p.children.length > 1) { - result = "pegged.peg.or!("; + result = "PEG.or!("; foreach(seq; p.children) result ~= generateCode(seq) ~ ", "; result = result[0..$-2] ~ ")"; @@ -782,14 +812,14 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) /// Make the generation at the Char level: directly what is needed, be it `` or "" or whatever if (p.children.length > 1) // a-b range { - result = "pegged.peg.charRange!('" ~ generateCode(p.children[0]) + result = "PEG.charRange!('" ~ generateCode(p.children[0]) ~ "', '" ~ generateCode(p.children[1]) ~ "')"; } else // lone char { - result = "pegged.peg.literal!("; + result = "PEG.literal!("; string ch = p.matches[0]; switch (ch) { @@ -810,7 +840,7 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) break; case "\"": case "\\\"": - result ~= "`\"`)"; + result ~= q{`"`)}; break; case "\n": case "\r": @@ -846,48 +876,48 @@ string grammar(Memoization withMemo = Memoization.yes)(ParseTree defAsParseTree) } break; case "Pegged.POS": - result = "pegged.peg.posLookahead!("; + result = "PEG.posLookahead!("; break; case "Pegged.NEG": - result = "pegged.peg.negLookahead!("; + result = "PEG.negLookahead!("; break; case "Pegged.FUSE": - result = "pegged.peg.fuse!("; + result = "PEG.fuse!("; break; case "Pegged.DISCARD": - result = "pegged.peg.discard!("; + result = "PEG.discard!("; break; //case "Pegged.CUT": // result = "discardChildren!("; // break; case "Pegged.KEEP": - result = "pegged.peg.keep!("; + result = "PEG.keep!("; break; case "Pegged.DROP": - result = "pegged.peg.drop!("; + result = "PEG.drop!("; break; case "Pegged.PROPAGATE": - result = "pegged.peg.propagate!("; + result = "PEG.propagate!("; break; case "Pegged.OPTION": - result = "pegged.peg.option!("; + result = "PEG.option!("; break; case "Pegged.ZEROORMORE": - result = "pegged.peg.zeroOrMore!("; + result = "PEG.zeroOrMore!("; break; case "Pegged.ONEORMORE": - result = "pegged.peg.oneOrMore!("; + result = "PEG.oneOrMore!("; break; case "Pegged.Action": result = generateCode(p.children[0]); foreach(action; p.matches[1..$]) - result = "pegged.peg.action!(" ~ result ~ ", " ~ action ~ ")"; + result = "PEG.action!(" ~ result ~ ", " ~ action ~ ")"; break; case "Pegged.ANY": - result = "pegged.peg.any"; + result = "PEG.any"; break; case "Pegged.WrapAround": - result = "pegged.peg.wrapAround!(" ~ generateCode(p.children[0]) ~ ", " + result = "PEG.wrapAround!(" ~ generateCode(p.children[0]) ~ ", " ~ generateCode(p.children[1]) ~ ", " ~ generateCode(p.children[2]) ~ ")"; break; @@ -910,10 +940,10 @@ Not used by Pegged yet. mixin template expected() { string expected(ParseTree p) - { - - switch(p.name) { + + switch(p.name) + { case "Pegged.Expression": string expectation; foreach(i, child; p.children) @@ -974,9 +1004,17 @@ mixin template expected() return "unknow rule (" ~ p.matches[0] ~ ")"; } } + } -unittest // 'grammar' unit test: low-level functionalities + + +version(unittest) { + private alias ParseTree = DefaultParseTree; + private import PEG=pegged.parsetree; +} + +@safe unittest // 'grammar' unit test: low-level functionalities { mixin(grammar(` Test1: @@ -996,11 +1034,10 @@ unittest // 'grammar' unit test: low-level functionalities assert(__traits(hasMember, Test1, "isRule"), "Test1 has a member named isRule."); } -unittest // 'grammar' unit test: PEG syntax +@safe unittest // 'grammar' unit test: PEG syntax { - // Here we do not test pegged.peg.*, just the grammar transformations + // Here we do not test PEG.*, just the grammar transformations // From a PEG to a Pegged expression template. - mixin(grammar(` Terminals: Literal1 <- "abc" @@ -1021,6 +1058,7 @@ unittest // 'grammar' unit test: PEG syntax Chars4 <- [\U00000000-\U000000FF] `)); + mixin DefaultPatters!ParseTree; ParseTree result = Terminals("abc"); assert(result.name == "Terminals", "Grammar name test."); @@ -1325,7 +1363,7 @@ unittest // 'grammar' unit test: PEG syntax assert(CaseSensitive("abci").successful); } -unittest // Multilines rules +@safe unittest // Multilines rules { mixin(grammar(` Indentation: @@ -1340,13 +1378,13 @@ Rule3 < 'e' Rule4 <- 'f' Rule5 # Rule4 ends with 'f', then it's Rule5 -<- 'g' + <- 'g' - 'h' -`)); + 'h' + `)); assert(Indentation("abc").successful); @@ -1356,13 +1394,15 @@ Rule4 <- 'f' Rule5 # Rule4 ends with 'f', then it's Rule5 assert(Indentation.Rule5("gh").successful); } -unittest // Parsing at compile-time +@safe unittest // Parsing at compile-time { + alias ParseTree = DefaultParseTree; + mixin(grammar(` - Test: - Rule1 <- 'a' Rule2('b') - Rule2(B) <- B - `)); + Test: + Rule1 <- 'a' Rule2('b') + Rule2(B) <- B + `)); // Equality on success ParseTree result = Test("ab"); @@ -1378,26 +1418,28 @@ unittest // Parsing at compile-time assert(CTfailure == result, "Compile-time parsing is equal to runtime parsing on failure."); } -unittest // PEG extensions (arrows, prefixes, suffixes) +@safe unittest // PEG extensions (arrows, prefixes, suffixes) { + alias ParseTree = DefaultParseTree; + mixin(grammar(` - Arrows: - Rule1 <- ABC DEF # Standard arrow - Rule2 < ABC DEF # Space arrow - Rule3 < ABC DEF* # Space arrow - Rule4 < ABC+ DEF # Space arrow - - Rule5 <- ABC* - Rule6 <~ ABC* # Fuse arrow - - Rule7 <: ABC DEF # Discard arrow - Rule8 <^ ABC DEF # Keep arrow - Rule9 <; ABC DEF # Drop arrow - Rule10 <% ABC Rule1 DEF # Propagate arrow - - ABC <- "abc" - DEF <- "def" - `)); + Arrows: + Rule1 <- ABC DEF # Standard arrow + Rule2 < ABC DEF # Space arrow + Rule3 < ABC DEF* # Space arrow + Rule4 < ABC+ DEF # Space arrow + + Rule5 <- ABC* + Rule6 <~ ABC* # Fuse arrow + + Rule7 <: ABC DEF # Discard arrow + Rule8 <^ ABC DEF # Keep arrow + Rule9 <; ABC DEF # Drop arrow + Rule10 <% ABC Rule1 DEF # Propagate arrow + + ABC <- "abc" + DEF <- "def" + `)); // Comparing <- ABC DEF and < ABC DEF ParseTree result = Arrows.decimateTree(Arrows.Rule1("abcdef")); @@ -1528,15 +1570,15 @@ unittest // PEG extensions (arrows, prefixes, suffixes) assert(result.children[2].name == "Arrows.DEF"); } -unittest //More space arrow tests +@safe unittest //More space arrow tests { mixin(grammar(` - Spaces: - Rule1 < A (B C)+ - A <- 'a' - B <- 'b' - C <- 'c' - `)); + Spaces: + Rule1 < A (B C)+ + A <- 'a' + B <- 'b' + C <- 'c' + `)); ParseTree result = Spaces.decimateTree(Spaces.Rule1("abcbc")); @@ -1563,44 +1605,44 @@ unittest //More space arrow tests assert(result.children[4].name == "Spaces.C"); } -unittest // Prefix and suffix tests +@safe unittest // Prefix and suffix tests { mixin(grammar(` - PrefixSuffix: - # Reference - Rule1 <- ABC DEF - Rule2 <- "abc" "def" - Rule3 <- ABC* - Rule4 <- "abc"* + PrefixSuffix: +# Reference + Rule1 <- ABC DEF + Rule2 <- "abc" "def" + Rule3 <- ABC* + Rule4 <- "abc"* - # Discard operator - Rule5 <- :ABC DEF - Rule6 <- ABC :DEF - Rule7 <- :"abc" "def" - Rule8 <- "abc" :"def" +# Discard operator + Rule5 <- :ABC DEF + Rule6 <- ABC :DEF + Rule7 <- :"abc" "def" + Rule8 <- "abc" :"def" - # Drop operator - Rule9 <- ;ABC DEF - Rule10 <- ABC ;DEF - Rule11 <- ;"abc" "def" - Rule12 <- "abc" ;"def" +# Drop operator + Rule9 <- ;ABC DEF + Rule10 <- ABC ;DEF + Rule11 <- ;"abc" "def" + Rule12 <- "abc" ;"def" - # Fuse operator +# Fuse operator - Rule13 <- ~( ABC* ) - Rule14 <- ~("abc"*) + Rule13 <- ~( ABC* ) + Rule14 <- ~("abc"*) - # Keep operator - Rule15 <- ^"abc" ^"def" +# Keep operator + Rule15 <- ^"abc" ^"def" - # Propagate operator - Rule16 <- ABC Rule1 DEF - Rule17 <- ABC %Rule1 DEF +# Propagate operator + Rule16 <- ABC Rule1 DEF + Rule17 <- ABC %Rule1 DEF - ABC <- "abc" - DEF <- "def" - `)); + ABC <- "abc" + DEF <- "def" + `)); // Comparing standard and discarded rules @@ -1775,17 +1817,17 @@ unittest // Prefix and suffix tests // Testing % and < together mixin(grammar(` - PropTest: - Rule1 < B C+ - Rule2 <- B (%C)+ - Rule3 < B (%C)+ - Rule4 < B %(D E)+ - - B <- 'b' - C <- D E - D <- 'd' - E <- 'e' - `)); + PropTest: + Rule1 < B C+ + Rule2 <- B (%C)+ + Rule3 < B (%C)+ + Rule4 < B %(D E)+ + + B <- 'b' + C <- D E + D <- 'd' + E <- 'e' + `)); result = PropTest.decimateTree(PropTest.Rule1("bdedede")); assert(result.successful); @@ -1870,20 +1912,20 @@ unittest // Prefix and suffix tests // More than one prefix, more than one suffixes mixin(grammar(` - MoreThanOne: - Rule1 <- ~:("abc"*) # Two prefixes (nothing left for ~, after :) - Rule2 <- :~("abc"*) # Two prefixes (: will discard everything ~ did) - Rule3 <- ;:~"abc" # Many prefixes - Rule4 <- ~~~("abc"*) # Many fuses (no global effect) + MoreThanOne: + Rule1 <- ~:("abc"*) # Two prefixes (nothing left for ~, after :) + Rule2 <- :~("abc"*) # Two prefixes (: will discard everything ~ did) + Rule3 <- ;:~"abc" # Many prefixes + Rule4 <- ~~~("abc"*) # Many fuses (no global effect) - Rule5 <- "abc"+* # Many suffixes - Rule6 <- "abc"+? # Many suffixes + Rule5 <- "abc"+* # Many suffixes + Rule6 <- "abc"+? # Many suffixes - Rule7 <- !!"abc" # Double negation, equivalent to '&' - Rule8 <- &"abc" + Rule7 <- !!"abc" # Double negation, equivalent to '&' + Rule8 <- &"abc" - Rule9 <- ^^"abc"+* # Many suffixes and prefixes - `)); + Rule9 <- ^^"abc"+* # Many suffixes and prefixes + `)); assert(is(MoreThanOne), "This compiles all right."); @@ -1964,15 +2006,16 @@ unittest // Prefix and suffix tests assert(result.children[0].children[0].children[0].children[2].name == `literal!("abc")`); } -unittest // Issue #88 unit test +@safe unittest // Issue #88 unit test { + alias ParseTree = DefaultParseTree; enum gram = ` - P: + P: Rule1 <- (w 'a' w)* - Rule2 <- (wx 'a' wx)* - w <- :(' ' / '\n' / '\t' / '\r')* + Rule2 <- (wx 'a' wx)* + w <- :(' ' / '\n' / '\t' / '\r')* wx <- (:' ' / '\n' / '\t' / '\r')* - `; + `; mixin(grammar(gram)); @@ -1989,14 +2032,16 @@ unittest // Issue #88 unit test assert(p2.end == input.length); } -unittest // Leading alternation +@safe unittest // Leading alternation { + alias ParseTree = DefaultParseTree; + mixin(grammar(` - LeadingAlternation: - Rule1 <- / 'a' - Rule2 <- / 'a' / 'b' - Rule3 <- (/ 'a' / 'b') - `)); + LeadingAlternation: + Rule1 <- / 'a' + Rule2 <- / 'a' / 'b' + Rule3 <- (/ 'a' / 'b') + `)); ParseTree result = LeadingAlternation.decimateTree(LeadingAlternation.Rule1("a")); assert(result.successful); @@ -2017,7 +2062,7 @@ unittest // Leading alternation assert(result.matches == ["b"]); } -unittest // Extended chars tests +@safe unittest // Extended chars tests { mixin(grammar(" Chars: @@ -2079,20 +2124,20 @@ mixin(grammar(" assert(Chars.decimateTree(Chars.Spanish("¡Hola!")).successful); } -unittest // Extended char range tests +@safe unittest // Extended char range tests { import std.conv; mixin(grammar(` - CharRanges: - Rule1 <- [a-z] - Rule2 <- [\141-\172] # a-z in octal - Rule3 <- [\x61-\x7A] # a-z in hexadecimal - Rule4 <- [\u0061-\u007A] # a-z in UTF16 - Rule5 <- [\U00000061-\U0000007A] # a-z in UTF32 - - Rule6 <- [\-\[\]\\\'\"\n\r\t] - `)); + CharRanges: + Rule1 <- [a-z] + Rule2 <- [\141-\172] # a-z in octal + Rule3 <- [\x61-\x7A] # a-z in hexadecimal + Rule4 <- [\u0061-\u007A] # a-z in UTF16 + Rule5 <- [\U00000061-\U0000007A] # a-z in UTF32 + + Rule6 <- [\-\[\]\\\'\"\n\r\t] + `)); string lower = "abcdefghijklmnopqrstuvwxyz"; string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -2124,20 +2169,20 @@ unittest // Extended char range tests } } -unittest // qualified names for rules +@safe unittest // qualified names for rules { mixin(grammar(` - First: - Rule1 <- "abc" - Rule2 <- "def" - `)); + First: + Rule1 <- "abc" + Rule2 <- "def" + `)); mixin(grammar(` - Second: - Rule1 <- First.Rule1 - Rule2 <- First.Rule2 - Rule3 <- pegged.peg.list(pegged.peg.identifier, ',') - `)); + Second: + Rule1 <- First.Rule1 + Rule2 <- First.Rule2 + Rule3 <- list(identifier, ',') + `)); // Equal on success ParseTree reference = First("abc"); @@ -2173,37 +2218,38 @@ unittest // qualified names for rules assert(result.matches == ["foo", "bar", "baz"]); } -unittest // Parameterized rules +@safe unittest // Parameterized rules { mixin(grammar(` - Parameterized: - # Different arities - Rule1(A) <- A+ - Rule1(A,B) <- (A B)+ - Rule1(A,B,C) <- (A B C)+ - - # Inner call - Call1 <- Rule1('a') - Call2 <- Rule1('a','b') - Call3 <- Rule1('a','b','c') - Call4(A) <- Rule1(A, A, A) - Call5(A) <- Rule1('a', A, 'c') - - # Default values - Rule2(A = 'a', B = 'b') <- (A B)+ - - # Re-using the parameters - Rule3(A,B) <- A B B A # Money money money! - - # The standard parameterized rule - List(Elem, Sep) < Elem (:Sep Elem)* - - # Another common PEG pattern - AllUntil(End) <~ (!End .)* :End - `)); + Parameterized: +# Different arities + Rule1(A) <- A+ + Rule1(A,B) <- (A B)+ + Rule1(A,B,C) <- (A B C)+ + +# Inner call + Call1 <- Rule1('a') + Call2 <- Rule1('a','b') + Call3 <- Rule1('a','b','c') + Call4(A) <- Rule1(A, A, A) + Call5(A) <- Rule1('a', A, 'c') + +# Default values + Rule2(A = 'a', B = 'b') <- (A B)+ + +# Re-using the parameters + Rule3(A,B) <- A B B A # Money money money! + +# The standard parameterized rule + List(Elem, Sep) < Elem (:Sep Elem)* - alias Parameterized.Rule1!(literal!"a") R1; - alias oneOrMore!(literal!"a") Ref1; +# Another common PEG pattern + AllUntil(End) <~ (!End .)* :End + `)); + + mixin DefaultPatters!ParseTree; + alias R1 = Parameterized.Rule1!(literal!"a"); + alias Ref1 = oneOrMore!(literal!"a"); ParseTree reference = Ref1("aaaa"); ParseTree result = R1("aaaa"); @@ -2224,7 +2270,7 @@ unittest // Parameterized rules assert(result.end == reference.end); alias Parameterized.Rule1!(literal!"abc") R1long; - alias oneOrMore!(literal!"abc") Ref1long; + alias Ref1long=oneOrMore!(literal!"abc"); reference = Ref1long("abcabcabcabc"); result = R1long("abcabcabcabc"); @@ -2236,8 +2282,8 @@ unittest // Parameterized rules assert(result.begin == reference.begin); assert(result.end == reference.end); - alias Parameterized.Rule1!(literal!"a", literal!"b") R2; - alias oneOrMore!(and!(literal!"a", literal!"b")) Ref2; + alias R2 = Parameterized.Rule1!(literal!"a", literal!"b"); + alias Ref2 = oneOrMore!(and!(literal!"a", literal!"b")); reference = Ref2("abababab"); result = R2("abababab"); @@ -2257,8 +2303,8 @@ unittest // Parameterized rules assert(result.begin == reference.begin); assert(result.end == reference.end); - alias Parameterized.Rule1!(literal!"a", literal!"b", literal!"c") R3; - alias oneOrMore!(and!(literal!"a", literal!"b", literal!"c")) Ref3; + alias R3 = Parameterized.Rule1!(literal!"a", literal!"b", literal!"c"); + alias Ref3 = oneOrMore!(and!(literal!"a", literal!"b", literal!"c")); reference = Ref3("abcabcabcabc"); result = R3("abcabcabcabc"); @@ -2359,11 +2405,11 @@ Here is another line. // Parameterized grammar test mixin(grammar(` - Arithmetic(Atom) : - Expr < Factor (('+'/'-') Factor)* - Factor < Primary (('*'/'/') Primary)* - Primary < '(' Expr ')' / '-' Expr / Atom - `)); + Arithmetic(Atom) : + Expr < Factor (('+'/'-') Factor)* + Factor < Primary (('*'/'/') Primary)* + Primary < '(' Expr ')' / '-' Expr / Atom + `)); alias Arithmetic!(identifier) Arith1; alias Arithmetic!(or!(identifier, digits)) Arith2; @@ -2374,6 +2420,7 @@ Here is another line. assert(!Arith1("1 + 2*3/456").successful); assert(Arith2("1 + 2*3/456").successful); assert(Arith2("1 + 2*3/z").successful); +// } } version(unittest) // Semantic actions @@ -2386,18 +2433,20 @@ version(unittest) // Semantic actions } } -unittest // Semantic actions, testing { foo } and { foo, bar, baz } +@safe unittest // Semantic actions, testing { foo } and { foo, bar, baz } { + alias ParseTree = DefaultParseTree; + mixin(grammar(` - Semantic: - Rule1 <- 'a' {doubler} - Rule2 <- 'b' {doubler, doubler} - Rule3 <- 'b' {doubler} {doubler} # Same as Rule2 - Rule4 <- 'b' {doubler, doubler, doubler} - Rule5 <- 'a' {doubler} 'b' 'c'{doubler} - Rule6 <{doubler} 'a' # Rule Level actions - Rule7 <{doubler} 'a' 'b' {doubler} # Rule Level actions - `)); + Semantic: + Rule1 <- 'a' {doubler} + Rule2 <- 'b' {doubler, doubler} + Rule3 <- 'b' {doubler} {doubler} # Same as Rule2 + Rule4 <- 'b' {doubler, doubler, doubler} + Rule5 <- 'a' {doubler} 'b' 'c'{doubler} + Rule6 <{doubler} 'a' # Rule Level actions + Rule7 <{doubler} 'a' 'b' {doubler} # Rule Level actions + `)); ParseTree result = Semantic.decimateTree(Semantic.Rule1("a")); assert(result.successful); @@ -2496,11 +2545,11 @@ unittest // failure cases: unnamed grammar, no-rule grammar, syntax errors, etc. badGrammar!"Name: Rule1 <- a'"; badGrammar!`Name: - Rule1 <- "a`; +Rule1 <- "a`; badGrammar!`Name: Rule1 <- a"`; badGrammar!`Name: - Rule1 <- 'a"`; +Rule1 <- 'a"`; badGrammar!`Name: Rule1 <- "a'`; badGrammar!"Name: @@ -2557,16 +2606,16 @@ unittest // failure cases: unnamed grammar, no-rule grammar, syntax errors, etc. badGrammar!"Name: Rule1 <- 'a' /"; // But: <- / 'a' is legal (it's equivalent to: <- 'a') - goodGrammar!"Name: +goodGrammar!"Name: Rule1 <- / 'a'"; - badGrammar!"Name: +badGrammar!"Name: Rule1 <- /"; - badGrammar!"Name: +badGrammar!"Name: Rule1 <- 'a' / / 'b'"; } +/ -unittest // Memoization testing +@safe unittest // Memoization testing { enum gram1 = ` Test1: @@ -2597,12 +2646,12 @@ unittest // Memoization testing assert(result3 == result4); //Directly comparing result1 and result3 is not possible, for the grammar names are different - assert(pegged.peg.softCompare(result1, result2)); - assert(pegged.peg.softCompare(result1, result3)); - assert(pegged.peg.softCompare(result1, result4)); + assert(softCompare(result1, result2)); + assert(softCompare(result1, result3)); + assert(softCompare(result1, result4)); } -unittest // Memoization reset in composed grammars. Issue #162 +@safe unittest // Memoization reset in composed grammars. Issue #162 { enum MathGrammar = ` Math: @@ -2622,29 +2671,29 @@ unittest // Memoization reset in composed grammars. Issue #162 // not cleared in all composed grammars. } -unittest // Test lambda syntax in semantic actions +@safe unittest // Test lambda syntax in semantic actions { import std.array; import std.string : strip; auto actions = [ - // Normal action - `{ myAction }`, + // Normal action + `{ myAction }`, - // List of normal actions - `{ myAction, myAction2 }`, + // List of normal actions + `{ myAction, myAction2 }`, - // Simple do-nothing lambda - `{ (a) {return a;} }`, + // Simple do-nothing lambda + `{ (a) {return a;} }`, - // Simple do-nothing lambda with formatting - `{ (a) { + // Simple do-nothing lambda with formatting + `{ (a) { return a; }}`, - // Lambda with commas and spurious braces to try and confuse it - `{ (a, b) { + // Lambda with commas and spurious braces to try and confuse it + `{ (a, b) { string s = "}"; if (a.successful,) { s ~= q"<}>"; @@ -2653,14 +2702,14 @@ unittest // Test lambda syntax in semantic actions } return a;} }`, - // List of mixed actions and lambdas - `{ myAction , (a) {return a;}, myAction2 , (a) { /* , } */ return a; } }`, + // List of mixed actions and lambdas + `{ myAction , (a) {return a;}, myAction2 , (a) { /* , } */ return a; } }`, - // Ambiguous lambda (not sure it would compile if used... but it should parse) - `{ myAction, a => transform(a), myAction2 }`, + // Ambiguous lambda (not sure it would compile if used... but it should parse) + `{ myAction, a => transform(a), myAction2 }`, - // Something more convoluted - "{ myAction, (a) { + // Something more convoluted + "{ myAction, (a) { /* block } comment with } braces */ string s = `} {` // wysiwyg string with braces and line comment with brace } if (s is null) { @@ -2694,26 +2743,26 @@ unittest // Test lambda syntax in semantic actions return a; }, myAction2 }", - ]; + ]; auto results = [ - [`myAction`], - [`myAction`,`myAction2`], - [`(a) {return a;}`], - [`(a) { + [`myAction`], + [`myAction`,`myAction2`], + [`(a) {return a;}`], + [`(a) { return a; }`], - [`(a, b) { + [q{(a, b) { string s = "}"; if (a.successful,) { s ~= q"<}>"; } else { { s ~= q"<}>"; /* } */ } } - return a;}`], - [`myAction`,`(a) {return a;}`,`myAction2`,`(a) { /* , } */ return a; }`], - [`myAction`,`a => transform(a)`,`myAction2`], - [`myAction`,"(a) { + return a;}}], + [`myAction`,`(a) {return a;}`,`myAction2`,`(a) { /* , } */ return a; }`], + [`myAction`,`a => transform(a)`,`myAction2`], + [`myAction`,"(a) { /* block } comment with } braces */ string s = `} {` // wysiwyg string with braces and line comment with brace } if (s is null) { @@ -2747,7 +2796,7 @@ unittest // Test lambda syntax in semantic actions return a; }",`myAction2`] - ]; + ]; foreach(idx, act; actions) { @@ -2757,21 +2806,21 @@ unittest // Test lambda syntax in semantic actions assert(p.successful); auto action = p.children[0].children[1] // Pegged.Definition - .children[2] // Pegged.Expression - .children[0] // Pegged.FirstExpression - .children[0] // Pegged.Sequence - .children[0] // Pegged.Prefix - .children[0] // Pegged.Suffix - .children[1]; // Pegged.Action + .children[2] // Pegged.Expression + .children[0] // Pegged.FirstExpression + .children[0] // Pegged.Sequence + .children[0] // Pegged.Prefix + .children[0] // Pegged.Suffix + .children[1]; // Pegged.Action assert(action.matches.length == results[idx].length); foreach(i, s; action.matches) assert(strip(s) == results[idx][i], - "\nGot |"~s~"|" ~ "\nNeeded: |"~results[idx][i]~"|"); + "\nGot |"~s~"|" ~ "\nNeeded: |"~results[idx][i]~"|"); } } -unittest +@safe unittest { // Higher-level word boundary test. mixin(grammar(` @@ -2802,8 +2851,10 @@ unittest assert(!pt.successful); } -unittest // Issue #129 unit test +@safe unittest // Issue #129 unit test { + alias ParseTree = DefaultParseTree; + enum gram = ` G: A <- B @@ -2830,7 +2881,7 @@ unittest // Issue #129 unit test assert(p.children[0].children[0].children[0].children[0].children.length == 0); } -unittest // Direct left-recursion +@safe unittest // Direct left-recursion { enum LeftGrammar = ` Left: @@ -2843,7 +2894,7 @@ unittest // Direct left-recursion assert(result.matches == ["n", "+n", "+n", "+n"]); } -unittest // Indirect left-recursion +@safe unittest // Indirect left-recursion { enum LeftGrammar = ` Left: @@ -2857,7 +2908,7 @@ unittest // Indirect left-recursion assert(result.matches == ["n", "+", "n", "+", "n", "+", "n"]); } -unittest // Proper blocking of memoization +@safe unittest // Proper blocking of memoization { // Three interlocking cycles of indirect left-recursion. enum LeftGrammar = ` @@ -2877,18 +2928,20 @@ unittest // Proper blocking of memoization } // Example from http://www.inf.puc-rio.br/~roberto/docs/sblp2012.pdf -unittest // Mutual left-recursion +@safe unittest // Mutual left-recursion { /* A thing about stoppers: - Because P is at the intersection of left-recursive cycles P -> P and L -> P -> L, it should - suffice to make only P a stopper to stop unbounded left-recursion. And so it does. But, - stoppers parse greedily: they always consume the maximum of input. So below, if only P is a stopper, - at some point P parses the complete input. Then L fails because it cannot append ".x", then M fails. - If both are made a stopper then M succeeds. That is because P will try L when P '(n)' no longer - consumes input, which will appear as a left-recursion to L if it is a stopper and because of that - it will have a chance to succeed on the full input which it recorded in its seed for the previous - recursion. + Because P is at the intersection of left-recursive cycles P -> P and L -> P -> L, it should + suffice to make only P a stopper to stop unbounded left-recursion. And so it does. But, + stoppers parse greedily: they always consume the maximum of input. So below, if only P is a stopper, + at some point P parses the complete input. Then L fails because it cannot append ".x", then M fails. + If both are made a stopper then M succeeds. That is because P will try L when P '(n)' no longer + consumes input, which will appear as a left-recursion to L if it is a stopper and because of that + it will have a chance to succeed on the full input which it recorded in its seed for the previous + recursion. */ + alias ParseTree = DefaultParseTree; + enum LeftGrammar = ` Left: M <- L eoi @@ -2901,7 +2954,7 @@ unittest // Mutual left-recursion assert(result.matches == ["x", "(n)", "(n)", ".x", "(n)", ".x"]); } -unittest // Left- and right-recursion (is right-associative!) +@safe unittest // Left- and right-recursion (is right-associative!) { enum LeftRightGrammar = ` LeftRight: @@ -2914,7 +2967,7 @@ unittest // Left- and right-recursion (is right-associative!) assert(result.matches == ["n", "+", "n", "+", "n", "+", "n"]); } -unittest // Hidden left-recursion +@safe unittest // Hidden left-recursion { enum HiddenLeft = ` Test: @@ -2928,7 +2981,7 @@ unittest // Hidden left-recursion assert(Test("bbca").successful); } -unittest // Null-matching left-recursion +@safe unittest // Null-matching left-recursion { enum NullMatch = ` Test: diff --git a/pegged/introspection.d b/pegged/introspection.d index 22bd5c73..6744a23a 100644 --- a/pegged/introspection.d +++ b/pegged/introspection.d @@ -40,7 +40,7 @@ enum InfiniteLoop { no, yes, indeterminate } /** Struct holding the introspection info on a rule. */ -struct RuleInfo +@safe struct RuleInfo { Recursive recursion; /// Is the rule recursive? LeftRecursive leftRecursion; /// Is the rule left-recursive? @@ -52,13 +52,13 @@ struct RuleInfo /** Struct holding the introspection info on a grammar. */ -struct GrammarInfo +@safe struct GrammarInfo { RuleInfo[string] ruleInfo; immutable(string[])[] leftRecursiveCycles; } -pure void appendCycleIfUnique(ref immutable(string[])[] cycles, const string[] cycle) +@safe pure void appendCycleIfUnique(ref immutable(string[])[] cycles, const string[] cycle) { bool exists() { @@ -89,7 +89,7 @@ Returns for all grammar rules: This kind of potential problem can be detected statically and should be transmitted to the grammar designer. */ -pure GrammarInfo grammarInfo(ParseTree p) +GrammarInfo grammarInfo(ParseTree)(ParseTree p) pure @safe { if (p.name == "Pegged") return grammarInfo(p.children[0]); @@ -109,18 +109,18 @@ pure GrammarInfo grammarInfo(ParseTree p) also appear in the call graph when the rule has a name: hence, calls to predefined rules like 'identifier' or 'digit' will appear, but not a call to '[0-9]+', considered here as an anonymous rule. */ - bool[string][string] callGraph(ParseTree p) + bool[string][string] callGraph(ParseTree p) @safe { - bool[string] findIdentifiers(ParseTree p) + bool[string] findIdentifiers(ParseTree p) @trusted { bool[string] idList; if (p.name == "Pegged.Identifier") idList[p.matches[0]] = true; - else + else { foreach(child; p.children) foreach(name; findIdentifiers(child).keys) idList[name] = true; - + } return idList; } @@ -144,7 +144,7 @@ pure GrammarInfo grammarInfo(ParseTree p) It will propagate the calls to find all rules called by a given rule, directly (already in the call graph) or indirectly (through another rule). */ - bool[string][string] closure(bool[string][string] graph) + bool[string][string] closure(bool[string][string] graph) @trusted { bool[string][string] path; foreach(rule, children; graph) // deep-dupping, to avoid children aliasing @@ -169,7 +169,7 @@ pure GrammarInfo grammarInfo(ParseTree p) return path; } - Recursive[string] recursions(bool[string][string] graph) + Recursive[string] recursions(bool[string][string] graph) @safe { bool[string][string] path = closure(graph); @@ -189,7 +189,7 @@ pure GrammarInfo grammarInfo(ParseTree p) return result; } - NullMatch nullMatching(ParseTree p) + NullMatch nullMatching(ParseTree p) @safe { switch (p.name) { @@ -428,18 +428,18 @@ Returns for all grammar rules: This kind of potential problem can be detected statically and should be transmitted to the grammar designer. */ -pure RuleInfo[string] ruleInfo(ParseTree p) +@safe pure RuleInfo[string] ruleInfo(ParseTree)(ParseTree p) { return grammarInfo(p).ruleInfo; } /** ditto */ -RuleInfo[string] ruleInfo(string grammar) +@safe RuleInfo[string] ruleInfo(string grammar) { return ruleInfo(Pegged(grammar).children[0]); } -unittest +@safe unittest { auto info = ruleInfo(` Test: @@ -463,7 +463,7 @@ unittest } // Test against infinite recursion in detection of indirect left-recursion. -unittest +@safe unittest { auto info = ruleInfo(` Test: @@ -475,7 +475,7 @@ unittest } // Test against compile-time infinite recursion. -unittest // Mutual left-recursion +@safe unittest // Mutual left-recursion { enum ct = ruleInfo(` Left: @@ -498,7 +498,7 @@ unittest // Mutual left-recursion assert(rt["P"].leftRecursion == LeftRecursive.direct); } -unittest // Intersecting cycles of left-recursion +@safe unittest // Intersecting cycles of left-recursion { enum ct = ruleInfo(` Left: @@ -520,7 +520,7 @@ unittest // Intersecting cycles of left-recursion assert(rt["B"].leftRecursion == LeftRecursive.indirect); } -unittest // Null-matching +@safe unittest // Null-matching { enum ct = ruleInfo(` NM: @@ -538,7 +538,7 @@ unittest // Null-matching assert(rt["NMM"].nullMatch == NullMatch.yes); } -unittest // Not null-matching +@safe unittest // Not null-matching { enum ct = ruleInfo(` Left: @@ -560,7 +560,7 @@ unittest // Not null-matching assert(rt["P"].nullMatch == NullMatch.no); } -unittest // Left-recursive null-matching +@safe unittest // Left-recursive null-matching { enum ct = ruleInfo(` Left: @@ -587,7 +587,7 @@ unittest // Left-recursive null-matching Act on rules parse tree as produced by pegged.parser. Replace every occurence of child in parent by child's parse tree */ -ParseTree replaceInto(ParseTree parent, ParseTree child) +ParseTree replaceInto(ParseTree)(ParseTree parent, ParseTree child) { if (parent.name == "Pegged.RhsName" && parent.matches[0] == child.matches[0]) return ParseTree("Pegged.Named", true, child.matches[0..1], "",0,0, diff --git a/pegged/parser.d b/pegged/parser.d index b1d976cd..72f8d11e 100644 --- a/pegged/parser.d +++ b/pegged/parser.d @@ -109,7 +109,7 @@ TKNString <- (&'q{' ('q' NestedList('{',DString,'}'))) DLMString <- ('q' doublequote) ( (&'{' NestedList('{',DString,'}')) / (&'[' NestedList('[',DString,']')) - / (&'$(LPAREN)' NestedList('(',DString,')')) + / (&'(' NestedList('(',DString,')')) / (&'<' NestedList('<',DString,'>')) ) doublequote @@ -133,22 +133,31 @@ NestedList(L,R) <- ^L ( !(L/R) . )* (NestedList(L,R) / ( !(L/R) . )*)* ( !(L/R) +/ module pegged.parser; +public import pegged.defaultparsetree; public import pegged.peg; import std.algorithm: startsWith; import std.functional: toDelegate; -struct GenericPegged(TParseTree) +import pegged.defaultparsetree : DefaultParseTree; +@safe struct GenericPegged(ParseTree) { +// static if (is(ParseTree == DefaultParseTree)) { + alias PEG=ParseTree; +// } + import std.functional : toDelegate; import pegged.dynamic.grammar; static import pegged.peg; - struct Pegged + mixin DefaultPatters!ParseTree; + //alias PEG=PeggedT!ParseTree; + + @safe struct Pegged { - enum name = "Pegged"; - static ParseTree delegate(ParseTree)[string] before; - static ParseTree delegate(ParseTree)[string] after; - static ParseTree delegate(ParseTree)[string] rules; - static this() + enum name = "Pegged"; + static ParseTree.Dynamic[string] before; + static ParseTree.Dynamic[string] after; + static ParseTree.Dynamic[string] rules; + static this() @trusted { rules["Grammar"] = toDelegate(&Grammar); rules["Definition"] = toDelegate(&Definition); @@ -207,6 +216,7 @@ struct GenericPegged(TParseTree) template hooked(alias r, string name) { + @safe { static ParseTree hooked(ParseTree p) { ParseTree result; @@ -230,12 +240,13 @@ struct GenericPegged(TParseTree) { return hooked!(r, name)(ParseTree("",false,[],input)); } + } } static void addRuleBefore(string parentRule, string ruleSyntax) { // enum name is the current grammar name - DynamicGrammar dg = pegged.dynamic.grammar.grammar(name ~ ": " ~ ruleSyntax, rules); + auto dg = pegged.dynamic.grammar.grammar!ParseTree(name ~ ": " ~ ruleSyntax, rules); foreach(ruleName,rule; dg.rules) if (ruleName != "Spacing") // Keep the local Spacing rule, do not overwrite it rules[ruleName] = rule; @@ -245,11 +256,11 @@ struct GenericPegged(TParseTree) static void addRuleAfter(string parentRule, string ruleSyntax) { // enum name is the current grammar named - DynamicGrammar dg = pegged.dynamic.grammar.grammar(name ~ ": " ~ ruleSyntax, rules); - foreach(name,rule; dg.rules) + auto dg = pegged.dynamic.grammar.grammar!ParseTree(name ~ ": " ~ ruleSyntax, rules); + foreach(ruleName,rule; dg.rules) { - if (name != "Spacing") - rules[name] = rule; + if (ruleName != "Spacing") + rules[ruleName] = rule; } after[parentRule] = rules[dg.startingRule]; } @@ -259,27 +270,27 @@ struct GenericPegged(TParseTree) import std.algorithm : startsWith; return s.startsWith("Pegged."); } - mixin decimateTree; + mixin decimateTree!ParseTree; - static TParseTree Grammar(TParseTree p) + static ParseTree Grammar(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Spacing, GrammarName, pegged.peg.oneOrMore!(Definition), pegged.peg.discard!(eoi)), "Pegged.Grammar")(p); + return PEG.defined!(PEG.and!(Spacing, GrammarName, PEG.oneOrMore!(Definition), PEG.discard!(eoi)), "Pegged.Grammar")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Spacing, GrammarName, pegged.peg.oneOrMore!(Definition), pegged.peg.discard!(eoi)), "Pegged.Grammar"), "Grammar")(p); + return hooked!(PEG.defined!(PEG.and!(Spacing, GrammarName, PEG.oneOrMore!(Definition), PEG.discard!(eoi)), "Pegged.Grammar"), "Grammar")(p); } } - static TParseTree Grammar(string s) + static ParseTree Grammar(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Spacing, GrammarName, pegged.peg.oneOrMore!(Definition), pegged.peg.discard!(eoi)), "Pegged.Grammar")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Spacing, GrammarName, PEG.oneOrMore!(Definition), PEG.discard!(eoi)), "Pegged.Grammar")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Spacing, GrammarName, pegged.peg.oneOrMore!(Definition), pegged.peg.discard!(eoi)), "Pegged.Grammar"), "Grammar")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Spacing, GrammarName, PEG.oneOrMore!(Definition), PEG.discard!(eoi)), "Pegged.Grammar"), "Grammar")(ParseTree("", false,[], s)); } } static string Grammar(GetName g) @@ -287,25 +298,25 @@ struct GenericPegged(TParseTree) return "Pegged.Grammar"; } - static TParseTree Definition(TParseTree p) + static ParseTree Definition(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(LhsName, Arrow, Expression), "Pegged.Definition")(p); + return PEG.defined!(PEG.and!(LhsName, Arrow, Expression), "Pegged.Definition")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(LhsName, Arrow, Expression), "Pegged.Definition"), "Definition")(p); + return hooked!(PEG.defined!(PEG.and!(LhsName, Arrow, Expression), "Pegged.Definition"), "Definition")(p); } } - static TParseTree Definition(string s) + static ParseTree Definition(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(LhsName, Arrow, Expression), "Pegged.Definition")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(LhsName, Arrow, Expression), "Pegged.Definition")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(LhsName, Arrow, Expression), "Pegged.Definition"), "Definition")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(LhsName, Arrow, Expression), "Pegged.Definition"), "Definition")(ParseTree("", false,[], s)); } } static string Definition(GetName g) @@ -313,25 +324,25 @@ struct GenericPegged(TParseTree) return "Pegged.Definition"; } - static TParseTree Expression(TParseTree p) + static ParseTree Expression(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(FirstExpression, LongestExpression), "Pegged.Expression")(p); + return PEG.defined!(PEG.or!(FirstExpression, LongestExpression), "Pegged.Expression")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(FirstExpression, LongestExpression), "Pegged.Expression"), "Expression")(p); + return hooked!(PEG.defined!(PEG.or!(FirstExpression, LongestExpression), "Pegged.Expression"), "Expression")(p); } } - static TParseTree Expression(string s) + static ParseTree Expression(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(FirstExpression, LongestExpression), "Pegged.Expression")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(FirstExpression, LongestExpression), "Pegged.Expression")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(FirstExpression, LongestExpression), "Pegged.Expression"), "Expression")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(FirstExpression, LongestExpression), "Pegged.Expression"), "Expression")(ParseTree("", false,[], s)); } } static string Expression(GetName g) @@ -339,25 +350,25 @@ struct GenericPegged(TParseTree) return "Pegged.Expression"; } - static TParseTree FirstExpression(TParseTree p) + static ParseTree FirstExpression(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(OR)), Sequence, pegged.peg.oneOrMore!(pegged.peg.and!(pegged.peg.discard!(OR), Sequence))), "Pegged.FirstExpression")(p); + return PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(OR)), Sequence, PEG.oneOrMore!(PEG.and!(PEG.discard!(OR), Sequence))), "Pegged.FirstExpression")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(OR)), Sequence, pegged.peg.oneOrMore!(pegged.peg.and!(pegged.peg.discard!(OR), Sequence))), "Pegged.FirstExpression"), "FirstExpression")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(OR)), Sequence, PEG.oneOrMore!(PEG.and!(PEG.discard!(OR), Sequence))), "Pegged.FirstExpression"), "FirstExpression")(p); } } - static TParseTree FirstExpression(string s) + static ParseTree FirstExpression(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(OR)), Sequence, pegged.peg.oneOrMore!(pegged.peg.and!(pegged.peg.discard!(OR), Sequence))), "Pegged.FirstExpression")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(OR)), Sequence, PEG.oneOrMore!(PEG.and!(PEG.discard!(OR), Sequence))), "Pegged.FirstExpression")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(OR)), Sequence, pegged.peg.oneOrMore!(pegged.peg.and!(pegged.peg.discard!(OR), Sequence))), "Pegged.FirstExpression"), "FirstExpression")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(OR)), Sequence, PEG.oneOrMore!(PEG.and!(PEG.discard!(OR), Sequence))), "Pegged.FirstExpression"), "FirstExpression")(ParseTree("", false,[], s)); } } static string FirstExpression(GetName g) @@ -365,25 +376,25 @@ struct GenericPegged(TParseTree) return "Pegged.FirstExpression"; } - static TParseTree LongestExpression(TParseTree p) + static ParseTree LongestExpression(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(pegged.peg.or!(OR, LONGEST_OR))), Sequence, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression")(p); + return PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(PEG.or!(OR, LONGEST_OR))), Sequence, PEG.zeroOrMore!(PEG.and!(PEG.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(pegged.peg.or!(OR, LONGEST_OR))), Sequence, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression"), "LongestExpression")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(PEG.or!(OR, LONGEST_OR))), Sequence, PEG.zeroOrMore!(PEG.and!(PEG.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression"), "LongestExpression")(p); } } - static TParseTree LongestExpression(string s) + static ParseTree LongestExpression(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(pegged.peg.or!(OR, LONGEST_OR))), Sequence, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(PEG.or!(OR, LONGEST_OR))), Sequence, PEG.zeroOrMore!(PEG.and!(PEG.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(pegged.peg.or!(OR, LONGEST_OR))), Sequence, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression"), "LongestExpression")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(PEG.option!(PEG.or!(OR, LONGEST_OR))), Sequence, PEG.zeroOrMore!(PEG.and!(PEG.discard!(LONGEST_OR), Sequence))), "Pegged.LongestExpression"), "LongestExpression")(ParseTree("", false,[], s)); } } static string LongestExpression(GetName g) @@ -391,25 +402,25 @@ struct GenericPegged(TParseTree) return "Pegged.LongestExpression"; } - static TParseTree Sequence(TParseTree p) + static ParseTree Sequence(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.oneOrMore!(Prefix), "Pegged.Sequence")(p); + return PEG.defined!(PEG.oneOrMore!(Prefix), "Pegged.Sequence")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.oneOrMore!(Prefix), "Pegged.Sequence"), "Sequence")(p); + return hooked!(PEG.defined!(PEG.oneOrMore!(Prefix), "Pegged.Sequence"), "Sequence")(p); } } - static TParseTree Sequence(string s) + static ParseTree Sequence(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.oneOrMore!(Prefix), "Pegged.Sequence")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.oneOrMore!(Prefix), "Pegged.Sequence")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.oneOrMore!(Prefix), "Pegged.Sequence"), "Sequence")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.oneOrMore!(Prefix), "Pegged.Sequence"), "Sequence")(ParseTree("", false,[], s)); } } static string Sequence(GetName g) @@ -417,25 +428,25 @@ struct GenericPegged(TParseTree) return "Pegged.Sequence"; } - static TParseTree Prefix(TParseTree p) + static ParseTree Prefix(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.zeroOrMore!(pegged.peg.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix")(p); + return PEG.defined!(PEG.and!(PEG.zeroOrMore!(PEG.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.zeroOrMore!(pegged.peg.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix"), "Prefix")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.zeroOrMore!(PEG.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix"), "Prefix")(p); } } - static TParseTree Prefix(string s) + static ParseTree Prefix(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.zeroOrMore!(pegged.peg.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.zeroOrMore!(PEG.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.zeroOrMore!(pegged.peg.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix"), "Prefix")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.zeroOrMore!(PEG.or!(POS, NEG, FUSE, DISCARD, KEEP, DROP, PROPAGATE)), Suffix), "Pegged.Prefix"), "Prefix")(ParseTree("", false,[], s)); } } static string Prefix(GetName g) @@ -443,25 +454,25 @@ struct GenericPegged(TParseTree) return "Pegged.Prefix"; } - static TParseTree Suffix(TParseTree p) + static ParseTree Suffix(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Primary, pegged.peg.zeroOrMore!(pegged.peg.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix")(p); + return PEG.defined!(PEG.and!(Primary, PEG.zeroOrMore!(PEG.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Primary, pegged.peg.zeroOrMore!(pegged.peg.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix"), "Suffix")(p); + return hooked!(PEG.defined!(PEG.and!(Primary, PEG.zeroOrMore!(PEG.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix"), "Suffix")(p); } } - static TParseTree Suffix(string s) + static ParseTree Suffix(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Primary, pegged.peg.zeroOrMore!(pegged.peg.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Primary, PEG.zeroOrMore!(PEG.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Primary, pegged.peg.zeroOrMore!(pegged.peg.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix"), "Suffix")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Primary, PEG.zeroOrMore!(PEG.or!(OPTION, ZEROORMORE, ONEORMORE, Action))), "Pegged.Suffix"), "Suffix")(ParseTree("", false,[], s)); } } static string Suffix(GetName g) @@ -469,25 +480,25 @@ struct GenericPegged(TParseTree) return "Pegged.Suffix"; } - static TParseTree Primary(TParseTree p) + static ParseTree Primary(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.and!(LhsName, Arrow)), pegged.peg.or!(RhsName, pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary")(p); + return PEG.defined!(PEG.and!(PEG.negLookahead!(PEG.and!(LhsName, Arrow)), PEG.or!(RhsName, PEG.and!(PEG.discard!(OPEN), Expression, PEG.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.and!(LhsName, Arrow)), pegged.peg.or!(RhsName, pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary"), "Primary")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.negLookahead!(PEG.and!(LhsName, Arrow)), PEG.or!(RhsName, PEG.and!(PEG.discard!(OPEN), Expression, PEG.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary"), "Primary")(p); } } - static TParseTree Primary(string s) + static ParseTree Primary(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.and!(LhsName, Arrow)), pegged.peg.or!(RhsName, pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.negLookahead!(PEG.and!(LhsName, Arrow)), PEG.or!(RhsName, PEG.and!(PEG.discard!(OPEN), Expression, PEG.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.and!(LhsName, Arrow)), pegged.peg.or!(RhsName, pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary"), "Primary")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.negLookahead!(PEG.and!(LhsName, Arrow)), PEG.or!(RhsName, PEG.and!(PEG.discard!(OPEN), Expression, PEG.discard!(CLOSE)), Literal, CILiteral, CharClass, ANY)), "Pegged.Primary"), "Primary")(ParseTree("", false,[], s)); } } static string Primary(GetName g) @@ -495,25 +506,25 @@ struct GenericPegged(TParseTree) return "Pegged.Primary"; } - static TParseTree Identifier(TParseTree p) + static ParseTree Identifier(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(identifier, "Pegged.Identifier")(p); + return PEG.defined!(identifier, "Pegged.Identifier")(p); } else { - return hooked!(pegged.peg.defined!(identifier, "Pegged.Identifier"), "Identifier")(p); + return hooked!(PEG.defined!(identifier, "Pegged.Identifier"), "Identifier")(p); } } - static TParseTree Identifier(string s) + static ParseTree Identifier(string s) { if(__ctfe) - return pegged.peg.defined!(identifier, "Pegged.Identifier")(TParseTree("", false,[], s)); + return PEG.defined!(identifier, "Pegged.Identifier")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(identifier, "Pegged.Identifier"), "Identifier")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(identifier, "Pegged.Identifier"), "Identifier")(ParseTree("", false,[], s)); } } static string Identifier(GetName g) @@ -521,25 +532,25 @@ struct GenericPegged(TParseTree) return "Pegged.Identifier"; } - static TParseTree GrammarName(TParseTree p) + static ParseTree GrammarName(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing, pegged.peg.discard!(pegged.peg.literal!(":")), Spacing), "Pegged.GrammarName")(p); + return PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing, PEG.discard!(PEG.literal!(":")), Spacing), "Pegged.GrammarName")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing, pegged.peg.discard!(pegged.peg.literal!(":")), Spacing), "Pegged.GrammarName"), "GrammarName")(p); + return hooked!(PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing, PEG.discard!(PEG.literal!(":")), Spacing), "Pegged.GrammarName"), "GrammarName")(p); } } - static TParseTree GrammarName(string s) + static ParseTree GrammarName(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing, pegged.peg.discard!(pegged.peg.literal!(":")), Spacing), "Pegged.GrammarName")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing, PEG.discard!(PEG.literal!(":")), Spacing), "Pegged.GrammarName")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing, pegged.peg.discard!(pegged.peg.literal!(":")), Spacing), "Pegged.GrammarName"), "GrammarName")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing, PEG.discard!(PEG.literal!(":")), Spacing), "Pegged.GrammarName"), "GrammarName")(ParseTree("", false,[], s)); } } static string GrammarName(GetName g) @@ -547,25 +558,25 @@ struct GenericPegged(TParseTree) return "Pegged.GrammarName"; } - static TParseTree LhsName(TParseTree p) + static ParseTree LhsName(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing), "Pegged.LhsName")(p); + return PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing), "Pegged.LhsName")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing), "Pegged.LhsName"), "LhsName")(p); + return hooked!(PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing), "Pegged.LhsName"), "LhsName")(p); } } - static TParseTree LhsName(string s) + static ParseTree LhsName(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing), "Pegged.LhsName")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing), "Pegged.LhsName")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ParamList), Spacing), "Pegged.LhsName"), "LhsName")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Identifier, PEG.option!(ParamList), Spacing), "Pegged.LhsName"), "LhsName")(ParseTree("", false,[], s)); } } static string LhsName(GetName g) @@ -573,25 +584,25 @@ struct GenericPegged(TParseTree) return "Pegged.LhsName"; } - static TParseTree RhsName(TParseTree p) + static ParseTree RhsName(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ArgList), pegged.peg.zeroOrMore!(pegged.peg.and!(NAMESEP, Identifier, pegged.peg.option!(ArgList))), Spacing), "Pegged.RhsName")(p); + return PEG.defined!(PEG.and!(Identifier, PEG.option!(ArgList), PEG.zeroOrMore!(PEG.and!(NAMESEP, Identifier, PEG.option!(ArgList))), Spacing), "Pegged.RhsName")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ArgList), pegged.peg.zeroOrMore!(pegged.peg.and!(NAMESEP, Identifier, pegged.peg.option!(ArgList))), Spacing), "Pegged.RhsName"), "RhsName")(p); + return hooked!(PEG.defined!(PEG.and!(Identifier, PEG.option!(ArgList), PEG.zeroOrMore!(PEG.and!(NAMESEP, Identifier, PEG.option!(ArgList))), Spacing), "Pegged.RhsName"), "RhsName")(p); } } - static TParseTree RhsName(string s) + static ParseTree RhsName(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ArgList), pegged.peg.zeroOrMore!(pegged.peg.and!(NAMESEP, Identifier, pegged.peg.option!(ArgList))), Spacing), "Pegged.RhsName")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Identifier, PEG.option!(ArgList), PEG.zeroOrMore!(PEG.and!(NAMESEP, Identifier, PEG.option!(ArgList))), Spacing), "Pegged.RhsName")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, pegged.peg.option!(ArgList), pegged.peg.zeroOrMore!(pegged.peg.and!(NAMESEP, Identifier, pegged.peg.option!(ArgList))), Spacing), "Pegged.RhsName"), "RhsName")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Identifier, PEG.option!(ArgList), PEG.zeroOrMore!(PEG.and!(NAMESEP, Identifier, PEG.option!(ArgList))), Spacing), "Pegged.RhsName"), "RhsName")(ParseTree("", false,[], s)); } } static string RhsName(GetName g) @@ -599,25 +610,25 @@ struct GenericPegged(TParseTree) return "Pegged.RhsName"; } - static TParseTree ParamList(TParseTree p) + static ParseTree ParamList(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Param, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Param)), pegged.peg.discard!(CLOSE)), "Pegged.ParamList")(p); + return PEG.defined!(PEG.and!(PEG.discard!(OPEN), Param, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Param)), PEG.discard!(CLOSE)), "Pegged.ParamList")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Param, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Param)), pegged.peg.discard!(CLOSE)), "Pegged.ParamList"), "ParamList")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(OPEN), Param, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Param)), PEG.discard!(CLOSE)), "Pegged.ParamList"), "ParamList")(p); } } - static TParseTree ParamList(string s) + static ParseTree ParamList(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Param, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Param)), pegged.peg.discard!(CLOSE)), "Pegged.ParamList")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.discard!(OPEN), Param, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Param)), PEG.discard!(CLOSE)), "Pegged.ParamList")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Param, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Param)), pegged.peg.discard!(CLOSE)), "Pegged.ParamList"), "ParamList")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(OPEN), Param, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Param)), PEG.discard!(CLOSE)), "Pegged.ParamList"), "ParamList")(ParseTree("", false,[], s)); } } static string ParamList(GetName g) @@ -625,25 +636,25 @@ struct GenericPegged(TParseTree) return "Pegged.ParamList"; } - static TParseTree Param(TParseTree p) + static ParseTree Param(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(DefaultParam, SingleParam), "Pegged.Param")(p); + return PEG.defined!(PEG.or!(DefaultParam, SingleParam), "Pegged.Param")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(DefaultParam, SingleParam), "Pegged.Param"), "Param")(p); + return hooked!(PEG.defined!(PEG.or!(DefaultParam, SingleParam), "Pegged.Param"), "Param")(p); } } - static TParseTree Param(string s) + static ParseTree Param(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(DefaultParam, SingleParam), "Pegged.Param")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(DefaultParam, SingleParam), "Pegged.Param")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(DefaultParam, SingleParam), "Pegged.Param"), "Param")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(DefaultParam, SingleParam), "Pegged.Param"), "Param")(ParseTree("", false,[], s)); } } static string Param(GetName g) @@ -651,25 +662,25 @@ struct GenericPegged(TParseTree) return "Pegged.Param"; } - static TParseTree DefaultParam(TParseTree p) + static ParseTree DefaultParam(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing, pegged.peg.discard!(ASSIGN), Expression), "Pegged.DefaultParam")(p); + return PEG.defined!(PEG.and!(Identifier, Spacing, PEG.discard!(ASSIGN), Expression), "Pegged.DefaultParam")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing, pegged.peg.discard!(ASSIGN), Expression), "Pegged.DefaultParam"), "DefaultParam")(p); + return hooked!(PEG.defined!(PEG.and!(Identifier, Spacing, PEG.discard!(ASSIGN), Expression), "Pegged.DefaultParam"), "DefaultParam")(p); } } - static TParseTree DefaultParam(string s) + static ParseTree DefaultParam(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing, pegged.peg.discard!(ASSIGN), Expression), "Pegged.DefaultParam")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Identifier, Spacing, PEG.discard!(ASSIGN), Expression), "Pegged.DefaultParam")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing, pegged.peg.discard!(ASSIGN), Expression), "Pegged.DefaultParam"), "DefaultParam")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Identifier, Spacing, PEG.discard!(ASSIGN), Expression), "Pegged.DefaultParam"), "DefaultParam")(ParseTree("", false,[], s)); } } static string DefaultParam(GetName g) @@ -677,25 +688,25 @@ struct GenericPegged(TParseTree) return "Pegged.DefaultParam"; } - static TParseTree SingleParam(TParseTree p) + static ParseTree SingleParam(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing), "Pegged.SingleParam")(p); + return PEG.defined!(PEG.and!(Identifier, Spacing), "Pegged.SingleParam")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing), "Pegged.SingleParam"), "SingleParam")(p); + return hooked!(PEG.defined!(PEG.and!(Identifier, Spacing), "Pegged.SingleParam"), "SingleParam")(p); } } - static TParseTree SingleParam(string s) + static ParseTree SingleParam(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing), "Pegged.SingleParam")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(Identifier, Spacing), "Pegged.SingleParam")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(Identifier, Spacing), "Pegged.SingleParam"), "SingleParam")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(Identifier, Spacing), "Pegged.SingleParam"), "SingleParam")(ParseTree("", false,[], s)); } } static string SingleParam(GetName g) @@ -703,25 +714,25 @@ struct GenericPegged(TParseTree) return "Pegged.SingleParam"; } - static TParseTree ArgList(TParseTree p) + static ParseTree ArgList(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Expression)), pegged.peg.discard!(CLOSE)), "Pegged.ArgList")(p); + return PEG.defined!(PEG.and!(PEG.discard!(OPEN), Expression, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Expression)), PEG.discard!(CLOSE)), "Pegged.ArgList")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Expression)), pegged.peg.discard!(CLOSE)), "Pegged.ArgList"), "ArgList")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(OPEN), Expression, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Expression)), PEG.discard!(CLOSE)), "Pegged.ArgList"), "ArgList")(p); } } - static TParseTree ArgList(string s) + static ParseTree ArgList(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Expression)), pegged.peg.discard!(CLOSE)), "Pegged.ArgList")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.discard!(OPEN), Expression, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Expression)), PEG.discard!(CLOSE)), "Pegged.ArgList")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(OPEN), Expression, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), Expression)), pegged.peg.discard!(CLOSE)), "Pegged.ArgList"), "ArgList")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(OPEN), Expression, PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), Expression)), PEG.discard!(CLOSE)), "Pegged.ArgList"), "ArgList")(ParseTree("", false,[], s)); } } static string ArgList(GetName g) @@ -729,25 +740,25 @@ struct GenericPegged(TParseTree) return "Pegged.ArgList"; } - static TParseTree Literal(TParseTree p) + static ParseTree Literal(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing)), "Pegged.Literal")(p); + return PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.negLookahead!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.negLookahead!(PEG.literal!("i")), Spacing)), "Pegged.Literal")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing)), "Pegged.Literal"), "Literal")(p); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.negLookahead!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.negLookahead!(PEG.literal!("i")), Spacing)), "Pegged.Literal"), "Literal")(p); } } - static TParseTree Literal(string s) + static ParseTree Literal(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing)), "Pegged.Literal")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.negLookahead!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.negLookahead!(PEG.literal!("i")), Spacing)), "Pegged.Literal")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.negLookahead!(pegged.peg.literal!("i")), Spacing)), "Pegged.Literal"), "Literal")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.negLookahead!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.negLookahead!(PEG.literal!("i")), Spacing)), "Pegged.Literal"), "Literal")(ParseTree("", false,[], s)); } } static string Literal(GetName g) @@ -755,25 +766,25 @@ struct GenericPegged(TParseTree) return "Pegged.Literal"; } - static TParseTree CILiteral(TParseTree p) + static ParseTree CILiteral(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing)), "Pegged.CILiteral")(p); + return PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.discard!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.discard!(PEG.literal!("i")), Spacing)), "Pegged.CILiteral")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing)), "Pegged.CILiteral"), "CILiteral")(p); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.discard!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.discard!(PEG.literal!("i")), Spacing)), "Pegged.CILiteral"), "CILiteral")(p); } } - static TParseTree CILiteral(string s) + static ParseTree CILiteral(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing)), "Pegged.CILiteral")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.discard!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.discard!(PEG.literal!("i")), Spacing)), "Pegged.CILiteral")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(quote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(quote), Char))), quote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing), pegged.peg.and!(doublequote, pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char))), doublequote, pegged.peg.discard!(pegged.peg.literal!("i")), Spacing)), "Pegged.CILiteral"), "CILiteral")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(quote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(quote), Char))), quote, PEG.discard!(PEG.literal!("i")), Spacing), PEG.and!(doublequote, PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char))), doublequote, PEG.discard!(PEG.literal!("i")), Spacing)), "Pegged.CILiteral"), "CILiteral")(ParseTree("", false,[], s)); } } static string CILiteral(GetName g) @@ -781,25 +792,25 @@ struct GenericPegged(TParseTree) return "Pegged.CILiteral"; } - static TParseTree CharClass(TParseTree p) + static ParseTree CharClass(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.literal!("[")), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("]")), CharRange)), pegged.peg.discard!(pegged.peg.literal!("]")), Spacing), "Pegged.CharClass")(p); + return PEG.defined!(PEG.and!(PEG.discard!(PEG.literal!("[")), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("]")), CharRange)), PEG.discard!(PEG.literal!("]")), Spacing), "Pegged.CharClass")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.literal!("[")), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("]")), CharRange)), pegged.peg.discard!(pegged.peg.literal!("]")), Spacing), "Pegged.CharClass"), "CharClass")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(PEG.literal!("[")), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("]")), CharRange)), PEG.discard!(PEG.literal!("]")), Spacing), "Pegged.CharClass"), "CharClass")(p); } } - static TParseTree CharClass(string s) + static ParseTree CharClass(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.literal!("[")), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("]")), CharRange)), pegged.peg.discard!(pegged.peg.literal!("]")), Spacing), "Pegged.CharClass")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.discard!(PEG.literal!("[")), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("]")), CharRange)), PEG.discard!(PEG.literal!("]")), Spacing), "Pegged.CharClass")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.literal!("[")), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("]")), CharRange)), pegged.peg.discard!(pegged.peg.literal!("]")), Spacing), "Pegged.CharClass"), "CharClass")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(PEG.literal!("[")), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("]")), CharRange)), PEG.discard!(PEG.literal!("]")), Spacing), "Pegged.CharClass"), "CharClass")(ParseTree("", false,[], s)); } } static string CharClass(GetName g) @@ -807,25 +818,25 @@ struct GenericPegged(TParseTree) return "Pegged.CharClass"; } - static TParseTree CharRange(TParseTree p) + static ParseTree CharRange(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(Char, pegged.peg.literal!("-"), Char), Char), "Pegged.CharRange")(p); + return PEG.defined!(PEG.or!(PEG.and!(Char, PEG.literal!("-"), Char), Char), "Pegged.CharRange")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(Char, pegged.peg.literal!("-"), Char), Char), "Pegged.CharRange"), "CharRange")(p); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(Char, PEG.literal!("-"), Char), Char), "Pegged.CharRange"), "CharRange")(p); } } - static TParseTree CharRange(string s) + static ParseTree CharRange(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(Char, pegged.peg.literal!("-"), Char), Char), "Pegged.CharRange")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(PEG.and!(Char, PEG.literal!("-"), Char), Char), "Pegged.CharRange")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(Char, pegged.peg.literal!("-"), Char), Char), "Pegged.CharRange"), "CharRange")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(Char, PEG.literal!("-"), Char), Char), "Pegged.CharRange"), "CharRange")(ParseTree("", false,[], s)); } } static string CharRange(GetName g) @@ -833,25 +844,25 @@ struct GenericPegged(TParseTree) return "Pegged.CharRange"; } - static TParseTree Char(TParseTree p) + static ParseTree Char(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.or!(pegged.peg.and!(backslash, pegged.peg.or!(quote, doublequote, backquote, backslash, pegged.peg.literal!("-"), pegged.peg.literal!("["), pegged.peg.literal!("]"), pegged.peg.or!(pegged.peg.literal!("n"), pegged.peg.literal!("r"), pegged.peg.literal!("t")), pegged.peg.and!(pegged.peg.charRange!('0', '2'), pegged.peg.charRange!('0', '7'), pegged.peg.charRange!('0', '7')), pegged.peg.and!(pegged.peg.charRange!('0', '7'), pegged.peg.option!(pegged.peg.charRange!('0', '7'))), pegged.peg.and!(pegged.peg.literal!("x"), hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), pegged.peg.any)), "Pegged.Char")(p); + return PEG.defined!(PEG.fuse!(PEG.or!(PEG.and!(backslash, PEG.or!(quote, doublequote, backquote, backslash, PEG.literal!("-"), PEG.literal!("["), PEG.literal!("]"), PEG.or!(PEG.literal!("n"), PEG.literal!("r"), PEG.literal!("t")), PEG.and!(PEG.charRange!('0', '2'), PEG.charRange!('0', '7'), PEG.charRange!('0', '7')), PEG.and!(PEG.charRange!('0', '7'), PEG.option!(PEG.charRange!('0', '7'))), PEG.and!(PEG.literal!("x"), hexDigit, hexDigit), PEG.and!(PEG.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), PEG.and!(PEG.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), PEG.any)), "Pegged.Char")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.or!(pegged.peg.and!(backslash, pegged.peg.or!(quote, doublequote, backquote, backslash, pegged.peg.literal!("-"), pegged.peg.literal!("["), pegged.peg.literal!("]"), pegged.peg.or!(pegged.peg.literal!("n"), pegged.peg.literal!("r"), pegged.peg.literal!("t")), pegged.peg.and!(pegged.peg.charRange!('0', '2'), pegged.peg.charRange!('0', '7'), pegged.peg.charRange!('0', '7')), pegged.peg.and!(pegged.peg.charRange!('0', '7'), pegged.peg.option!(pegged.peg.charRange!('0', '7'))), pegged.peg.and!(pegged.peg.literal!("x"), hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), pegged.peg.any)), "Pegged.Char"), "Char")(p); + return hooked!(PEG.defined!(PEG.fuse!(PEG.or!(PEG.and!(backslash, PEG.or!(quote, doublequote, backquote, backslash, PEG.literal!("-"), PEG.literal!("["), PEG.literal!("]"), PEG.or!(PEG.literal!("n"), PEG.literal!("r"), PEG.literal!("t")), PEG.and!(PEG.charRange!('0', '2'), PEG.charRange!('0', '7'), PEG.charRange!('0', '7')), PEG.and!(PEG.charRange!('0', '7'), PEG.option!(PEG.charRange!('0', '7'))), PEG.and!(PEG.literal!("x"), hexDigit, hexDigit), PEG.and!(PEG.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), PEG.and!(PEG.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), PEG.any)), "Pegged.Char"), "Char")(p); } } - static TParseTree Char(string s) + static ParseTree Char(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.or!(pegged.peg.and!(backslash, pegged.peg.or!(quote, doublequote, backquote, backslash, pegged.peg.literal!("-"), pegged.peg.literal!("["), pegged.peg.literal!("]"), pegged.peg.or!(pegged.peg.literal!("n"), pegged.peg.literal!("r"), pegged.peg.literal!("t")), pegged.peg.and!(pegged.peg.charRange!('0', '2'), pegged.peg.charRange!('0', '7'), pegged.peg.charRange!('0', '7')), pegged.peg.and!(pegged.peg.charRange!('0', '7'), pegged.peg.option!(pegged.peg.charRange!('0', '7'))), pegged.peg.and!(pegged.peg.literal!("x"), hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), pegged.peg.any)), "Pegged.Char")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.fuse!(PEG.or!(PEG.and!(backslash, PEG.or!(quote, doublequote, backquote, backslash, PEG.literal!("-"), PEG.literal!("["), PEG.literal!("]"), PEG.or!(PEG.literal!("n"), PEG.literal!("r"), PEG.literal!("t")), PEG.and!(PEG.charRange!('0', '2'), PEG.charRange!('0', '7'), PEG.charRange!('0', '7')), PEG.and!(PEG.charRange!('0', '7'), PEG.option!(PEG.charRange!('0', '7'))), PEG.and!(PEG.literal!("x"), hexDigit, hexDigit), PEG.and!(PEG.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), PEG.and!(PEG.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), PEG.any)), "Pegged.Char")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.or!(pegged.peg.and!(backslash, pegged.peg.or!(quote, doublequote, backquote, backslash, pegged.peg.literal!("-"), pegged.peg.literal!("["), pegged.peg.literal!("]"), pegged.peg.or!(pegged.peg.literal!("n"), pegged.peg.literal!("r"), pegged.peg.literal!("t")), pegged.peg.and!(pegged.peg.charRange!('0', '2'), pegged.peg.charRange!('0', '7'), pegged.peg.charRange!('0', '7')), pegged.peg.and!(pegged.peg.charRange!('0', '7'), pegged.peg.option!(pegged.peg.charRange!('0', '7'))), pegged.peg.and!(pegged.peg.literal!("x"), hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), pegged.peg.and!(pegged.peg.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), pegged.peg.any)), "Pegged.Char"), "Char")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.fuse!(PEG.or!(PEG.and!(backslash, PEG.or!(quote, doublequote, backquote, backslash, PEG.literal!("-"), PEG.literal!("["), PEG.literal!("]"), PEG.or!(PEG.literal!("n"), PEG.literal!("r"), PEG.literal!("t")), PEG.and!(PEG.charRange!('0', '2'), PEG.charRange!('0', '7'), PEG.charRange!('0', '7')), PEG.and!(PEG.charRange!('0', '7'), PEG.option!(PEG.charRange!('0', '7'))), PEG.and!(PEG.literal!("x"), hexDigit, hexDigit), PEG.and!(PEG.literal!("u"), hexDigit, hexDigit, hexDigit, hexDigit), PEG.and!(PEG.literal!("U"), hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit))), PEG.any)), "Pegged.Char"), "Char")(ParseTree("", false,[], s)); } } static string Char(GetName g) @@ -859,25 +870,25 @@ struct GenericPegged(TParseTree) return "Pegged.Char"; } - static TParseTree Arrow(TParseTree p) + static ParseTree Arrow(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow")(p); + return PEG.defined!(PEG.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow"), "Arrow")(p); + return hooked!(PEG.defined!(PEG.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow"), "Arrow")(p); } } - static TParseTree Arrow(string s) + static ParseTree Arrow(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow"), "Arrow")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(LEFTARROW, FUSEARROW, DISCARDARROW, KEEPARROW, DROPARROW, PROPAGATEARROW, ACTIONARROW, SPACEARROW), "Pegged.Arrow"), "Arrow")(ParseTree("", false,[], s)); } } static string Arrow(GetName g) @@ -885,25 +896,25 @@ struct GenericPegged(TParseTree) return "Pegged.Arrow"; } - static TParseTree LEFTARROW(TParseTree p) + static ParseTree LEFTARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<-"), Spacing), "Pegged.LEFTARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<-"), Spacing), "Pegged.LEFTARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<-"), Spacing), "Pegged.LEFTARROW"), "LEFTARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<-"), Spacing), "Pegged.LEFTARROW"), "LEFTARROW")(p); } } - static TParseTree LEFTARROW(string s) + static ParseTree LEFTARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<-"), Spacing), "Pegged.LEFTARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<-"), Spacing), "Pegged.LEFTARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<-"), Spacing), "Pegged.LEFTARROW"), "LEFTARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<-"), Spacing), "Pegged.LEFTARROW"), "LEFTARROW")(ParseTree("", false,[], s)); } } static string LEFTARROW(GetName g) @@ -911,25 +922,25 @@ struct GenericPegged(TParseTree) return "Pegged.LEFTARROW"; } - static TParseTree FUSEARROW(TParseTree p) + static ParseTree FUSEARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<~"), Spacing), "Pegged.FUSEARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<~"), Spacing), "Pegged.FUSEARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<~"), Spacing), "Pegged.FUSEARROW"), "FUSEARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<~"), Spacing), "Pegged.FUSEARROW"), "FUSEARROW")(p); } } - static TParseTree FUSEARROW(string s) + static ParseTree FUSEARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<~"), Spacing), "Pegged.FUSEARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<~"), Spacing), "Pegged.FUSEARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<~"), Spacing), "Pegged.FUSEARROW"), "FUSEARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<~"), Spacing), "Pegged.FUSEARROW"), "FUSEARROW")(ParseTree("", false,[], s)); } } static string FUSEARROW(GetName g) @@ -937,25 +948,25 @@ struct GenericPegged(TParseTree) return "Pegged.FUSEARROW"; } - static TParseTree DISCARDARROW(TParseTree p) + static ParseTree DISCARDARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<:"), Spacing), "Pegged.DISCARDARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<:"), Spacing), "Pegged.DISCARDARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<:"), Spacing), "Pegged.DISCARDARROW"), "DISCARDARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<:"), Spacing), "Pegged.DISCARDARROW"), "DISCARDARROW")(p); } } - static TParseTree DISCARDARROW(string s) + static ParseTree DISCARDARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<:"), Spacing), "Pegged.DISCARDARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<:"), Spacing), "Pegged.DISCARDARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<:"), Spacing), "Pegged.DISCARDARROW"), "DISCARDARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<:"), Spacing), "Pegged.DISCARDARROW"), "DISCARDARROW")(ParseTree("", false,[], s)); } } static string DISCARDARROW(GetName g) @@ -963,25 +974,25 @@ struct GenericPegged(TParseTree) return "Pegged.DISCARDARROW"; } - static TParseTree KEEPARROW(TParseTree p) + static ParseTree KEEPARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<^"), Spacing), "Pegged.KEEPARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<^"), Spacing), "Pegged.KEEPARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<^"), Spacing), "Pegged.KEEPARROW"), "KEEPARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<^"), Spacing), "Pegged.KEEPARROW"), "KEEPARROW")(p); } } - static TParseTree KEEPARROW(string s) + static ParseTree KEEPARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<^"), Spacing), "Pegged.KEEPARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<^"), Spacing), "Pegged.KEEPARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<^"), Spacing), "Pegged.KEEPARROW"), "KEEPARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<^"), Spacing), "Pegged.KEEPARROW"), "KEEPARROW")(ParseTree("", false,[], s)); } } static string KEEPARROW(GetName g) @@ -989,25 +1000,25 @@ struct GenericPegged(TParseTree) return "Pegged.KEEPARROW"; } - static TParseTree DROPARROW(TParseTree p) + static ParseTree DROPARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<;"), Spacing), "Pegged.DROPARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<;"), Spacing), "Pegged.DROPARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<;"), Spacing), "Pegged.DROPARROW"), "DROPARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<;"), Spacing), "Pegged.DROPARROW"), "DROPARROW")(p); } } - static TParseTree DROPARROW(string s) + static ParseTree DROPARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<;"), Spacing), "Pegged.DROPARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<;"), Spacing), "Pegged.DROPARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<;"), Spacing), "Pegged.DROPARROW"), "DROPARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<;"), Spacing), "Pegged.DROPARROW"), "DROPARROW")(ParseTree("", false,[], s)); } } static string DROPARROW(GetName g) @@ -1015,25 +1026,25 @@ struct GenericPegged(TParseTree) return "Pegged.DROPARROW"; } - static TParseTree PROPAGATEARROW(TParseTree p) + static ParseTree PROPAGATEARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW"), "PROPAGATEARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW"), "PROPAGATEARROW")(p); } } - static TParseTree PROPAGATEARROW(string s) + static ParseTree PROPAGATEARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW"), "PROPAGATEARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<%"), Spacing), "Pegged.PROPAGATEARROW"), "PROPAGATEARROW")(ParseTree("", false,[], s)); } } static string PROPAGATEARROW(GetName g) @@ -1041,25 +1052,25 @@ struct GenericPegged(TParseTree) return "Pegged.PROPAGATEARROW"; } - static TParseTree SPACEARROW(TParseTree p) + static ParseTree SPACEARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Spacing), "Pegged.SPACEARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<"), Spacing), "Pegged.SPACEARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Spacing), "Pegged.SPACEARROW"), "SPACEARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<"), Spacing), "Pegged.SPACEARROW"), "SPACEARROW")(p); } } - static TParseTree SPACEARROW(string s) + static ParseTree SPACEARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Spacing), "Pegged.SPACEARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<"), Spacing), "Pegged.SPACEARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Spacing), "Pegged.SPACEARROW"), "SPACEARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<"), Spacing), "Pegged.SPACEARROW"), "SPACEARROW")(ParseTree("", false,[], s)); } } static string SPACEARROW(GetName g) @@ -1067,25 +1078,25 @@ struct GenericPegged(TParseTree) return "Pegged.SPACEARROW"; } - static TParseTree ACTIONARROW(TParseTree p) + static ParseTree ACTIONARROW(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW")(p); + return PEG.defined!(PEG.and!(PEG.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW"), "ACTIONARROW")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW"), "ACTIONARROW")(p); } } - static TParseTree ACTIONARROW(string s) + static ParseTree ACTIONARROW(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW"), "ACTIONARROW")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("<"), Action, Spacing), "Pegged.ACTIONARROW"), "ACTIONARROW")(ParseTree("", false,[], s)); } } static string ACTIONARROW(GetName g) @@ -1093,25 +1104,25 @@ struct GenericPegged(TParseTree) return "Pegged.ACTIONARROW"; } - static TParseTree OR(TParseTree p) + static ParseTree OR(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/"), Spacing), "Pegged.OR")(p); + return PEG.defined!(PEG.and!(PEG.literal!("/"), Spacing), "Pegged.OR")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/"), Spacing), "Pegged.OR"), "OR")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("/"), Spacing), "Pegged.OR"), "OR")(p); } } - static TParseTree OR(string s) + static ParseTree OR(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/"), Spacing), "Pegged.OR")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("/"), Spacing), "Pegged.OR")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/"), Spacing), "Pegged.OR"), "OR")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("/"), Spacing), "Pegged.OR"), "OR")(ParseTree("", false,[], s)); } } static string OR(GetName g) @@ -1119,25 +1130,25 @@ struct GenericPegged(TParseTree) return "Pegged.OR"; } - static TParseTree LONGEST_OR(TParseTree p) + static ParseTree LONGEST_OR(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("|"), Spacing), "Pegged.LONGEST_OR")(p); + return PEG.defined!(PEG.and!(PEG.literal!("|"), Spacing), "Pegged.LONGEST_OR")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("|"), Spacing), "Pegged.LONGEST_OR"), "LONGEST_OR")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("|"), Spacing), "Pegged.LONGEST_OR"), "LONGEST_OR")(p); } } - static TParseTree LONGEST_OR(string s) + static ParseTree LONGEST_OR(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("|"), Spacing), "Pegged.LONGEST_OR")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("|"), Spacing), "Pegged.LONGEST_OR")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("|"), Spacing), "Pegged.LONGEST_OR"), "LONGEST_OR")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("|"), Spacing), "Pegged.LONGEST_OR"), "LONGEST_OR")(ParseTree("", false,[], s)); } } static string LONGEST_OR(GetName g) @@ -1145,25 +1156,25 @@ struct GenericPegged(TParseTree) return "Pegged.LONGEST_OR"; } - static TParseTree POS(TParseTree p) + static ParseTree POS(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("&"), Spacing), "Pegged.POS")(p); + return PEG.defined!(PEG.and!(PEG.literal!("&"), Spacing), "Pegged.POS")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("&"), Spacing), "Pegged.POS"), "POS")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("&"), Spacing), "Pegged.POS"), "POS")(p); } } - static TParseTree POS(string s) + static ParseTree POS(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("&"), Spacing), "Pegged.POS")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("&"), Spacing), "Pegged.POS")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("&"), Spacing), "Pegged.POS"), "POS")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("&"), Spacing), "Pegged.POS"), "POS")(ParseTree("", false,[], s)); } } static string POS(GetName g) @@ -1171,25 +1182,25 @@ struct GenericPegged(TParseTree) return "Pegged.POS"; } - static TParseTree NEG(TParseTree p) + static ParseTree NEG(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("!"), Spacing), "Pegged.NEG")(p); + return PEG.defined!(PEG.and!(PEG.literal!("!"), Spacing), "Pegged.NEG")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("!"), Spacing), "Pegged.NEG"), "NEG")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("!"), Spacing), "Pegged.NEG"), "NEG")(p); } } - static TParseTree NEG(string s) + static ParseTree NEG(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("!"), Spacing), "Pegged.NEG")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("!"), Spacing), "Pegged.NEG")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("!"), Spacing), "Pegged.NEG"), "NEG")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("!"), Spacing), "Pegged.NEG"), "NEG")(ParseTree("", false,[], s)); } } static string NEG(GetName g) @@ -1197,25 +1208,25 @@ struct GenericPegged(TParseTree) return "Pegged.NEG"; } - static TParseTree FUSE(TParseTree p) + static ParseTree FUSE(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("~"), Spacing), "Pegged.FUSE")(p); + return PEG.defined!(PEG.and!(PEG.literal!("~"), Spacing), "Pegged.FUSE")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("~"), Spacing), "Pegged.FUSE"), "FUSE")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("~"), Spacing), "Pegged.FUSE"), "FUSE")(p); } } - static TParseTree FUSE(string s) + static ParseTree FUSE(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("~"), Spacing), "Pegged.FUSE")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("~"), Spacing), "Pegged.FUSE")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("~"), Spacing), "Pegged.FUSE"), "FUSE")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("~"), Spacing), "Pegged.FUSE"), "FUSE")(ParseTree("", false,[], s)); } } static string FUSE(GetName g) @@ -1223,25 +1234,25 @@ struct GenericPegged(TParseTree) return "Pegged.FUSE"; } - static TParseTree DISCARD(TParseTree p) + static ParseTree DISCARD(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(":"), Spacing), "Pegged.DISCARD")(p); + return PEG.defined!(PEG.and!(PEG.literal!(":"), Spacing), "Pegged.DISCARD")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(":"), Spacing), "Pegged.DISCARD"), "DISCARD")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(":"), Spacing), "Pegged.DISCARD"), "DISCARD")(p); } } - static TParseTree DISCARD(string s) + static ParseTree DISCARD(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(":"), Spacing), "Pegged.DISCARD")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!(":"), Spacing), "Pegged.DISCARD")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(":"), Spacing), "Pegged.DISCARD"), "DISCARD")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(":"), Spacing), "Pegged.DISCARD"), "DISCARD")(ParseTree("", false,[], s)); } } static string DISCARD(GetName g) @@ -1249,25 +1260,25 @@ struct GenericPegged(TParseTree) return "Pegged.DISCARD"; } - static TParseTree KEEP(TParseTree p) + static ParseTree KEEP(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("^"), Spacing), "Pegged.KEEP")(p); + return PEG.defined!(PEG.and!(PEG.literal!("^"), Spacing), "Pegged.KEEP")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("^"), Spacing), "Pegged.KEEP"), "KEEP")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("^"), Spacing), "Pegged.KEEP"), "KEEP")(p); } } - static TParseTree KEEP(string s) + static ParseTree KEEP(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("^"), Spacing), "Pegged.KEEP")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("^"), Spacing), "Pegged.KEEP")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("^"), Spacing), "Pegged.KEEP"), "KEEP")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("^"), Spacing), "Pegged.KEEP"), "KEEP")(ParseTree("", false,[], s)); } } static string KEEP(GetName g) @@ -1275,25 +1286,25 @@ struct GenericPegged(TParseTree) return "Pegged.KEEP"; } - static TParseTree DROP(TParseTree p) + static ParseTree DROP(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(";"), Spacing), "Pegged.DROP")(p); + return PEG.defined!(PEG.and!(PEG.literal!(";"), Spacing), "Pegged.DROP")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(";"), Spacing), "Pegged.DROP"), "DROP")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(";"), Spacing), "Pegged.DROP"), "DROP")(p); } } - static TParseTree DROP(string s) + static ParseTree DROP(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(";"), Spacing), "Pegged.DROP")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!(";"), Spacing), "Pegged.DROP")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(";"), Spacing), "Pegged.DROP"), "DROP")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(";"), Spacing), "Pegged.DROP"), "DROP")(ParseTree("", false,[], s)); } } static string DROP(GetName g) @@ -1301,25 +1312,25 @@ struct GenericPegged(TParseTree) return "Pegged.DROP"; } - static TParseTree PROPAGATE(TParseTree p) + static ParseTree PROPAGATE(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("%"), Spacing), "Pegged.PROPAGATE")(p); + return PEG.defined!(PEG.and!(PEG.literal!("%"), Spacing), "Pegged.PROPAGATE")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("%"), Spacing), "Pegged.PROPAGATE"), "PROPAGATE")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("%"), Spacing), "Pegged.PROPAGATE"), "PROPAGATE")(p); } } - static TParseTree PROPAGATE(string s) + static ParseTree PROPAGATE(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("%"), Spacing), "Pegged.PROPAGATE")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("%"), Spacing), "Pegged.PROPAGATE")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("%"), Spacing), "Pegged.PROPAGATE"), "PROPAGATE")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("%"), Spacing), "Pegged.PROPAGATE"), "PROPAGATE")(ParseTree("", false,[], s)); } } static string PROPAGATE(GetName g) @@ -1327,25 +1338,25 @@ struct GenericPegged(TParseTree) return "Pegged.PROPAGATE"; } - static TParseTree OPTION(TParseTree p) + static ParseTree OPTION(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("?"), Spacing), "Pegged.OPTION")(p); + return PEG.defined!(PEG.and!(PEG.literal!("?"), Spacing), "Pegged.OPTION")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("?"), Spacing), "Pegged.OPTION"), "OPTION")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("?"), Spacing), "Pegged.OPTION"), "OPTION")(p); } } - static TParseTree OPTION(string s) + static ParseTree OPTION(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("?"), Spacing), "Pegged.OPTION")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("?"), Spacing), "Pegged.OPTION")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("?"), Spacing), "Pegged.OPTION"), "OPTION")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("?"), Spacing), "Pegged.OPTION"), "OPTION")(ParseTree("", false,[], s)); } } static string OPTION(GetName g) @@ -1353,25 +1364,25 @@ struct GenericPegged(TParseTree) return "Pegged.OPTION"; } - static TParseTree ZEROORMORE(TParseTree p) + static ParseTree ZEROORMORE(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("*"), Spacing), "Pegged.ZEROORMORE")(p); + return PEG.defined!(PEG.and!(PEG.literal!("*"), Spacing), "Pegged.ZEROORMORE")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("*"), Spacing), "Pegged.ZEROORMORE"), "ZEROORMORE")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("*"), Spacing), "Pegged.ZEROORMORE"), "ZEROORMORE")(p); } } - static TParseTree ZEROORMORE(string s) + static ParseTree ZEROORMORE(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("*"), Spacing), "Pegged.ZEROORMORE")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("*"), Spacing), "Pegged.ZEROORMORE")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("*"), Spacing), "Pegged.ZEROORMORE"), "ZEROORMORE")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("*"), Spacing), "Pegged.ZEROORMORE"), "ZEROORMORE")(ParseTree("", false,[], s)); } } static string ZEROORMORE(GetName g) @@ -1379,25 +1390,25 @@ struct GenericPegged(TParseTree) return "Pegged.ZEROORMORE"; } - static TParseTree ONEORMORE(TParseTree p) + static ParseTree ONEORMORE(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("+"), Spacing), "Pegged.ONEORMORE")(p); + return PEG.defined!(PEG.and!(PEG.literal!("+"), Spacing), "Pegged.ONEORMORE")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("+"), Spacing), "Pegged.ONEORMORE"), "ONEORMORE")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("+"), Spacing), "Pegged.ONEORMORE"), "ONEORMORE")(p); } } - static TParseTree ONEORMORE(string s) + static ParseTree ONEORMORE(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("+"), Spacing), "Pegged.ONEORMORE")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("+"), Spacing), "Pegged.ONEORMORE")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("+"), Spacing), "Pegged.ONEORMORE"), "ONEORMORE")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("+"), Spacing), "Pegged.ONEORMORE"), "ONEORMORE")(ParseTree("", false,[], s)); } } static string ONEORMORE(GetName g) @@ -1405,25 +1416,25 @@ struct GenericPegged(TParseTree) return "Pegged.ONEORMORE"; } - static TParseTree ACTIONOPEN(TParseTree p) + static ParseTree ACTIONOPEN(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("{"), Spacing), "Pegged.ACTIONOPEN")(p); + return PEG.defined!(PEG.and!(PEG.literal!("{"), Spacing), "Pegged.ACTIONOPEN")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("{"), Spacing), "Pegged.ACTIONOPEN"), "ACTIONOPEN")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("{"), Spacing), "Pegged.ACTIONOPEN"), "ACTIONOPEN")(p); } } - static TParseTree ACTIONOPEN(string s) + static ParseTree ACTIONOPEN(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("{"), Spacing), "Pegged.ACTIONOPEN")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("{"), Spacing), "Pegged.ACTIONOPEN")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("{"), Spacing), "Pegged.ACTIONOPEN"), "ACTIONOPEN")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("{"), Spacing), "Pegged.ACTIONOPEN"), "ACTIONOPEN")(ParseTree("", false,[], s)); } } static string ACTIONOPEN(GetName g) @@ -1431,25 +1442,25 @@ struct GenericPegged(TParseTree) return "Pegged.ACTIONOPEN"; } - static TParseTree ACTIONCLOSE(TParseTree p) + static ParseTree ACTIONCLOSE(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("}"), Spacing), "Pegged.ACTIONCLOSE")(p); + return PEG.defined!(PEG.and!(PEG.literal!("}"), Spacing), "Pegged.ACTIONCLOSE")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("}"), Spacing), "Pegged.ACTIONCLOSE"), "ACTIONCLOSE")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("}"), Spacing), "Pegged.ACTIONCLOSE"), "ACTIONCLOSE")(p); } } - static TParseTree ACTIONCLOSE(string s) + static ParseTree ACTIONCLOSE(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("}"), Spacing), "Pegged.ACTIONCLOSE")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("}"), Spacing), "Pegged.ACTIONCLOSE")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("}"), Spacing), "Pegged.ACTIONCLOSE"), "ACTIONCLOSE")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("}"), Spacing), "Pegged.ACTIONCLOSE"), "ACTIONCLOSE")(ParseTree("", false,[], s)); } } static string ACTIONCLOSE(GetName g) @@ -1457,25 +1468,25 @@ struct GenericPegged(TParseTree) return "Pegged.ACTIONCLOSE"; } - static TParseTree SEPARATOR(TParseTree p) + static ParseTree SEPARATOR(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(","), Spacing), "Pegged.SEPARATOR")(p); + return PEG.defined!(PEG.and!(PEG.literal!(","), Spacing), "Pegged.SEPARATOR")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(","), Spacing), "Pegged.SEPARATOR"), "SEPARATOR")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(","), Spacing), "Pegged.SEPARATOR"), "SEPARATOR")(p); } } - static TParseTree SEPARATOR(string s) + static ParseTree SEPARATOR(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(","), Spacing), "Pegged.SEPARATOR")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!(","), Spacing), "Pegged.SEPARATOR")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(","), Spacing), "Pegged.SEPARATOR"), "SEPARATOR")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(","), Spacing), "Pegged.SEPARATOR"), "SEPARATOR")(ParseTree("", false,[], s)); } } static string SEPARATOR(GetName g) @@ -1483,25 +1494,25 @@ struct GenericPegged(TParseTree) return "Pegged.SEPARATOR"; } - static TParseTree ASSIGN(TParseTree p) + static ParseTree ASSIGN(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("="), Spacing), "Pegged.ASSIGN")(p); + return PEG.defined!(PEG.and!(PEG.literal!("="), Spacing), "Pegged.ASSIGN")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("="), Spacing), "Pegged.ASSIGN"), "ASSIGN")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("="), Spacing), "Pegged.ASSIGN"), "ASSIGN")(p); } } - static TParseTree ASSIGN(string s) + static ParseTree ASSIGN(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("="), Spacing), "Pegged.ASSIGN")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("="), Spacing), "Pegged.ASSIGN")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("="), Spacing), "Pegged.ASSIGN"), "ASSIGN")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("="), Spacing), "Pegged.ASSIGN"), "ASSIGN")(ParseTree("", false,[], s)); } } static string ASSIGN(GetName g) @@ -1509,25 +1520,25 @@ struct GenericPegged(TParseTree) return "Pegged.ASSIGN"; } - static TParseTree NAMESEP(TParseTree p) + static ParseTree NAMESEP(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.literal!("."), "Pegged.NAMESEP")(p); + return PEG.defined!(PEG.literal!("."), "Pegged.NAMESEP")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.literal!("."), "Pegged.NAMESEP"), "NAMESEP")(p); + return hooked!(PEG.defined!(PEG.literal!("."), "Pegged.NAMESEP"), "NAMESEP")(p); } } - static TParseTree NAMESEP(string s) + static ParseTree NAMESEP(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.literal!("."), "Pegged.NAMESEP")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.literal!("."), "Pegged.NAMESEP")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.literal!("."), "Pegged.NAMESEP"), "NAMESEP")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.literal!("."), "Pegged.NAMESEP"), "NAMESEP")(ParseTree("", false,[], s)); } } static string NAMESEP(GetName g) @@ -1535,25 +1546,25 @@ struct GenericPegged(TParseTree) return "Pegged.NAMESEP"; } - static TParseTree OPEN(TParseTree p) + static ParseTree OPEN(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("("), Spacing), "Pegged.OPEN")(p); + return PEG.defined!(PEG.and!(PEG.literal!("("), Spacing), "Pegged.OPEN")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("("), Spacing), "Pegged.OPEN"), "OPEN")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("("), Spacing), "Pegged.OPEN"), "OPEN")(p); } } - static TParseTree OPEN(string s) + static ParseTree OPEN(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("("), Spacing), "Pegged.OPEN")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("("), Spacing), "Pegged.OPEN")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("("), Spacing), "Pegged.OPEN"), "OPEN")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("("), Spacing), "Pegged.OPEN"), "OPEN")(ParseTree("", false,[], s)); } } static string OPEN(GetName g) @@ -1561,25 +1572,25 @@ struct GenericPegged(TParseTree) return "Pegged.OPEN"; } - static TParseTree CLOSE(TParseTree p) + static ParseTree CLOSE(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(")"), Spacing), "Pegged.CLOSE")(p); + return PEG.defined!(PEG.and!(PEG.literal!(")"), Spacing), "Pegged.CLOSE")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(")"), Spacing), "Pegged.CLOSE"), "CLOSE")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(")"), Spacing), "Pegged.CLOSE"), "CLOSE")(p); } } - static TParseTree CLOSE(string s) + static ParseTree CLOSE(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(")"), Spacing), "Pegged.CLOSE")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!(")"), Spacing), "Pegged.CLOSE")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!(")"), Spacing), "Pegged.CLOSE"), "CLOSE")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!(")"), Spacing), "Pegged.CLOSE"), "CLOSE")(ParseTree("", false,[], s)); } } static string CLOSE(GetName g) @@ -1587,25 +1598,25 @@ struct GenericPegged(TParseTree) return "Pegged.CLOSE"; } - static TParseTree ANY(TParseTree p) + static ParseTree ANY(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("."), Spacing), "Pegged.ANY")(p); + return PEG.defined!(PEG.and!(PEG.literal!("."), Spacing), "Pegged.ANY")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("."), Spacing), "Pegged.ANY"), "ANY")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("."), Spacing), "Pegged.ANY"), "ANY")(p); } } - static TParseTree ANY(string s) + static ParseTree ANY(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("."), Spacing), "Pegged.ANY")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("."), Spacing), "Pegged.ANY")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("."), Spacing), "Pegged.ANY"), "ANY")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("."), Spacing), "Pegged.ANY"), "ANY")(ParseTree("", false,[], s)); } } static string ANY(GetName g) @@ -1613,25 +1624,25 @@ struct GenericPegged(TParseTree) return "Pegged.ANY"; } - static TParseTree Spacing(TParseTree p) + static ParseTree Spacing(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.discard!(pegged.peg.zeroOrMore!(pegged.peg.or!(blank, Comment))), "Pegged.Spacing")(p); + return PEG.defined!(PEG.discard!(PEG.zeroOrMore!(PEG.or!(blank, Comment))), "Pegged.Spacing")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.discard!(pegged.peg.zeroOrMore!(pegged.peg.or!(blank, Comment))), "Pegged.Spacing"), "Spacing")(p); + return hooked!(PEG.defined!(PEG.discard!(PEG.zeroOrMore!(PEG.or!(blank, Comment))), "Pegged.Spacing"), "Spacing")(p); } } - static TParseTree Spacing(string s) + static ParseTree Spacing(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.discard!(pegged.peg.zeroOrMore!(pegged.peg.or!(blank, Comment))), "Pegged.Spacing")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.discard!(PEG.zeroOrMore!(PEG.or!(blank, Comment))), "Pegged.Spacing")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.discard!(pegged.peg.zeroOrMore!(pegged.peg.or!(blank, Comment))), "Pegged.Spacing"), "Spacing")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.discard!(PEG.zeroOrMore!(PEG.or!(blank, Comment))), "Pegged.Spacing"), "Spacing")(ParseTree("", false,[], s)); } } static string Spacing(GetName g) @@ -1639,25 +1650,25 @@ struct GenericPegged(TParseTree) return "Pegged.Spacing"; } - static TParseTree Comment(TParseTree p) + static ParseTree Comment(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("#"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(eol), pegged.peg.any)), pegged.peg.discard!(eol)), "Pegged.Comment")(p); + return PEG.defined!(PEG.and!(PEG.literal!("#"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(eol), PEG.any)), PEG.discard!(eol)), "Pegged.Comment")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("#"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(eol), pegged.peg.any)), pegged.peg.discard!(eol)), "Pegged.Comment"), "Comment")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("#"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(eol), PEG.any)), PEG.discard!(eol)), "Pegged.Comment"), "Comment")(p); } } - static TParseTree Comment(string s) + static ParseTree Comment(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("#"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(eol), pegged.peg.any)), pegged.peg.discard!(eol)), "Pegged.Comment")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("#"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(eol), PEG.any)), PEG.discard!(eol)), "Pegged.Comment")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("#"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(eol), pegged.peg.any)), pegged.peg.discard!(eol)), "Pegged.Comment"), "Comment")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("#"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(eol), PEG.any)), PEG.discard!(eol)), "Pegged.Comment"), "Comment")(ParseTree("", false,[], s)); } } static string Comment(GetName g) @@ -1665,25 +1676,25 @@ struct GenericPegged(TParseTree) return "Pegged.Comment"; } - static TParseTree Space(TParseTree p) + static ParseTree Space(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(spacing, pegged.peg.literal!("\\t"), pegged.peg.literal!("\\n"), pegged.peg.literal!("\\r")), "Pegged.Space")(p); + return PEG.defined!(PEG.or!(spacing, PEG.literal!("\\t"), PEG.literal!("\\n"), PEG.literal!("\\r")), "Pegged.Space")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(spacing, pegged.peg.literal!("\\t"), pegged.peg.literal!("\\n"), pegged.peg.literal!("\\r")), "Pegged.Space"), "Space")(p); + return hooked!(PEG.defined!(PEG.or!(spacing, PEG.literal!("\\t"), PEG.literal!("\\n"), PEG.literal!("\\r")), "Pegged.Space"), "Space")(p); } } - static TParseTree Space(string s) + static ParseTree Space(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(spacing, pegged.peg.literal!("\\t"), pegged.peg.literal!("\\n"), pegged.peg.literal!("\\r")), "Pegged.Space")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(spacing, PEG.literal!("\\t"), PEG.literal!("\\n"), PEG.literal!("\\r")), "Pegged.Space")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(spacing, pegged.peg.literal!("\\t"), pegged.peg.literal!("\\n"), pegged.peg.literal!("\\r")), "Pegged.Space"), "Space")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(spacing, PEG.literal!("\\t"), PEG.literal!("\\n"), PEG.literal!("\\r")), "Pegged.Space"), "Space")(ParseTree("", false,[], s)); } } static string Space(GetName g) @@ -1691,25 +1702,25 @@ struct GenericPegged(TParseTree) return "Pegged.Space"; } - static TParseTree Action(TParseTree p) + static ParseTree Action(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(ACTIONOPEN), Spacing, pegged.peg.and!(pegged.peg.or!(Lambda, qualifiedIdentifier), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), pegged.peg.or!(Lambda, qualifiedIdentifier)))), Spacing, pegged.peg.discard!(ACTIONCLOSE)), "Pegged.Action")(p); + return PEG.defined!(PEG.and!(PEG.discard!(ACTIONOPEN), Spacing, PEG.and!(PEG.or!(Lambda, qualifiedIdentifier), PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), PEG.or!(Lambda, qualifiedIdentifier)))), Spacing, PEG.discard!(ACTIONCLOSE)), "Pegged.Action")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(ACTIONOPEN), Spacing, pegged.peg.and!(pegged.peg.or!(Lambda, qualifiedIdentifier), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), pegged.peg.or!(Lambda, qualifiedIdentifier)))), Spacing, pegged.peg.discard!(ACTIONCLOSE)), "Pegged.Action"), "Action")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(ACTIONOPEN), Spacing, PEG.and!(PEG.or!(Lambda, qualifiedIdentifier), PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), PEG.or!(Lambda, qualifiedIdentifier)))), Spacing, PEG.discard!(ACTIONCLOSE)), "Pegged.Action"), "Action")(p); } } - static TParseTree Action(string s) + static ParseTree Action(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(ACTIONOPEN), Spacing, pegged.peg.and!(pegged.peg.or!(Lambda, qualifiedIdentifier), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), pegged.peg.or!(Lambda, qualifiedIdentifier)))), Spacing, pegged.peg.discard!(ACTIONCLOSE)), "Pegged.Action")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.discard!(ACTIONOPEN), Spacing, PEG.and!(PEG.or!(Lambda, qualifiedIdentifier), PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), PEG.or!(Lambda, qualifiedIdentifier)))), Spacing, PEG.discard!(ACTIONCLOSE)), "Pegged.Action")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.discard!(ACTIONOPEN), Spacing, pegged.peg.and!(pegged.peg.or!(Lambda, qualifiedIdentifier), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(SEPARATOR), pegged.peg.or!(Lambda, qualifiedIdentifier)))), Spacing, pegged.peg.discard!(ACTIONCLOSE)), "Pegged.Action"), "Action")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.discard!(ACTIONOPEN), Spacing, PEG.and!(PEG.or!(Lambda, qualifiedIdentifier), PEG.zeroOrMore!(PEG.and!(PEG.discard!(SEPARATOR), PEG.or!(Lambda, qualifiedIdentifier)))), Spacing, PEG.discard!(ACTIONCLOSE)), "Pegged.Action"), "Action")(ParseTree("", false,[], s)); } } static string Action(GetName g) @@ -1717,25 +1728,25 @@ struct GenericPegged(TParseTree) return "Pegged.Action"; } - static TParseTree Lambda(TParseTree p) + static ParseTree Lambda(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(ACTIONCLOSE, SEPARATOR)), pegged.peg.or!(LambdaItems, NestedList!(pegged.peg.literal!("{"), LambdaItems, pegged.peg.literal!("}")), pegged.peg.any)))), "Pegged.Lambda")(p); + return PEG.defined!(PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(ACTIONCLOSE, SEPARATOR)), PEG.or!(LambdaItems, NestedList!(PEG.literal!("{"), LambdaItems, PEG.literal!("}")), PEG.any)))), "Pegged.Lambda")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(ACTIONCLOSE, SEPARATOR)), pegged.peg.or!(LambdaItems, NestedList!(pegged.peg.literal!("{"), LambdaItems, pegged.peg.literal!("}")), pegged.peg.any)))), "Pegged.Lambda"), "Lambda")(p); + return hooked!(PEG.defined!(PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(ACTIONCLOSE, SEPARATOR)), PEG.or!(LambdaItems, NestedList!(PEG.literal!("{"), LambdaItems, PEG.literal!("}")), PEG.any)))), "Pegged.Lambda"), "Lambda")(p); } } - static TParseTree Lambda(string s) + static ParseTree Lambda(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(ACTIONCLOSE, SEPARATOR)), pegged.peg.or!(LambdaItems, NestedList!(pegged.peg.literal!("{"), LambdaItems, pegged.peg.literal!("}")), pegged.peg.any)))), "Pegged.Lambda")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(ACTIONCLOSE, SEPARATOR)), PEG.or!(LambdaItems, NestedList!(PEG.literal!("{"), LambdaItems, PEG.literal!("}")), PEG.any)))), "Pegged.Lambda")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.fuse!(pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(ACTIONCLOSE, SEPARATOR)), pegged.peg.or!(LambdaItems, NestedList!(pegged.peg.literal!("{"), LambdaItems, pegged.peg.literal!("}")), pegged.peg.any)))), "Pegged.Lambda"), "Lambda")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.fuse!(PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(ACTIONCLOSE, SEPARATOR)), PEG.or!(LambdaItems, NestedList!(PEG.literal!("{"), LambdaItems, PEG.literal!("}")), PEG.any)))), "Pegged.Lambda"), "Lambda")(ParseTree("", false,[], s)); } } static string Lambda(GetName g) @@ -1743,25 +1754,25 @@ struct GenericPegged(TParseTree) return "Pegged.Lambda"; } - static TParseTree LambdaItems(TParseTree p) + static ParseTree LambdaItems(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.fuse!(DComment), pegged.peg.fuse!(DString), pegged.peg.fuse!(DParamList)), "Pegged.LambdaItems")(p); + return PEG.defined!(PEG.or!(PEG.fuse!(DComment), PEG.fuse!(DString), PEG.fuse!(DParamList)), "Pegged.LambdaItems")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.fuse!(DComment), pegged.peg.fuse!(DString), pegged.peg.fuse!(DParamList)), "Pegged.LambdaItems"), "LambdaItems")(p); + return hooked!(PEG.defined!(PEG.or!(PEG.fuse!(DComment), PEG.fuse!(DString), PEG.fuse!(DParamList)), "Pegged.LambdaItems"), "LambdaItems")(p); } } - static TParseTree LambdaItems(string s) + static ParseTree LambdaItems(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.fuse!(DComment), pegged.peg.fuse!(DString), pegged.peg.fuse!(DParamList)), "Pegged.LambdaItems")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(PEG.fuse!(DComment), PEG.fuse!(DString), PEG.fuse!(DParamList)), "Pegged.LambdaItems")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.fuse!(DComment), pegged.peg.fuse!(DString), pegged.peg.fuse!(DParamList)), "Pegged.LambdaItems"), "LambdaItems")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(PEG.fuse!(DComment), PEG.fuse!(DString), PEG.fuse!(DParamList)), "Pegged.LambdaItems"), "LambdaItems")(ParseTree("", false,[], s)); } } static string LambdaItems(GetName g) @@ -1769,25 +1780,25 @@ struct GenericPegged(TParseTree) return "Pegged.LambdaItems"; } - static TParseTree DString(TParseTree p) + static ParseTree DString(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString")(p); + return PEG.defined!(PEG.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString"), "DString")(p); + return hooked!(PEG.defined!(PEG.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString"), "DString")(p); } } - static TParseTree DString(string s) + static ParseTree DString(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString"), "DString")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(WYSString, DBQString, TKNString, DLMString), "Pegged.DString"), "DString")(ParseTree("", false,[], s)); } } static string DString(GetName g) @@ -1795,25 +1806,25 @@ struct GenericPegged(TParseTree) return "Pegged.DString"; } - static TParseTree WYSString(TParseTree p) + static ParseTree WYSString(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(pegged.peg.literal!("r"), doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), pegged.peg.any)), doublequote), pegged.peg.and!(backquote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(backquote), pegged.peg.any)), backquote)), "Pegged.WYSString")(p); + return PEG.defined!(PEG.or!(PEG.and!(PEG.literal!("r"), doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), PEG.any)), doublequote), PEG.and!(backquote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(backquote), PEG.any)), backquote)), "Pegged.WYSString")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(pegged.peg.literal!("r"), doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), pegged.peg.any)), doublequote), pegged.peg.and!(backquote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(backquote), pegged.peg.any)), backquote)), "Pegged.WYSString"), "WYSString")(p); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(PEG.literal!("r"), doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), PEG.any)), doublequote), PEG.and!(backquote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(backquote), PEG.any)), backquote)), "Pegged.WYSString"), "WYSString")(p); } } - static TParseTree WYSString(string s) + static ParseTree WYSString(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(pegged.peg.literal!("r"), doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), pegged.peg.any)), doublequote), pegged.peg.and!(backquote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(backquote), pegged.peg.any)), backquote)), "Pegged.WYSString")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(PEG.and!(PEG.literal!("r"), doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), PEG.any)), doublequote), PEG.and!(backquote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(backquote), PEG.any)), backquote)), "Pegged.WYSString")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(pegged.peg.and!(pegged.peg.literal!("r"), doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), pegged.peg.any)), doublequote), pegged.peg.and!(backquote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(backquote), pegged.peg.any)), backquote)), "Pegged.WYSString"), "WYSString")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(PEG.and!(PEG.literal!("r"), doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), PEG.any)), doublequote), PEG.and!(backquote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(backquote), PEG.any)), backquote)), "Pegged.WYSString"), "WYSString")(ParseTree("", false,[], s)); } } static string WYSString(GetName g) @@ -1821,25 +1832,25 @@ struct GenericPegged(TParseTree) return "Pegged.WYSString"; } - static TParseTree DBQString(TParseTree p) + static ParseTree DBQString(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString")(p); + return PEG.defined!(PEG.and!(doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString"), "DBQString")(p); + return hooked!(PEG.defined!(PEG.and!(doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString"), "DBQString")(p); } } - static TParseTree DBQString(string s) + static ParseTree DBQString(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(doublequote, pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString"), "DBQString")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(doublequote, PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(doublequote), Char)), doublequote), "Pegged.DBQString"), "DBQString")(ParseTree("", false,[], s)); } } static string DBQString(GetName g) @@ -1847,25 +1858,25 @@ struct GenericPegged(TParseTree) return "Pegged.DBQString"; } - static TParseTree TKNString(TParseTree p) + static ParseTree TKNString(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("q{")), pegged.peg.and!(pegged.peg.literal!("q"), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}")))), "Pegged.TKNString")(p); + return PEG.defined!(PEG.and!(PEG.posLookahead!(PEG.literal!("q{")), PEG.and!(PEG.literal!("q"), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}")))), "Pegged.TKNString")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("q{")), pegged.peg.and!(pegged.peg.literal!("q"), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}")))), "Pegged.TKNString"), "TKNString")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.posLookahead!(PEG.literal!("q{")), PEG.and!(PEG.literal!("q"), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}")))), "Pegged.TKNString"), "TKNString")(p); } } - static TParseTree TKNString(string s) + static ParseTree TKNString(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("q{")), pegged.peg.and!(pegged.peg.literal!("q"), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}")))), "Pegged.TKNString")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.posLookahead!(PEG.literal!("q{")), PEG.and!(PEG.literal!("q"), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}")))), "Pegged.TKNString")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("q{")), pegged.peg.and!(pegged.peg.literal!("q"), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}")))), "Pegged.TKNString"), "TKNString")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.posLookahead!(PEG.literal!("q{")), PEG.and!(PEG.literal!("q"), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}")))), "Pegged.TKNString"), "TKNString")(ParseTree("", false,[], s)); } } static string TKNString(GetName g) @@ -1873,25 +1884,25 @@ struct GenericPegged(TParseTree) return "Pegged.TKNString"; } - static TParseTree DLMString(TParseTree p) + static ParseTree DLMString(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.and!(pegged.peg.literal!("q"), doublequote), pegged.peg.or!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("{")), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("[")), NestedList!(pegged.peg.literal!("["), DString, pegged.peg.literal!("]"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("(")), NestedList!(pegged.peg.literal!("("), DString, pegged.peg.literal!(")"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("<")), NestedList!(pegged.peg.literal!("<"), DString, pegged.peg.literal!(">")))), doublequote), "Pegged.DLMString")(p); + return PEG.defined!(PEG.and!(PEG.and!(PEG.literal!("q"), doublequote), PEG.or!(PEG.and!(PEG.posLookahead!(PEG.literal!("{")), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}"))), PEG.and!(PEG.posLookahead!(PEG.literal!("[")), NestedList!(PEG.literal!("["), DString, PEG.literal!("]"))), PEG.and!(PEG.posLookahead!(PEG.literal!("(")), NestedList!(PEG.literal!("("), DString, PEG.literal!(")"))), PEG.and!(PEG.posLookahead!(PEG.literal!("<")), NestedList!(PEG.literal!("<"), DString, PEG.literal!(">")))), doublequote), "Pegged.DLMString")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.and!(pegged.peg.literal!("q"), doublequote), pegged.peg.or!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("{")), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("[")), NestedList!(pegged.peg.literal!("["), DString, pegged.peg.literal!("]"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("(")), NestedList!(pegged.peg.literal!("("), DString, pegged.peg.literal!(")"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("<")), NestedList!(pegged.peg.literal!("<"), DString, pegged.peg.literal!(">")))), doublequote), "Pegged.DLMString"), "DLMString")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.and!(PEG.literal!("q"), doublequote), PEG.or!(PEG.and!(PEG.posLookahead!(PEG.literal!("{")), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}"))), PEG.and!(PEG.posLookahead!(PEG.literal!("[")), NestedList!(PEG.literal!("["), DString, PEG.literal!("]"))), PEG.and!(PEG.posLookahead!(PEG.literal!("(")), NestedList!(PEG.literal!("("), DString, PEG.literal!(")"))), PEG.and!(PEG.posLookahead!(PEG.literal!("<")), NestedList!(PEG.literal!("<"), DString, PEG.literal!(">")))), doublequote), "Pegged.DLMString"), "DLMString")(p); } } - static TParseTree DLMString(string s) + static ParseTree DLMString(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.and!(pegged.peg.literal!("q"), doublequote), pegged.peg.or!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("{")), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("[")), NestedList!(pegged.peg.literal!("["), DString, pegged.peg.literal!("]"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("(")), NestedList!(pegged.peg.literal!("("), DString, pegged.peg.literal!(")"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("<")), NestedList!(pegged.peg.literal!("<"), DString, pegged.peg.literal!(">")))), doublequote), "Pegged.DLMString")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.and!(PEG.literal!("q"), doublequote), PEG.or!(PEG.and!(PEG.posLookahead!(PEG.literal!("{")), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}"))), PEG.and!(PEG.posLookahead!(PEG.literal!("[")), NestedList!(PEG.literal!("["), DString, PEG.literal!("]"))), PEG.and!(PEG.posLookahead!(PEG.literal!("(")), NestedList!(PEG.literal!("("), DString, PEG.literal!(")"))), PEG.and!(PEG.posLookahead!(PEG.literal!("<")), NestedList!(PEG.literal!("<"), DString, PEG.literal!(">")))), doublequote), "Pegged.DLMString")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.and!(pegged.peg.literal!("q"), doublequote), pegged.peg.or!(pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("{")), NestedList!(pegged.peg.literal!("{"), DString, pegged.peg.literal!("}"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("[")), NestedList!(pegged.peg.literal!("["), DString, pegged.peg.literal!("]"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("(")), NestedList!(pegged.peg.literal!("("), DString, pegged.peg.literal!(")"))), pegged.peg.and!(pegged.peg.posLookahead!(pegged.peg.literal!("<")), NestedList!(pegged.peg.literal!("<"), DString, pegged.peg.literal!(">")))), doublequote), "Pegged.DLMString"), "DLMString")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.and!(PEG.literal!("q"), doublequote), PEG.or!(PEG.and!(PEG.posLookahead!(PEG.literal!("{")), NestedList!(PEG.literal!("{"), DString, PEG.literal!("}"))), PEG.and!(PEG.posLookahead!(PEG.literal!("[")), NestedList!(PEG.literal!("["), DString, PEG.literal!("]"))), PEG.and!(PEG.posLookahead!(PEG.literal!("(")), NestedList!(PEG.literal!("("), DString, PEG.literal!(")"))), PEG.and!(PEG.posLookahead!(PEG.literal!("<")), NestedList!(PEG.literal!("<"), DString, PEG.literal!(">")))), doublequote), "Pegged.DLMString"), "DLMString")(ParseTree("", false,[], s)); } } static string DLMString(GetName g) @@ -1899,25 +1910,25 @@ struct GenericPegged(TParseTree) return "Pegged.DLMString"; } - static TParseTree DComment(TParseTree p) + static ParseTree DComment(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment")(p); + return PEG.defined!(PEG.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment"), "DComment")(p); + return hooked!(PEG.defined!(PEG.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment"), "DComment")(p); } } - static TParseTree DComment(string s) + static ParseTree DComment(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment"), "DComment")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.or!(DLineComment, DBlockComment, DNestingBlockComment), "Pegged.DComment"), "DComment")(ParseTree("", false,[], s)); } } static string DComment(GetName g) @@ -1925,25 +1936,25 @@ struct GenericPegged(TParseTree) return "Pegged.DComment"; } - static TParseTree DLineComment(TParseTree p) + static ParseTree DLineComment(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("//"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(endOfLine), pegged.peg.any)), endOfLine), "Pegged.DLineComment")(p); + return PEG.defined!(PEG.and!(PEG.literal!("//"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(endOfLine), PEG.any)), endOfLine), "Pegged.DLineComment")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("//"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(endOfLine), pegged.peg.any)), endOfLine), "Pegged.DLineComment"), "DLineComment")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("//"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(endOfLine), PEG.any)), endOfLine), "Pegged.DLineComment"), "DLineComment")(p); } } - static TParseTree DLineComment(string s) + static ParseTree DLineComment(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("//"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(endOfLine), pegged.peg.any)), endOfLine), "Pegged.DLineComment")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("//"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(endOfLine), PEG.any)), endOfLine), "Pegged.DLineComment")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("//"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(endOfLine), pegged.peg.any)), endOfLine), "Pegged.DLineComment"), "DLineComment")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("//"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(endOfLine), PEG.any)), endOfLine), "Pegged.DLineComment"), "DLineComment")(ParseTree("", false,[], s)); } } static string DLineComment(GetName g) @@ -1951,25 +1962,25 @@ struct GenericPegged(TParseTree) return "Pegged.DLineComment"; } - static TParseTree DBlockComment(TParseTree p) + static ParseTree DBlockComment(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/*"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("*/")), pegged.peg.any)), pegged.peg.literal!("*/")), "Pegged.DBlockComment")(p); + return PEG.defined!(PEG.and!(PEG.literal!("/*"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("*/")), PEG.any)), PEG.literal!("*/")), "Pegged.DBlockComment")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/*"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("*/")), pegged.peg.any)), pegged.peg.literal!("*/")), "Pegged.DBlockComment"), "DBlockComment")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("/*"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("*/")), PEG.any)), PEG.literal!("*/")), "Pegged.DBlockComment"), "DBlockComment")(p); } } - static TParseTree DBlockComment(string s) + static ParseTree DBlockComment(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/*"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("*/")), pegged.peg.any)), pegged.peg.literal!("*/")), "Pegged.DBlockComment")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.literal!("/*"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("*/")), PEG.any)), PEG.literal!("*/")), "Pegged.DBlockComment")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("/*"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("*/")), pegged.peg.any)), pegged.peg.literal!("*/")), "Pegged.DBlockComment"), "DBlockComment")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.literal!("/*"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("*/")), PEG.any)), PEG.literal!("*/")), "Pegged.DBlockComment"), "DBlockComment")(ParseTree("", false,[], s)); } } static string DBlockComment(GetName g) @@ -1977,25 +1988,25 @@ struct GenericPegged(TParseTree) return "Pegged.DBlockComment"; } - static TParseTree DNestingBlockComment(TParseTree p) + static ParseTree DNestingBlockComment(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(NestedList!(pegged.peg.literal!("/+"), pegged.peg.literal!("+/")), "Pegged.DNestingBlockComment")(p); + return PEG.defined!(NestedList!(PEG.literal!("/+"), PEG.literal!("+/")), "Pegged.DNestingBlockComment")(p); } else { - return hooked!(pegged.peg.defined!(NestedList!(pegged.peg.literal!("/+"), pegged.peg.literal!("+/")), "Pegged.DNestingBlockComment"), "DNestingBlockComment")(p); + return hooked!(PEG.defined!(NestedList!(PEG.literal!("/+"), PEG.literal!("+/")), "Pegged.DNestingBlockComment"), "DNestingBlockComment")(p); } } - static TParseTree DNestingBlockComment(string s) + static ParseTree DNestingBlockComment(string s) { if(__ctfe) - return pegged.peg.defined!(NestedList!(pegged.peg.literal!("/+"), pegged.peg.literal!("+/")), "Pegged.DNestingBlockComment")(TParseTree("", false,[], s)); + return PEG.defined!(NestedList!(PEG.literal!("/+"), PEG.literal!("+/")), "Pegged.DNestingBlockComment")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(NestedList!(pegged.peg.literal!("/+"), pegged.peg.literal!("+/")), "Pegged.DNestingBlockComment"), "DNestingBlockComment")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(NestedList!(PEG.literal!("/+"), PEG.literal!("+/")), "Pegged.DNestingBlockComment"), "DNestingBlockComment")(ParseTree("", false,[], s)); } } static string DNestingBlockComment(GetName g) @@ -2003,25 +2014,25 @@ struct GenericPegged(TParseTree) return "Pegged.DNestingBlockComment"; } - static TParseTree DParamList(TParseTree p) + static ParseTree DParamList(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(NestedList!(pegged.peg.literal!("("), pegged.peg.literal!(")")), "Pegged.DParamList")(p); + return PEG.defined!(NestedList!(PEG.literal!("("), PEG.literal!(")")), "Pegged.DParamList")(p); } else { - return hooked!(pegged.peg.defined!(NestedList!(pegged.peg.literal!("("), pegged.peg.literal!(")")), "Pegged.DParamList"), "DParamList")(p); + return hooked!(PEG.defined!(NestedList!(PEG.literal!("("), PEG.literal!(")")), "Pegged.DParamList"), "DParamList")(p); } } - static TParseTree DParamList(string s) + static ParseTree DParamList(string s) { if(__ctfe) - return pegged.peg.defined!(NestedList!(pegged.peg.literal!("("), pegged.peg.literal!(")")), "Pegged.DParamList")(TParseTree("", false,[], s)); + return PEG.defined!(NestedList!(PEG.literal!("("), PEG.literal!(")")), "Pegged.DParamList")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(NestedList!(pegged.peg.literal!("("), pegged.peg.literal!(")")), "Pegged.DParamList"), "DParamList")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(NestedList!(PEG.literal!("("), PEG.literal!(")")), "Pegged.DParamList"), "DParamList")(ParseTree("", false,[], s)); } } static string DParamList(GetName g) @@ -2031,25 +2042,25 @@ struct GenericPegged(TParseTree) template NestedList(alias L, alias Items, alias R) { - static TParseTree NestedList(TParseTree p) + static ParseTree NestedList(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(Items, NestedList!(L, Items, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(p); + return PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.zeroOrMore!(PEG.or!(Items, NestedList!(L, Items, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(Items, NestedList!(L, Items, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_3")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.zeroOrMore!(PEG.or!(Items, NestedList!(L, Items, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_3")(p); } } - static TParseTree NestedList(string s) + static ParseTree NestedList(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(Items, NestedList!(L, Items, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.zeroOrMore!(PEG.or!(Items, NestedList!(L, Items, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(Items, NestedList!(L, Items, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R, Items)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_3")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.zeroOrMore!(PEG.or!(Items, NestedList!(L, Items, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R, Items)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(Items)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_3")(ParseTree("", false,[], s)); } } static string NestedList(GetName g) @@ -2060,25 +2071,25 @@ struct GenericPegged(TParseTree) } template NestedList(alias L, alias R) { - static TParseTree NestedList(TParseTree p) + static ParseTree NestedList(ParseTree p) { if(__ctfe) { - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(NestedList!(L, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(p); + return PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.zeroOrMore!(PEG.or!(NestedList!(L, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(p); } else { - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(NestedList!(L, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_2")(p); + return hooked!(PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.zeroOrMore!(PEG.or!(NestedList!(L, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_2")(p); } } - static TParseTree NestedList(string s) + static ParseTree NestedList(string s) { if(__ctfe) - return pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(NestedList!(L, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(TParseTree("", false,[], s)); + return PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.zeroOrMore!(PEG.or!(NestedList!(L, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")")(ParseTree("", false,[], s)); else { forgetMemo(); - return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.keep!(L), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.zeroOrMore!(pegged.peg.or!(NestedList!(L, R), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)))), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.or!(L, R)), pegged.peg.any)), pegged.peg.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_2")(TParseTree("", false,[], s)); + return hooked!(PEG.defined!(PEG.and!(PEG.keep!(L), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.zeroOrMore!(PEG.or!(NestedList!(L, R), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)))), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.or!(L, R)), PEG.any)), PEG.keep!(R)), "Pegged.NestedList!(" ~ pegged.peg.getName!(L)() ~ ", " ~ pegged.peg.getName!(R) ~ ")"), "NestedList_2")(ParseTree("", false,[], s)); } } static string NestedList(GetName g) @@ -2087,18 +2098,18 @@ struct GenericPegged(TParseTree) } } - static TParseTree opCall(TParseTree p) + static ParseTree opCall(ParseTree p) { - TParseTree result = decimateTree(Grammar(p)); + ParseTree result = decimateTree(Grammar(p)); result.children = [result]; result.name = "Pegged"; return result; } - static TParseTree opCall(string input) + static ParseTree opCall(string input) { forgetMemo(); - return Pegged(TParseTree(``, false, [], input, 0, 0)); + return Pegged(ParseTree(``, false, [], input, 0, 0)); } static string opCall(GetName g) { @@ -2112,5 +2123,5 @@ struct GenericPegged(TParseTree) } } -alias GenericPegged!(ParseTree).Pegged Pegged; +alias GenericPegged!(DefaultParseTree).Pegged Pegged; diff --git a/pegged/parsetree.d b/pegged/parsetree.d new file mode 100644 index 00000000..a404ac4e --- /dev/null +++ b/pegged/parsetree.d @@ -0,0 +1,201 @@ +/** + This module contaits functions and parameter for ParseTree data element +*/ +module pegged.parsetree; + +import std.traits : isType, ReturnType, ForeachType, isCallable, Unqual; +/** + Returns: + Gets the lvalue of M where M can be a function/data as type of data +*/ +template Returns(alias M) { + static if (isType!M) { + alias U = M; + } + else { + alias U = typeof(M); + } + static if (isCallable!U) { + alias Returns = Unqual!(ReturnType!U); + } + else { + alias Returns = Unqual!(U); + } +} + +/** + Returns + true if T is a value ParseTree type +*/ +enum isParseTree(T) = + is(Returns!(T.name) == string) && + is(Returns!(T.successful) == bool) && + is(Returns!(T.input) == string) && + is(Returns!(T.begin) == size_t) && + is(Returns!(T.end) == size_t) && + is(Returns!(T.failEnd) == size_t) && + is(ForeachType!(Returns!(T.matches)) == string) && + is(ForeachType!(Returns!(T.children)) == T) && + is(ForeachType!(Returns!(T.failedChild)) == T); + + +/** + Contains the basic data and function for a ParseTree data element +*/ +mixin template ParseTreeM() { + import pegged.peg; + import std.functional : toDelegate; + import std.conv : to; + import std.algorithm.iteration : map; + import std.array : array; + + alias ParseTree = typeof(this); + @safe { + + alias Dynamic = ParseTree delegate(ParseTree) @safe; + string name; /// The node name + bool successful; /// Indicates whether a parsing was successful or not + string[] matches; /// The matched input's parts. Some expressions match at more than one place, hence matches is an array. + + string input; /// The input string that generated the parse tree. Stored here for the parse tree to be passed to other expressions, as input. + size_t begin, end; /// Indices for the matched part from the very beginning of the first match to the last char of the last match. + + ParseTree[] children; /// The sub-trees created by sub-rules parsing. + + size_t failEnd; // The furthest this tree could match the input (including !successful rules). + ParseTree[] failedChild; /// The !successful child that could still be partially parsed. + + /** + Basic toString for easy pretty-printing. + */ + string toString(string tabs = "") const + { + string result = name; + + string childrenString; + bool allChildrenSuccessful = true; + + foreach(i,child; children) + { + childrenString ~= tabs ~ " +-" ~ child.toString(tabs ~ ((i < children.length -1 ) ? " | " : " ")); + if (!child.successful) { + allChildrenSuccessful = false; + } + } + result ~= this.toStringThisNode(allChildrenSuccessful); + return result ~ childrenString; + } + + static ParseTree[] getUpto(ParseTree[] children, size_t minFailedLength) { + import std.algorithm : filter, max; + ParseTree[] arr; + foreach(a; children.filter!(r => max(r.end, r.failEnd) >= minFailedLength)) { + arr~=a; + } + return arr; +// return children.filter!(r => max(r.end, r.failEnd) >= minFailedLength).array(); + } + + + /** + * Basic toString of only this node, without the children + */ + private string toStringThisNode(bool allChildrenSuccessful) const + { + if (successful) { + return to!string([begin, end]) ~ to!string(matches) ~ "\n"; + } else { // some failure info is needed + if (allChildrenSuccessful) { // no one calculated the position yet + return " " ~ this.failMsg ~ "\n"; + } else { + return " (failure)\n"; + } + } + } + + /** + * Default fail message formating function + */ + static string defaultFormatFailMsg(Position pos, string left, string right, const ParseTree pt) + { + return "Failure at line " ~ to!string(pos.line) ~ ", col " ~ to!string(pos.col) ~ ", " + ~ (left.length > 0 ? "after " ~ left.stringified ~ " " : "") + ~ "expected " ~ (pt.matches.length > 0 ? pt.matches[$ - 1].stringified : "NO MATCH") + ~ `, but got ` ~ right.stringified; + }; + + + /** + * Generates a generic error when a node fails + * + * @param successMsg String returned when there isn't an error + * @param formatFailMsg Formating delegate function that generates the error message. + */ + string failMsg(string delegate(Position, string, string, const ParseTree) @safe formatFailMsg = toDelegate(&defaultFormatFailMsg), + string successMsg = "Sucess") const @property + { + foreach(i, child; children) { + if (!child.successful) { + return child.failMsg(formatFailMsg, successMsg); + } + } + + if (!successful) { + Position pos = position(this); + string left, right; + + if (pos.index < 10) { + left = input[0 .. pos.index]; + } else { + left = input[pos.index - 10 .. pos.index]; + } + if (pos.index + 10 < input.length) { + right = input[pos.index .. pos.index + 10]; + } else { + right = input[pos.index .. $]; + } + return formatFailMsg(pos, left, right, this); + } + + return successMsg; + } + + ParseTree dup() const @property + { + ParseTree result; + result.name = name; + result.successful = successful; + result.matches = matches.dup; + result.input = input; + result.begin = begin; + result.end = end; + result.failEnd = failEnd; + result.failedChild = map!(p => p.dup)(failedChild).array(); + result.children = map!(p => p.dup)(children).array(); + return result; + } + + @trusted immutable(ParseTree) idup() const @property + { + return cast(immutable)dup(); + } + + // Override opIndex operators + ref ParseTree opIndex(size_t index) { + return children[index]; + } + + ref ParseTree[] opIndex() return { + return children; + } + + size_t opDollar(size_t pos)() const + { + return children.length; + } + + ParseTree[] opSlice(size_t i, size_t j) { + return children[i..j]; + } + } +} diff --git a/pegged/peg.d b/pegged/peg.d index 33ce886f..ae8f8b91 100644 --- a/pegged/peg.d +++ b/pegged/peg.d @@ -1,21 +1,21 @@ /** -This module contains the engine behind Pegged, the expression templates building blocks to create a top-down -recursive-descent parser. + This module contains the engine behind Pegged, the expression templates building blocks to create a top-down + recursive-descent parser. -The terminals and non-terminals described here are meant to be used inside a Pegged grammar. -As such, they are a bit less user-friendly than what's output by pegged.grammar. -For example they take a ParseTree as input, not a string. + The terminals and non-terminals described here are meant to be used inside a Pegged grammar. + As such, they are a bit less user-friendly than what's output by pegged.grammar. + For example they take a ParseTree as input, not a string. -See the /docs directory for the full documentation as markdown files. + See the /docs directory for the full documentation as markdown files. */ module pegged.peg; /* -NOTE: -Do not use the GrammarTester for unittesting in this module. This module needs -to be able to pass its unittests before the GrammarTester is even trustable. -Writing tests the long way is preferred here, as it will avoid the circular -dependency. + NOTE: + Do not use the GrammarTester for unittesting in this module. This module needs + to be able to pass its unittests before the GrammarTester is even trustable. + Writing tests the long way is preferred here, as it will avoid the circular + dependency. */ import std.algorithm: equal, map, startsWith, max, countUntil, maxElement, filter; @@ -24,9 +24,11 @@ import std.array; import std.conv; import std.string: strip; import std.typetuple; +import pegged.parsetree : isParseTree; +import std.exception : assumeUnique; // Returns quoted and escaped version of the input, but if the input is null, then return `"end of input"`. -package string stringified(string inp) @safe +string stringified(string inp) @safe { import std.format : format; @@ -49,12 +51,12 @@ package string stringified(string inp) @safe "\t" : `"\t"`, `"` : `"\""`, - "`" : q"("`")", + "`" : q{"`"}, "'" : `"'"`, "42" : `"42"`, "\"some text\"\n" : `"\"some text\"\n"` - ]; + ]; const caseSuit2 = [cast(string)null : `"end of input"`]; @@ -75,306 +77,307 @@ package string stringified(string inp) @safe } // Result is always true, but here, we just force CTFE-mode. - static assert(doTest); // Compile-time. doTest; // Run-time. + static assert(doTest); // Compile-time. } -version (tracer) -{ - import std.experimental.logger; - import std.algorithm.comparison : min; - - // Function pointers. - private static bool function(string ruleName, const ref ParseTree p) traceConditionFunction; - private static bool delegate(string ruleName, const ref ParseTree p) traceConditionDelegate; - private static int traceLevel; - private static bool traceBlocked; - private static bool logTraceLevel = false; - - private void incTraceLevel() - { - if (!__ctfe) - traceLevel++; - } - - private void decTraceLevel() - { - if (!__ctfe) - traceLevel--; - } - - private bool shouldTrace(string ruleName, const ref ParseTree p) - { - if (__ctfe || traceBlocked) - return false; - if (traceConditionDelegate != null) - return traceConditionDelegate(ruleName, p); - if (traceConditionFunction != null) - return traceConditionFunction(ruleName, p); - return false; - } +struct GetName {} - static this() - { - traceLevel = 0; - traceNothing(); - traceBlocked = false; - } +string getName(alias expr)() @property +{ + static if (is(typeof( { expr(GetName()); }))) + return expr(GetName()); + else + return __traits(identifier, expr); +} - /++ Supply a function to dynamically switch tracing on and off based on the rule name. - + - + Example: - + --- - + /* Exclude build-in parsers, only trace parsers generated from MyGrammar. */ - + setTraceConditionFunction(ruleName => ruleName.startsWith("MyGrammar")); - + --- - +/ - void setTraceConditionFunction(bool delegate(string ruleName, const ref ParseTree p) condition) - { - traceConditionDelegate = condition; - traceConditionFunction = null; - } +/// To compare two trees for content (not bothering with node names) +/// That's useful to compare the results from two different grammars. +bool softCompare(ParseTree)(const ParseTree p1, const ParseTree p2) @safe if (isParseTree!ParseTree) { + return p1.successful == p2.successful + && p1.matches == p2.matches + && p1.begin == p2.begin + && p1.end == p2.end + && equal!(softCompare)(p1.children, p2.children); // the same for children +} - /// ditto - void setTraceConditionFunction(bool function(string ruleName, const ref ParseTree p) condition) - { - traceConditionFunction = condition; - traceConditionDelegate = null; - } +/** + Predefined parser: matches word boundaries, as \b for regexes. +*/ +ParseTree wordBoundary(ParseTree)(const ParseTree p) @safe if (isParseTree!ParseTree) { + // TODO: I added more indexing guards and now this could probably use + // some simplification. Too tired to write it better. --Chad + bool matched = (p.end == 0 && isAlpha(p.input.front())) + || (p.end == p.input.length && isAlpha(p.input.back())) + || (p.end > 0 && isAlpha(p.input[p.end-1]) && p.end < p.input.length && !isAlpha(p.input[p.end])) + || (p.end > 0 && !isAlpha(p.input[p.end-1]) && p.end < p.input.length && isAlpha(p.input[p.end])); + if (matched) + return ParseTree("wordBoundary", matched, [], p.input, p.end, p.end, null); + else + return ParseTree("wordBoundary", matched, ["word boundary"], p.input, p.end, p.end, null); +} - /** Trace all rules. - * - * This can produce a lot of output. - */ - void traceAll() - { - setTraceConditionFunction(function(string ruleName, const ref ParseTree p) {return true;}); - } - /** Do not trace any rules. */ - void traceNothing() - { - traceConditionFunction = null; - traceConditionDelegate = null; - } +/** + CT Switch for testing 'keywords' implementations +*/ +enum +{ + IFCHAIN, + TRIE +} +enum KEYWORDS = IFCHAIN; - private string traceMsg(ParseTree p, string expression, string name) - { - import std.format; - Position pos = position(p); - enum inputLength = 15; - string result; - for (auto i = 1; i <= traceLevel; i++) - result ~= format("%d|", i); - result ~= format(" (l:%d, c:%d, i:%d)\t", pos.line + 1, pos.col + 1, pos.index) ~ - expression.stringified ~ " considering rule " ~ name.stringified ~ " on " ~ - p.input[p.end .. min(p.input.length, p.end + inputLength)].stringified ~ - (p.end + inputLength > p.input.length ? "" : "..."); - return result; - } +/// To record a position in a text +struct Position +{ + size_t line;/// line number (starts at 0) + size_t col;/// column number (starts at 0) + size_t index;/// index (starts at 0) +} - private string traceResultMsg(ParseTree p, string name) - { - import std.format; - import std.range: chain; - import std.algorithm.iteration: joiner; - Position pos = position(p); - enum inputLength = 15; - string result; - for (auto i = 1; i <= traceLevel; i++) - result ~= format("%d|", i); - if (p.successful) - { - string consumed; - foreach (match; p.matches) - consumed ~= match; - result ~= format(" (l:%d, c:%d, i:%d)\t", pos.line + 1, pos.col + 1, pos.index) ~ name.stringified ~ " SUCCEEDED on " ~ - consumed.stringified; - } - else - result ~= format(" (l:%d, c:%d, i:%d)\t", pos.line + 1, pos.col + 1, pos.index) ~ name.stringified ~ " FAILED on " ~ - p.input[p.end .. min(p.input.length, p.end + inputLength)].stringified ~ - (p.end + inputLength > p.input.length ? "" : "..."); - return result; - } +/** + Given an input string, returns the position corresponding to the end of the string. - /** - Overrides FileLogger to remove the time stamp. + For example: + --- + assert(position("abc") == Position(0,3,3)); + assert(position("abc + ") == Position(1,0,4)); + assert(position("abc - Example: - --- - sharedLog = new TraceLogger("TraceLog.txt"); - --- - */ - class TraceLogger : FileLogger + ") == Position(2,4,8)); + --- +*/ +Position position(string s) @safe +{ + size_t col, line, index, prev_i; + char prev_c; + foreach(i,c; s) { - this(in string fn) @safe + if ((c == '\n' && !(i == prev_i + 1 && prev_c == '\r')) || // new line except when directly following a carriage return. + c == '\r') { - super(fn); + col = 0; + ++line; + ++index; + prev_i = i; + prev_c = c; } - import std.concurrency : Tid; - import std.datetime : SysTime; - override protected void beginLogMsg(string file, int line, string funcName, - string prettyFuncName, string moduleName, LogLevel logLevel, - Tid threadId, SysTime timestamp, Logger logger) - @safe + else { + if (c != '\n') + ++col; + ++index; } } + + return Position(line,col,index); } + /** -CT Switch for testing 'keywords' implementations + Same as previous overload, but from the begin of P.input to p.end */ -enum +Position position(ParseTree)(const ParseTree p) @safe if(isParseTree!ParseTree) { - IFCHAIN, - TRIE + return position(p.input[0..p.end]); } -enum KEYWORDS = IFCHAIN; -/** -The basic parse tree, as used throughout the project. -You can define your own parse tree node, but respect the basic layout. -*/ -struct ParseTree +@safe unittest { - string name; /// The node name - bool successful; /// Indicates whether a parsing was successful or not - string[] matches; /// The matched input's parts. Some expressions match at more than one place, hence matches is an array. + assert(position("") == Position(0,0,0), "Null string, position 0."); + assert(position("abc") == Position(0,3,3), "length 3 string, no line feed."); + assert(position("abc +") == Position(1,0,4), "One end of line."); + assert(position("abc - string input; /// The input string that generated the parse tree. Stored here for the parse tree to be passed to other expressions, as input. - size_t begin, end; /// Indices for the matched part from the very beginning of the first match to the last char of the last match. +----") == Position(2,4,9), "Three lines (second one empty)."); + assert(position("abc +---- +----") == Position(2,4,13), "Three lines."); + assert(position(" - ParseTree[] children; /// The sub-trees created by sub-rules parsing. - size_t failEnd; // The furthest this tree could match the input (including !successful rules). - ParseTree[] failedChild; /// The !successful child that could still be partially parsed. +") == Position(3,0,3), "Four lines, all empty."); + assert(position("one\r\ntwo\r\nthree") == Position(2, 5, 15), "Three lines, DOS line endings"); +} - /** - Basic toString for easy pretty-printing. - */ - string toString(string tabs = "") const - { - string result = name; - string childrenString; - bool allChildrenSuccessful = true; +struct PeggedT(ParseTree) { - foreach(i,child; children) +// import pegged.peg : fail, eoi, wordBoundary, eps; +// mixin ParseCollections!ParseTree; + version (tracer) { - childrenString ~= tabs ~ " +-" ~ child.toString(tabs ~ ((i < children.length -1 ) ? " | " : " ")); - if (!child.successful) { - allChildrenSuccessful = false; + import std.experimental.logger; + import std.algorithm.comparison : min; + + // Function pointers. + private static bool function(string ruleName, const ref ParseTree p) traceConditionFunction; + private static bool delegate(string ruleName, const ref ParseTree p) traceConditionDelegate; + private static int traceLevel; + private static bool traceBlocked; + private static bool logTraceLevel = false; + + private void incTraceLevel() + { + if (!__ctfe) + traceLevel++; } - } - result ~= this.toStringThisNode(allChildrenSuccessful); - return result ~ childrenString; - } - /** - * Basic toString of only this node, without the children - */ - private string toStringThisNode(bool allChildrenSuccessful) const - { - if (successful) { - return to!string([begin, end]) ~ to!string(matches) ~ "\n"; - } else { // some failure info is needed - if (allChildrenSuccessful) { // no one calculated the position yet - return " " ~ this.failMsg ~ "\n"; - } else { - return " (failure)\n"; + private void decTraceLevel() + { + if (!__ctfe) + traceLevel--; } - } - } - /** - * Generates a generic error when a node fails - * - * @param successMsg String returned when there isn't an error - * @param formatFailMsg Formating delegate function that generates the error message. - */ - string failMsg(string delegate(Position, string, string, const ParseTree) formatFailMsg = defaultFormatFailMsg, - string successMsg = "Sucess") const @property - { - foreach(i, child; children) { - if (!child.successful) { - return child.failMsg(formatFailMsg, successMsg); + private bool shouldTrace(string ruleName, const ref ParseTree p) + { + if (__ctfe || traceBlocked) + return false; + if (traceConditionDelegate != null) + return traceConditionDelegate(ruleName, p); + if (traceConditionFunction != null) + return traceConditionFunction(ruleName, p); + return false; + } + + static this() + { + traceLevel = 0; + traceNothing(); + traceBlocked = false; + } + + /++ Supply a function to dynamically switch tracing on and off based on the rule name. + + + + Example: + + --- + + /* Exclude build-in parsers, only trace parsers generated from MyGrammar. */ + + setTraceConditionFunction(ruleName => ruleName.startsWith("MyGrammar")); + + --- + +/ + static void setTraceConditionFunction(bool delegate(string ruleName, const ref ParseTree p) condition) + { + traceConditionDelegate = condition; + traceConditionFunction = null; } - } - if (!successful) { - Position pos = position(this); - string left, right; + /// ditto + static void setTraceConditionFunction(bool function(string ruleName, const ref ParseTree p) condition) + { + traceConditionFunction = condition; + traceConditionDelegate = null; + } - if (pos.index < 10) { - left = input[0 .. pos.index]; - } else { - left = input[pos.index - 10 .. pos.index]; + /** Trace all rules. + * + * This can produce a lot of output. + */ + static void traceAll() + { + setTraceConditionFunction(function(string ruleName, const ref ParseTree p) {return true;}); } - if (pos.index + 10 < input.length) { - right = input[pos.index .. pos.index + 10]; - } else { - right = input[pos.index .. $]; + + /** Do not trace any rules. */ + static void traceNothing() + { + traceConditionFunction = null; + traceConditionDelegate = null; } - return formatFailMsg(pos, left, right, this); - } - return successMsg; - } + private static string traceMsg(const ParseTree p, string expression, string name) + { + import std.format; + Position pos = position(p); + enum inputLength = 15; + string result; + for (auto i = 1; i <= traceLevel; i++) + result ~= format("%d|", i); + result ~= format(" (l:%d, c:%d, i:%d)\t", pos.line + 1, pos.col + 1, pos.index) ~ + expression.stringified ~ " considering rule " ~ name.stringified ~ " on " ~ + p.input[p.end .. min(p.input.length, p.end + inputLength)].stringified ~ + (p.end + inputLength > p.input.length ? "" : "..."); + return result; + } - ParseTree dup() const @property - { - ParseTree result; - result.name = name; - result.successful = successful; - result.matches = matches.dup; - result.input = input; - result.begin = begin; - result.end = end; - result.failEnd = failEnd; - result.failedChild = map!(p => p.dup)(failedChild).array(); - result.children = map!(p => p.dup)(children).array(); - return result; - } + private static string traceResultMsg(const ParseTree p, string name) + { + import std.format; + import std.range: chain; + import std.algorithm.iteration: joiner; + Position pos = position(p); + enum inputLength = 15; + string result; + for (auto i = 1; i <= traceLevel; i++) + result ~= format("%d|", i); + if (p.successful) + { + string consumed; + foreach (match; p.matches) + consumed ~= match; + result ~= format(" (l:%d, c:%d, i:%d)\t", pos.line + 1, pos.col + 1, pos.index) ~ name.stringified ~ " SUCCEEDED on " ~ + consumed.stringified; + } + else + result ~= format(" (l:%d, c:%d, i:%d)\t", pos.line + 1, pos.col + 1, pos.index) ~ name.stringified ~ " FAILED on " ~ + p.input[p.end .. min(p.input.length, p.end + inputLength)].stringified ~ + (p.end + inputLength > p.input.length ? "" : "..."); + return result; + } - immutable(ParseTree) idup() const @property - { - return cast(immutable)dup(); - } + /** + Overrides FileLogger to remove the time stamp. - // Override opIndex operators - ref ParseTree opIndex(size_t index) { - return children[index]; - } + Example: + --- + sharedLog = new TraceLogger("TraceLog.txt"); + --- + */ + static class TraceLogger : FileLogger + { + this(in string fn) @safe + { + super(fn); + } + import std.concurrency : Tid; + import std.datetime : SysTime; + override protected void beginLogMsg(string file, int line, string funcName, + string prettyFuncName, string moduleName, LogLevel logLevel, + Tid threadId, SysTime timestamp, Logger logger) + @safe + { + } + } + } - ref ParseTree[] opIndex() return { - return children; - } +// alias endOfInput = PEG.eoi; /// helper alias. + static ParseTree wordBoundary(string input) + { + return ParseTree("wordBoundary", isAlpha(input.front()), [], input, 0,0, null); + } - size_t opDollar(size_t pos)() const - { - return children.length; - } +/// ditto + static string wordBoundary(GetName g) + { + return "wordBoundary"; + } - ParseTree[] opSlice(size_t i, size_t j) { - return children[i..j]; - } } -/** - * Default fail message formating function - */ -immutable defaultFormatFailMsg = delegate (Position pos, string left, string right, const ParseTree pt) -{ - return "Failure at line " ~ to!string(pos.line) ~ ", col " ~ to!string(pos.col) ~ ", " - ~ (left.length > 0 ? "after " ~ left.stringified ~ " " : "") - ~ "expected " ~ (pt.matches.length > 0 ? pt.matches[$ - 1].stringified : "NO MATCH") - ~ `, but got ` ~ right.stringified; -}; - +version(unittest) { + private { + private import pegged.defaultparsetree : DefaultParseTree; + private alias ParseTree = DefaultParseTree; + private import PEG=pegged.parsetree; +// mixin ParseCollections!ParseTree; +// private alias PEG=PeggedT!ParseTree; +// mixin DefaultParsePatterns!PEG; + } +} -unittest // ParseTree testing +@safe unittest // ParseTree testing { ParseTree p; assert(p == p, "Self-identity on null tree."); @@ -429,18 +432,7 @@ unittest // ParseTree testing assert(p.failMsg == `Failure at line 0, col 1, after "i" expected "def", but got "nput"`); } -/// To compare two trees for content (not bothering with node names) -/// That's useful to compare the results from two different grammars. -bool softCompare(const ParseTree p1, const ParseTree p2) -{ - return p1.successful == p2.successful - && p1.matches == p2.matches - && p1.begin == p2.begin - && p1.end == p2.end - && equal!(softCompare)(p1.children, p2.children); // the same for children -} - -unittest // softCompare +@safe unittest // softCompare { ParseTree p = ParseTree("Name", true, ["abc", "", "def"], "input", 0, 1, null); ParseTree child = ParseTree("Child", true, ["abc", "", "def"], "input", 0, 1, null); @@ -455,328 +447,281 @@ unittest // softCompare assert(softCompare(p,q), "Name change => Trees equal for softCompare."); } -/// To record a position in a text -struct Position + +@safe unittest // 'fail' unit test { - size_t line;/// line number (starts at 0) - size_t col;/// column number (starts at 0) - size_t index;/// index (starts at 0) -} -/** -Given an input string, returns the position corresponding to the end of the string. + ParseTree input = ParseTree("input", true, [], "This is the input string.", 0,0, null); + ParseTree result = ParseTree.fail(input); + assert(result.name == "fail"); + assert(!result.successful, "'fail' fails."); + assert(result.matches is null, "'fail' makes no match."); + assert(result.input == input.input, "'fail' does not change the input."); + assert(result.end == input.end, "'fail' puts the index after the previous parse."); + assert(result.children is null, "'fail' has no children."); -For example: ---- -assert(position("abc") == Position(0,3,3)); -assert(position("abc -") == Position(1,0,4)); -assert(position("abc + result = ParseTree.fail("This is the input string."); + assert(!result.successful, "'fail' fails."); +} - ") == Position(2,4,8)); ---- -*/ -Position position(string s) + +@safe unittest // 'eoi' unit test { - size_t col, line, index, prev_i; - char prev_c; - foreach(i,c; s) - { - if ((c == '\n' && !(i == prev_i + 1 && prev_c == '\r')) || // new line except when directly following a carriage return. - c == '\r') - { - col = 0; - ++line; - ++index; - prev_i = i; - prev_c = c; - } - else - { - if (c != '\n') - ++col; - ++index; - } - } + ParseTree input = ParseTree("input", true, [], "This is the input string.", 0,0, null); + ParseTree result = ParseTree.eoi(input); + assert(result.name == "eoi"); + assert(!result.successful, "'eoi' fails on non-null string."); + assert(result.matches == ["end of input"], "'eoi' error message."); + assert(result.input == input.input, "'eoi' does not change the input."); + assert(result.end == input.end, "'eoi' puts the index after the previous parse."); + assert(result.children is null, "'eoi' has no children."); - return Position(line,col,index); + input = ParseTree("input", true, [], "", 0,0, null); + result = ParseTree.eoi(input); + assert(result.successful, "'eoi' succeeds on strings of length 0."); + result = ParseTree.eoi(""); + assert(result.successful, "'eoi' succeeds on strings of length 0."); + result = ParseTree.eoi(null); + assert(result.successful, "'eoi' succeeds on null strings"); } -/** -Same as previous overload, but from the begin of P.input to p.end -*/ -Position position(const ParseTree p) -{ - return position(p.input[0..p.end]); -} -unittest +@safe unittest // 'any' unit test { - assert(position("") == Position(0,0,0), "Null string, position 0."); - assert(position("abc") == Position(0,3,3), "length 3 string, no line feed."); - assert(position("abc -") == Position(1,0,4), "One end of line."); - assert(position("abc + ParseTree input = ParseTree("input", true, [], "This is the input string.", 0,0, null); + ParseTree result = ParseTree.any(input); -----") == Position(2,4,9), "Three lines (second one empty)."); - assert(position("abc ----- -----") == Position(2,4,13), "Three lines."); - assert(position(" + assert(result.name == "any"); + assert(result.successful, "'any' succeeds on non-null strings."); + assert(result.matches == ["T"], "'any' matches the first char in an input."); + assert(result.input == input.input, "'any' does not change the input."); + assert(result.end == input.end+1, "'any' advances the index by one position."); + assert(result.children is null, "'any' has no children."); + result = ParseTree.any("a"); + assert(result.successful, "'any' matches on strings of length one."); + assert(result.matches == ["a"], "'any' matches the first char in an input."); + assert(result.input == "a", "'any' does not change the input."); + assert(result.end == 1, "'any' advances the index by one position."); + assert(result.children is null, "'any' has no children."); -") == Position(3,0,3), "Four lines, all empty."); - assert(position("one\r\ntwo\r\nthree") == Position(2, 5, 15), "Three lines, DOS line endings"); -} + input = ParseTree("input", true, [], "", 0,0, null); -string getName(alias expr)() @property -{ - static if (is(typeof( { expr(GetName()); }))) - return expr(GetName()); - else - return __traits(identifier, expr); -} + result = ParseTree.any(input); + assert(!result.successful, "'any' fails on strings of length 0."); + assert(result.matches == ["any char"], "'any' error message on strings of length 0."); + assert(result.end == 0, "'any' does not advance the index."); -struct GetName {} + result = ParseTree.any(""); + assert(!result.successful, "'any' fails on strings of length 0."); + assert(result.matches == ["any char"], "'any' error message on strings of length 0."); + assert(result.end == 0, "'any' does not advance the index."); -/** -Basic rule, that always fail without consuming. -*/ -ParseTree fail(ParseTree p) -{ - return ParseTree("fail", false, [], p.input, p.end, p.end, null); + result = ParseTree.any(null); + assert(!result.successful, "'any' fails on null strings."); + assert(result.matches == ["any char"], "'any' error message on strings of length 0."); + assert(result.end == 0, "'any' does not advance the index."); } -/// ditto -ParseTree fail(string input) -{ - return fail(ParseTree("", false, [], input)); -} -string fail(GetName g) +@safe unittest // word boundary { - return "fail"; + ParseTree input = ParseTree("", false, [], "This is a word."); + auto wb = [// "This" + cast(size_t)(0):true, 1:false, 2:false, 3:false, 4: true, + // "is" + 5: true, 6:false, 7: true, + // "a" + 8: true, 9:true, + // "word" + 10:true, 11:false, 12:false, 13:false, 14:true, + // "." + 15:false + ]; + + foreach(size_t index; 0 .. input.input.length) + { + input.end = index; + ParseTree result = wordBoundary(input); + + assert(result.name == "wordBoundary"); + assert(result.successful == wb[index]); // true, false, ... + // for errors, there is an error message + assert(result.successful && result.matches is null || !result.successful); + assert(result.begin == input.end); + assert(result.end == input.end); + assert(result.children is null); + } } -unittest // 'fail' unit test + +@safe unittest // 'eps' unit test { - ParseTree input = ParseTree("input", true, [], "This is the input string.", 0,0, null); - ParseTree result = fail(input); - assert(result.name == "fail"); - assert(!result.successful, "'fail' fails."); - assert(result.matches is null, "'fail' makes no match."); - assert(result.input == input.input, "'fail' does not change the input."); - assert(result.end == input.end, "'fail' puts the index after the previous parse."); - assert(result.children is null, "'fail' has no children."); + ParseTree input = ParseTree("input", true, [], "abcdef", 0,0, null); - result = fail("This is the input string."); - assert(!result.successful, "'fail' fails."); + ParseTree result = ParseTree.eps(input); + + assert(result.name == "eps"); + assert(result.successful, "'eps' succeeds on non-null inputs."); + assert(result.matches == [""], "'eps' matches '' at the beginning."); + assert(result.input == input.input, "'eps' does not change the input."); + assert(result.end == input.end+0, "'eps' does not advance the index."); + assert(result.children is null, "'eps' has no children."); + + input.input = ""; + + result = ParseTree.eps(input); + assert(result.name == "eps"); + assert(result.successful, "'eps' succeeds on empty strings."); + assert(result.matches == [""], "'eps' matches '' at the beginning, even on empty strings."); + assert(result.input == input.input, "'eps' does not change the input."); + assert(result.end == input.end+0, "'eps' does not advance the index."); + assert(result.children is null, "'eps' has no children."); } + + +template eoiT(ParseTree) { + @safe: /** -Matches the end of input. Fails if there is any character left. + Matches the end of input. Fails if there is any character left. */ -ParseTree eoi(ParseTree p) -{ - if (p.end == p.input.length) - return ParseTree("eoi", true, [], p.input, p.end, p.end); - else - return ParseTree("eoi", false, ["end of input"], p.input, p.end, p.end); -} + ParseTree eoiT(ParseTree p) { + if (p.end == p.input.length) + return ParseTree("eoi", true, [], p.input, p.end, p.end); + else + return ParseTree("eoi", false, ["end of input"], p.input, p.end, p.end); + } /// ditto -ParseTree eoi(string input) -{ - return eoi(ParseTree("", false, [], input)); -} - -string eoi(GetName g) -{ - return "eoi"; -} + ParseTree eoiT(string input) + { + return eoiT(ParseTree("", false, [], input)); + } -alias eoi endOfInput; /// helper alias. -unittest // 'eoi' unit test -{ - ParseTree input = ParseTree("input", true, [], "This is the input string.", 0,0, null); - ParseTree result = eoi(input); - assert(result.name == "eoi"); - assert(!result.successful, "'eoi' fails on non-null string."); - assert(result.matches == ["end of input"], "'eoi' error message."); - assert(result.input == input.input, "'eoi' does not change the input."); - assert(result.end == input.end, "'eoi' puts the index after the previous parse."); - assert(result.children is null, "'eoi' has no children."); - - input = ParseTree("input", true, [], "", 0,0, null); - result = eoi(input); - assert(result.successful, "'eoi' succeeds on strings of length 0."); - result = eoi(""); - assert(result.successful, "'eoi' succeeds on strings of length 0."); - result = eoi(null); - assert(result.successful, "'eoi' succeeds on null strings"); + string eoiT(GetName g) @safe + { + return "eoi"; + } } + +template epsT(ParseTree) { /** -Match any character. As long as there is at least a character left in the input, it succeeds. -Conversely, it fails only if called at the end of the input. + eps matches the empty string (usually denoted by the Greek letter 'epsilon') and always succeeds. + It's equivalent to literal!"" (for example, it creates a match of [""]: one match, the empty string). */ -ParseTree any(ParseTree p) -{ - if (p.end < p.input.length) - return ParseTree("any", true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); - else - return ParseTree("any", false, ["any char"], p.input, p.end, p.end); -} + ParseTree epsT(const ParseTree p) { + return ParseTree("eps", true, [""], p.input, p.end, p.end); + } -/// ditto -ParseTree any(string input) -{ - return any(ParseTree("", false, [], input)); + ParseTree epsT(string input) + { + return epsT(ParseTree("",false,[], input)); + } + + string epsT(GetName g) + { + return "eps"; + } } -string any(GetName g) -{ - return "any"; -} -unittest // 'any' unit test -{ - ParseTree input = ParseTree("input", true, [], "This is the input string.", 0,0, null); - ParseTree result = any(input); +template anyT(ParseTree) { + /** + Match any character. As long as there is at least a character left in the input, it succeeds. + Conversely, it fails only if called at the end of the input. + */ + ParseTree anyT(ParseTree p) { + if (p.end < p.input.length) + return ParseTree("any", true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); + else + return ParseTree("any", false, ["any char"], p.input, p.end, p.end); + } - assert(result.name == "any"); - assert(result.successful, "'any' succeeds on non-null strings."); - assert(result.matches == ["T"], "'any' matches the first char in an input."); - assert(result.input == input.input, "'any' does not change the input."); - assert(result.end == input.end+1, "'any' advances the index by one position."); - assert(result.children is null, "'any' has no children."); - result = any("a"); - assert(result.successful, "'any' matches on strings of length one."); - assert(result.matches == ["a"], "'any' matches the first char in an input."); - assert(result.input == "a", "'any' does not change the input."); - assert(result.end == 1, "'any' advances the index by one position."); - assert(result.children is null, "'any' has no children."); + /// ditto + ParseTree anyT(string input) + { + return anyT(ParseTree("", false, [], input)); + } - input = ParseTree("input", true, [], "", 0,0, null); - result = any(input); - assert(!result.successful, "'any' fails on strings of length 0."); - assert(result.matches == ["any char"], "'any' error message on strings of length 0."); - assert(result.end == 0, "'any' does not advance the index."); + string anyT(GetName g) @safe + { + return "any"; + } +} - result = any(""); - assert(!result.successful, "'any' fails on strings of length 0."); - assert(result.matches == ["any char"], "'any' error message on strings of length 0."); - assert(result.end == 0, "'any' does not advance the index."); +template failT(ParseTree) { + /** + Basic rule, that always fail without consuming. + */ + ParseTree failT(ParseTree p) @safe { + return ParseTree("fail", false, [], p.input, p.end, p.end, null); + } - result = any(null); - assert(!result.successful, "'any' fails on null strings."); - assert(result.matches == ["any char"], "'any' error message on strings of length 0."); - assert(result.end == 0, "'any' does not advance the index."); -} -/** -Predefined parser: matches word boundaries, as \b for regexes. -*/ -ParseTree wordBoundary(ParseTree p) -{ - // TODO: I added more indexing guards and now this could probably use - // some simplification. Too tired to write it better. --Chad - bool matched = (p.end == 0 && isAlpha(p.input.front())) - || (p.end == p.input.length && isAlpha(p.input.back())) - || (p.end > 0 && isAlpha(p.input[p.end-1]) && p.end < p.input.length && !isAlpha(p.input[p.end])) - || (p.end > 0 && !isAlpha(p.input[p.end-1]) && p.end < p.input.length && isAlpha(p.input[p.end])); - if (matched) - return ParseTree("wordBoundary", matched, [], p.input, p.end, p.end, null); - else - return ParseTree("wordBoundary", matched, ["word boundary"], p.input, p.end, p.end, null); -} -/// ditto -ParseTree wordBoundary(string input) -{ - return ParseTree("wordBoundary", isAlpha(input.front()), [], input, 0,0, null); -} + ParseTree failT(string input) + { + return failT(ParseTree("", false, [], input)); + } -string wordBoundary(GetName g) -{ - return "wordBoundary"; + + string failT(GetName g) @safe + { + return "fail"; + } } -unittest // word boundary -{ - ParseTree input = ParseTree("", false, [], "This is a word."); - auto wb = [// "This" - cast(size_t)(0):true, 1:false, 2:false, 3:false, 4: true, - // "is" - 5: true, 6:false, 7: true, - // "a" - 8: true, 9:true, - // "word" - 10:true, 11:false, 12:false, 13:false, 14:true, - // "." - 15:false - ]; - foreach(size_t index; 0 .. input.input.length) - { - input.end = index; - ParseTree result = wordBoundary(input); - assert(result.name == "wordBoundary"); - assert(result.successful == wb[index]); // true, false, ... - // for errors, there is an error message - assert(result.successful && result.matches is null || !result.successful); - assert(result.begin == input.end); - assert(result.end == input.end); - assert(result.children is null); - } -} /** -Represents a literal in a PEG, like "abc" or 'abc' (or even ''). -It succeeds if a prefix of the input is equal to its template parameter and fails otherwise. + Represents a literal in a PEG, like "abc" or 'abc' (or even ''). + It succeeds if a prefix of the input is equal to its template parameter and fails otherwise. */ -template literal(string s) +template literalT(ParseTree, string s) { enum name = "literal!(\""~s~"\")"; - ParseTree literal(ParseTree p) - { - enum lit = "\"" ~ s ~ "\""; - - if (p.end+s.length <= p.input.length && p.input[p.end..p.end+s.length] == s) - return ParseTree(name, true, [s], p.input, p.end, p.end+s.length); - else { - import std.algorithm : commonPrefix; - import std.utf : byCodeUnit; - auto prefix = p.input[p.end..$].byCodeUnit.commonPrefix(s.byCodeUnit); - return ParseTree(name, false, [lit], p.input, p.end, p.end, null, p.end + prefix.length); + ParseTree literalT(ParseTree p) + { + enum lit = "\"" ~ s ~ "\""; + + if (p.end+s.length <= p.input.length && p.input[p.end..p.end+s.length] == s) + return ParseTree(name, true, [s], p.input, p.end, p.end+s.length); + else { + import std.algorithm : commonPrefix; + import std.utf : byCodeUnit; + auto prefix = p.input[p.end..$].byCodeUnit.commonPrefix(s.byCodeUnit); + return ParseTree(name, false, [lit], p.input, p.end, p.end, null, p.end + prefix.length); + } } - } - ParseTree literal(string input) - { - return .literal!(s)(ParseTree("", false, [], input)); - } + ParseTree literalT(string input) + { + return literalT!(ParseTree, s)(ParseTree("", false, [], input)); + } - string literal(GetName g) - { - return name; - } + string literalT(GetName g) + { + return name; + } } -unittest // 'literal' unit test +@safe unittest // 'literal' unit test { + ParseTree input = ParseTree("input", true, [], "abcdef", 0,0, null); - alias literal!"a" a; - alias literal!"abc" abc; - alias literal!"" empty; + alias a = ParseTree.literal!"a"; + alias abc = ParseTree.literal!"abc"; + alias empty = ParseTree.literal!""; ParseTree result = a(input); @@ -883,43 +828,43 @@ unittest // 'literal' unit test } /** -Represents a case insensitive literal in a PEG, like "abc"i or 'abc'i (or even ''i). -It succeeds if a case insensitive comparison of a prefix of the input and its template -parameter yields no difference and fails otherwise. + Represents a case insensitive literal in a PEG, like "abc"i or 'abc'i (or even ''i). + It succeeds if a case insensitive comparison of a prefix of the input and its template + parameter yields no difference and fails otherwise. */ -template caseInsensitiveLiteral(string s) +template caseInsensitiveLiteralT(ParseTree, string s) { enum name = "caseInsensitiveLiteral!(\""~s~"\")"; - ParseTree caseInsensitiveLiteral(ParseTree p) - { - enum lit = "\"" ~ s ~ "\""; - if (p.end+s.length <= p.input.length && icmp(p.input[p.end..p.end+s.length], s) == 0) - return ParseTree(name, true, [s], p.input, p.end, p.end+s.length); - else - return ParseTree(name, false, [lit], p.input, p.end, p.end); - } + ParseTree caseInsensitiveLiteralT(ParseTree p) + { + enum lit = "\"" ~ s ~ "\""; + if (p.end+s.length <= p.input.length && icmp(p.input[p.end..p.end+s.length], s) == 0) + return ParseTree(name, true, [s], p.input, p.end, p.end+s.length); + else + return ParseTree(name, false, [lit], p.input, p.end, p.end); + } - ParseTree caseInsensitiveLiteral(string input) - { - return .caseInsensitiveLiteral!(s)(ParseTree("", false, [], input)); - } + ParseTree caseInsensitiveLiteralT(string input) + { + return caseInsensitiveLiteralT!(ParseTree, s)(ParseTree("", false, [], input)); + } - string caseInsensitiveLiteral(GetName g) - { - return name; - } + string caseInsensitiveLiteralT(GetName g) + { + return name; + } } -unittest // 'caseInsensitiveLiteral' unit test +@safe unittest // 'caseInsensitiveLiteral' unit test { ParseTree input = ParseTree("input", true, [], "AbCdEf", 0,0, null); - alias caseInsensitiveLiteral!"a" a; - alias caseInsensitiveLiteral!"aBC" abc; - alias caseInsensitiveLiteral!"" empty; + alias ParseTree.caseInsensitiveLiteral!"a" a; + alias ParseTree.caseInsensitiveLiteral!"aBC" abc; + alias ParseTree.caseInsensitiveLiteral!"" empty; ParseTree result = a(input); @@ -1025,53 +970,53 @@ unittest // 'caseInsensitiveLiteral' unit test assert(result.children is null, "'' has no children."); input.input = "ÄöÜæØå"; - result = caseInsensitiveLiteral!"äÖüÆøÅ"(input); + result = ParseTree.caseInsensitiveLiteral!"äÖüÆøÅ"(input); assert(result.successful, "Unicode characters are matched case insensitively."); } /** -Represents a range of chars, from begin to end, included. So charRange!('a','z') matches -all English lowercase letters. If fails if the input is empty or does not begin with a character -between begin and end. + Represents a range of chars, from begin to end, included. So charRange!('a','z') matches + all English lowercase letters. If fails if the input is empty or does not begin with a character + between begin and end. -If begin == end, it will match one char (begin... or end). + If begin == end, it will match one char (begin... or end). -begin > end is non-legal. + begin > end is non-legal. */ -template charRange(dchar begin, dchar end) if (begin <= end) +template charRangeT(ParseTree, dchar begin, dchar end) if (begin <= end) { enum name = "charRange!('"~to!string(begin)~"','" ~ to!string(end) ~ "')"; - ParseTree charRange(ParseTree p) - { - enum longname = "a char between '"~to!string(begin)~"' and '"~to!string(end)~"'"; - if (p.end < p.input.length && p.input[p.end] >= begin && p.input[p.end] <= end) - return ParseTree(name, true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); - else - return ParseTree(name, false, [longname], p.input, p.end, p.end); - } + ParseTree charRangeT(ParseTree p) + { + enum longname = "a char between '"~to!string(begin)~"' and '"~to!string(end)~"'"; + if (p.end < p.input.length && p.input[p.end] >= begin && p.input[p.end] <= end) + return ParseTree(name, true, [p.input[p.end..p.end+1]], p.input, p.end, p.end+1); + else + return ParseTree(name, false, [longname], p.input, p.end, p.end); + } - ParseTree charRange(string input) - { - return .charRange!(begin,end)(ParseTree("",false,[],input)); - } + ParseTree charRangeT(string input) + { + return .charRangeT!(ParseTree, begin, end)(ParseTree("",false,[],input)); + } - string charRange(GetName g) - { - return name; - } + string charRangeT(GetName g) + { + return name; + } } -unittest // 'charRange' unit test +@safe unittest // 'charRange' unit test { ParseTree input = ParseTree("input", true, [], "abcdef", 0,0, null); - alias charRange!('a','a') aa; - alias charRange!('a','b') ab; - alias charRange!('a','z') az; - alias charRange!(dchar.min,dchar.max) allChars; - alias charRange!('\U00000000','\U000000FF') ASCII; + alias aa = ParseTree.charRange!('a','a'); + alias ab = ParseTree.charRange!('a','b'); + alias az = ParseTree.charRange!('a','z'); + alias allChars = ParseTree.charRange!(dchar.min,dchar.max); + alias ASCII = ParseTree.charRange!('\U00000000','\U000000FF'); static assert(!__traits(compiles, {alias charRange!('z','a') za;})); @@ -1188,211 +1133,165 @@ unittest // 'charRange' unit test } /** -eps matches the empty string (usually denoted by the Greek letter 'epsilon') and always succeeds. -It's equivalent to literal!"" (for example, it creates a match of [""]: one match, the empty string). -*/ -ParseTree eps(ParseTree p) -{ - return ParseTree("eps", true, [""], p.input, p.end, p.end); -} - -ParseTree eps(string input) -{ - return eps(ParseTree("",false,[], input)); -} - -string eps(GetName g) -{ - return "eps"; -} - -unittest // 'eps' unit test -{ - ParseTree input = ParseTree("input", true, [], "abcdef", 0,0, null); - - ParseTree result = eps(input); - - assert(result.name == "eps"); - assert(result.successful, "'eps' succeeds on non-null inputs."); - assert(result.matches == [""], "'eps' matches '' at the beginning."); - assert(result.input == input.input, "'eps' does not change the input."); - assert(result.end == input.end+0, "'eps' does not advance the index."); - assert(result.children is null, "'eps' has no children."); - - input.input = ""; - - result = eps(input); - assert(result.name == "eps"); - assert(result.successful, "'eps' succeeds on empty strings."); - assert(result.matches == [""], "'eps' matches '' at the beginning, even on empty strings."); - assert(result.input == input.input, "'eps' does not change the input."); - assert(result.end == input.end+0, "'eps' does not advance the index."); - assert(result.children is null, "'eps' has no children."); -} - - -/** -Basic operator: it matches if all its subrules (stored in the rules template parameter tuple) match -the input successively. Its subrules parse trees are stored as its children and its matches field -will contain all its subrules matches, in order. - ----- -alias and!(literal!"abc", charRange!('a','z')) rule; // abc followed by any letter between a and z. -ParseTree input = ParseTree("",false,[],"abcd"); // low-level plumbing, - // the rules described here act on ParseTree's not strings. - // It's equivalent to "abcd" as input -auto result = rule(input); - -assert(result.successful); // OK, 'abc' followed by 'd' -assert(result.matches == ["abc", "d"]); // stores the matches -assert(result.children.length == 2); // two children, the result of "abc" on "abcd" and the result of [a-z] on "d" - -input.input = "abc"; // changing the input string; -assert(!rule(input)).successful); // NOK, abc alone -input.input = "ab"; -assert(!rule(input)).successful); // NOK, does not begin by abc ----- - -If it fails, the last children will contain the failed node. That way, when printing, as sort of diagnostic is given: - ----- -alias and!(literal!"abc", charRange!('a','z')) rule; // 'abc[a-z]', aka 'abc' followed by any letter between 'a' and 'z'. -ParseTree input = ParseTree("",false,[],"abc1"); // equivalent to "abc1" - -auto failure = rule(input); -writeln(failure); -/+ -writes: -and (failure) - +-literal(abc) [0, 3]["abc"] - +-charRange(a,z) failure at line 0, col 3, after "abc" a char between 'a' and 'z', but got "1" -+/ ----- - -So we know the global 'and' failed, that the first sub-rule ('abc') succeeded on input[0..3] with "abc" -and that the second subrule ('[a-z]') failed at position 3 (so, on '1'). + Basic operator: it matches if all its subrules (stored in the rules template parameter tuple) match + the input successively. Its subrules parse trees are stored as its children and its matches field + will contain all its subrules matches, in order. + + ---- + alias and!(literal!"abc", charRange!('a','z')) rule; // abc followed by any letter between a and z. + ParseTree input = ParseTree("",false,[],"abcd"); // low-level plumbing, + // the rules described here act on ParseTree's not strings. + // It's equivalent to "abcd" as input + auto result = rule(input); + + assert(result.successful); // OK, 'abc' followed by 'd' + assert(result.matches == ["abc", "d"]); // stores the matches + assert(result.children.length == 2); // two children, the result of "abc" on "abcd" and the result of [a-z] on "d" + + input.input = "abc"; // changing the input string; + assert(!rule(input)).successful); // NOK, abc alone + input.input = "ab"; + assert(!rule(input)).successful); // NOK, does not begin by abc + ---- + + If it fails, the last children will contain the failed node. That way, when printing, as sort of diagnostic is given: + + ---- + alias and!(literal!"abc", charRange!('a','z')) rule; // 'abc[a-z]', aka 'abc' followed by any letter between 'a' and 'z'. + ParseTree input = ParseTree("",false,[],"abc1"); // equivalent to "abc1" + + auto failure = rule(input); + writeln(failure); + /+ + writes: + and (failure) + +-literal(abc) [0, 3]["abc"] + +-charRange(a,z) failure at line 0, col 3, after "abc" a char between 'a' and 'z', but got "1" + +/ + ---- + + So we know the global 'and' failed, that the first sub-rule ('abc') succeeded on input[0..3] with "abc" + and that the second subrule ('[a-z]') failed at position 3 (so, on '1'). */ -template and(rules...) if (rules.length > 0) +template andT(ParseTree, rules...) if (rules.length > 0) { string ctfeGetNameAnd() - { - string name = "and!("; - foreach(i,rule; rules) - name ~= __traits(identifier, rule) // because using getName!(rule) causes an infinite loop during compilation - // for recursive rules + { + string name = "and!("; + foreach(i,rule; rules) + name ~= __traits(identifier, rule) // because using getName!(rule) causes an infinite loop during compilation + // for recursive rules ~ (i < rules.length -1 ? ", " : ""); - name ~= ")"; - return name; - } + name ~= ")"; + return name; + } enum name = ctfeGetNameAnd(); - ParseTree and(ParseTree p) - { - bool keepNode(ParseTree node) - { - return node.name.startsWith("keep!(") - || ( !node.name.startsWith("discard!(") - //&& !node.name.startsWith("drop!(") - && (node.matches !is null - || node.failEnd >= node.end) - //&& node.begin != node.end - ); - } - - version (tracer) + ParseTree andT(ParseTree p) { - incTraceLevel(); - } - - ParseTree result = ParseTree(name, false, [], p.input, p.end, p.end, []); + bool keepNode(ParseTree node) + { + return node.name.startsWith("keep!(") + || ( !node.name.startsWith("discard!(") + //&& !node.name.startsWith("drop!(") + && (node.matches !is null + || node.failEnd >= node.end) + //&& node.begin != node.end + ); + } - foreach(i,r; rules) - { version (tracer) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(result, name, getName!(r)())); + incTraceLevel(); } - ParseTree temp = r(result); - result.end = temp.end; - result.failEnd = max(result.failEnd, temp.failEnd); - if (temp.successful) + + ParseTree result = ParseTree(name, false, [], p.input, p.end, p.end, []); + + foreach(i,r; rules) { - if (keepNode(temp)) + version (tracer) { - result.matches ~= temp.matches; - if (temp.name.startsWith("drop!(")) - {} - else if (temp.name.startsWith("propagate!(")) - result.children ~= temp.children; - else - result.children ~= temp; + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(result, name, getName!(r)())); } - } - else - { - auto firstLongestFailedMatch = result.children.firstLongestFailedMatch(temp.end); - if (firstLongestFailedMatch == -1) { - result.children ~= temp;// add the failed node, to indicate which failed - if (temp.matches.length > 0) - result.matches ~= temp.matches[$-1]; - } else { - // don't add the failed node because a previous one already failed further back - result.children = result.children[0 .. firstLongestFailedMatch+1]; // discard any intermediate correct nodes - // This current 'and' rule has failed parsing and there is a successful child - // that had a longer failing match. We now want to revisit that child and modify it - // so that it is no longer successful and we want to move its failedChild into its children. - failedChildFixup(result.children[firstLongestFailedMatch], result.children[firstLongestFailedMatch].failEnd); + ParseTree temp = r(result); + result.end = temp.end; + result.failEnd = max(result.failEnd, temp.failEnd); + if (temp.successful) + { + if (keepNode(temp)) + { + result.matches ~= temp.matches; + if (temp.name.startsWith("drop!(")) + {} + else if (temp.name.startsWith("propagate!(")) + result.children ~= temp.children; + else + result.children ~= temp; + } } - result.end = result.children.maxEnd(); - result.failEnd = result.children.maxFailEnd(); - version (tracer) + else { - if (shouldTrace(getName!(r)(), p)) - trace(traceResultMsg(result, getName!(r)())); - decTraceLevel(); + auto firstLongestFailedMatch = result.children.firstLongestFailedMatch(temp.end); + if (firstLongestFailedMatch == -1) { + result.children ~= temp;// add the failed node, to indicate which failed + if (temp.matches.length > 0) + result.matches ~= temp.matches[$-1]; + } else { + // don't add the failed node because a previous one already failed further back + result.children = result.children[0 .. firstLongestFailedMatch+1]; // discard any intermediate correct nodes + // This current 'and' rule has failed parsing and there is a successful child + // that had a longer failing match. We now want to revisit that child and modify it + // so that it is no longer successful and we want to move its failedChild into its children. + failedChildFixup(result.children[firstLongestFailedMatch], result.children[firstLongestFailedMatch].failEnd); + } + result.end = result.children.maxEnd(); + result.failEnd = result.children.maxFailEnd(); + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceResultMsg(result, getName!(r)())); + decTraceLevel(); + } + return result; // and end the parsing attempt right there } - return result; // and end the parsing attempt right there } + result.successful = true; + version (tracer) + { + foreach(i, r; rules) + if (shouldTrace(getName!(r)(), p)) + { + trace(traceResultMsg(result, name)); + break; + } + decTraceLevel(); + } + return result; } - result.successful = true; - version (tracer) + + ParseTree andT(string input) { - foreach(i, r; rules) - if (shouldTrace(getName!(r)(), p)) - { - trace(traceResultMsg(result, name)); - break; - } - decTraceLevel(); + return .andT!(ParseTree, rules)(ParseTree("",false,[],input)); } - return result; - } - - ParseTree and(string input) - { - return .and!(rules)(ParseTree("",false,[],input)); - } - string and(GetName g) - { - return name; - } + string andT(GetName g) + { + return name; + } } -auto firstLongestFailedMatch(ParseTree[] children, size_t threshold) { +auto firstLongestFailedMatch(ParseTree)(ParseTree[] children, size_t threshold) if (isParseTree!ParseTree) { return children.countUntil!(c => c.failEnd > threshold); } -auto maxFailEnd(ParseTree[] children) -{ +auto maxFailEnd(ParseTree)(ParseTree[] children) if (isParseTree!ParseTree) { return children.map!(c => c.failEnd).maxElement; } -auto maxEnd(ParseTree[] children) -{ +auto maxEnd(ParseTree)(ParseTree[] children) if (isParseTree!ParseTree) { return children.map!(c => c.end).maxElement; } @@ -1401,8 +1300,7 @@ auto maxEnd(ParseTree[] children) // moved into its children, the successful is set to false, the end is set the its failEnd, // the failEnd is reset, and all that info is propagated upwards the tree so intermediate // nodes reflect the proper state. -bool failedChildFixup(ref ParseTree p, size_t failEnd) -{ +bool failedChildFixup(ParseTree)(ref ParseTree p, size_t failEnd) if (isParseTree!ParseTree) { if (p.failedChild.length > 0) { p.children ~= p.failedChild[0]; @@ -1431,17 +1329,17 @@ bool failedChildFixup(ref ParseTree p, size_t failEnd) } } -unittest // 'and' unit test +@safe unittest // 'and' unit test { - alias literal!"abc" abc; - alias literal!"de" de; - alias literal!"f" f; - - alias and!(abc) abcAnd; - alias and!(abc,de) abcde; - alias and!(abc,de,f) abcdef; - alias and!(eps, abc, eps, de, eps, f, eps) withEps; + mixin DefaultPatters!ParseTree; + alias abc= ParseTree.literal!"abc"; + alias de = ParseTree.literal!"de"; + alias f = ParseTree.literal!"f"; + alias abcAnd = and!(abc); + alias abcde = and!(abc,de); + alias abcdef = and!(abc,de,f); + alias withEps = and!(eps, abc, eps, de, eps, f, eps); //assert(getName!(abcAnd)() == `and!(literal!("abc"))`); //assert(getName!(abcde)() == `and!(literal!("abc"), literal!("de"))`); //assert(getName!(abcdef)() == `and!(literal!("abc"), literal!("de"), literal!("f"))`); @@ -1459,27 +1357,27 @@ unittest // 'and' unit test assert(result.successful, "and!('abc','de') parses 'abcdefghi'"); assert(result.matches == ["abc","de"], - "and!('abc','de') matches 'abc' and 'de' at the beginning of 'abcdefghi'"); + "and!('abc','de') matches 'abc' and 'de' at the beginning of 'abcdefghi'"); assert(result.end == input.end+5, "and!('abc','de') advances the index by 3+2 positions."); assert(result.children == [abc(input), de(abc(input))], - "and!('abc','de') has two children, created by 'abc' and 'de'."); + "and!('abc','de') has two children, created by 'abc' and 'de'."); result = abcdef(input); assert(result.successful, "and!('abc','de','f') parses 'abcdefghi'"); assert(result.matches == ["abc","de","f"], - "and!('abc','de','f') matches 'abcdef' at the beginning of 'abcdefghi'"); + "and!('abc','de','f') matches 'abcdef' at the beginning of 'abcdefghi'"); assert(result.end == input.end+6, "and!('abc','de','f') advances the index by 3+2+1 positions."); assert(result.children == [abc(input), de(abc(input)), f(de(abc(input)))] - , "and!('abc','de') has two children, created by 'abc' and 'de'."); + , "and!('abc','de') has two children, created by 'abc' and 'de'."); result = withEps(input); assert(result.successful, "and!('','abc','','de','','f','') parses 'abcdefghi'"); assert(result.matches == ["","abc","","de","","f",""], - "and!('','abc','','de','','f','') matches 'abcdef' at the beginning of 'abcdefghi'"); + "and!('','abc','','de','','f','') matches 'abcdef' at the beginning of 'abcdefghi'"); assert(result.end == input.end+6, - "and!('','abc','','de','','f','') advances the index by 0+3+0+2+0+1+0 positions."); + "and!('','abc','','de','','f','') advances the index by 0+3+0+2+0+1+0 positions."); input.input = "bcdefghi"; @@ -1498,24 +1396,24 @@ unittest // 'and' unit test //assert(result.matches == ["abc"], "Only the first match, from 'abc'."); assert(result.end == input.end+3, "Advances by 3 positions, due to 'abc'"); assert(result.children == [abc(input), de(abc(input))] - , "'abc' 'de' 'f' has two child on 'abc_efghi', the one from 'abc' (success) and the one from 'de' (failure)."); + , "'abc' 'de' 'f' has two child on 'abc_efghi', the one from 'abc' (success) and the one from 'de' (failure)."); } version (unittest) { - static ParseTree getError(ref ParseTree p) { + static ParseTree getError(ParseTree)(ref ParseTree p) if (isParseTree!ParseTree) { if (p.children.length > 0) return getError(p.children[$-1]); return p; } } -unittest // 'and' unit test with zeroOrMore and longest failing match +@safe unittest // 'and' unit test with zeroOrMore and longest failing match { - alias literal!"abc" A; - alias literal!"def" B; - alias literal!"ghi" C; + alias A = ParseTree.literal!"abc"; + alias B = ParseTree.literal!"def"; + alias C = ParseTree.literal!"ghi"; - alias and!(zeroOrMore!(and!(A,B)), C) Thing; + alias Thing = ParseTree.and!(ParseTree.zeroOrMore!(ParseTree.and!(A,B)), C) Thing; ParseTree input = ParseTree("",false,[], "abc"); ParseTree result = Thing(input); @@ -1525,13 +1423,14 @@ unittest // 'and' unit test with zeroOrMore and longest failing match assert(result.matches == []); } -unittest // 'and' unit test with option and longest failing match +@safe unittest // 'and' unit test with option and longest failing match { - alias literal!"abc" A; - alias literal!"def" B; - alias literal!"ghi" C; - alias and!(option!(and!(A,B)), C) Thing; + alias A = ParseTree.literal!"abc"; + alias B = ParseTree.literal!"def"; + alias C = ParseTree.literal!"ghi"; + + alias Thing = ParseTree.and!(ParseTree.option!(ParseTree.and!(A,B)), C); ParseTree input = ParseTree("",false,[], "abc"); ParseTree result = Thing(input); @@ -1541,13 +1440,14 @@ unittest // 'and' unit test with option and longest failing match assert(result.matches == []); } -unittest // 'and' unit test with oneOrMore and longest failing match +@safe unittest // 'and' unit test with oneOrMore and longest failing match { - alias literal!"abc" A; - alias literal!"def" B; - alias literal!"ghi" C; - alias and!(oneOrMore!(and!(A,B)), C) Thing; + alias ParseTree.literal!"abc" A; + alias ParseTree.literal!"def" B; + alias ParseTree.literal!"ghi" C; + + alias Thing = ParseTree.and!(ParseTree.oneOrMore!(ParseTree.and!(A,B)), C); ParseTree input = ParseTree("",false,[], "abcdefabc"); ParseTree result = Thing(input); @@ -1557,216 +1457,216 @@ unittest // 'and' unit test with oneOrMore and longest failing match assert(result.matches == ["abc", "def"]); } -template wrapAround(alias before, alias target, alias after) +template wrapAroundT(ParseTree, alias before, alias target, alias after) { - ParseTree wrapAround(ParseTree p) - { - ParseTree temp = before(p); - if (!temp.successful) - return temp; + ParseTree wrapAroundT(ParseTree p) + { + ParseTree temp = before(p); + if (!temp.successful) + return temp; - ParseTree result = target(temp); - if (!result.successful) - return result; - result.begin = temp.begin; + ParseTree result = target(temp); + if (!result.successful) + return result; + result.begin = temp.begin; - temp = after(result); - if (!temp.successful) - return temp; + temp = after(result); + if (!temp.successful) + return temp; - result.end = temp.end; - return result; - } + result.end = temp.end; + return result; + } - ParseTree wrapAround(string input) - { - return .wrapAround!(before, target, after)(ParseTree("",false,[],input)); - } + ParseTree wrapAroundT(string input) + { + return wrapAroundT!(ParseTree, before, target, after)(ParseTree("",false,[],input)); + } - string wrapAround(GetName g) - { - return "wrapAround!(" ~ getName!(before)() ~ + string wrapAroundT(GetName g) + { + return "wrapAround!(" ~ getName!(before)() ~ ", " ~ getName!(target)() ~ ", " ~ getName!(after)() ~ ")"; - } + } } /** -Basic operator: it matches if one of its subrules (stored in the rules template parameter tuple) match -the input. The subrules are tested in order, from rules[0] to rules[$-1]. - -The matching subrule parse trees is stored as its only child and its matches field -will contain all the subrule matches, in order. - ----- -alias or!(literal!"abc", charRange!('a','z')) rule; // abc or, failing that, any letter between a and z. -ParseTree input = ParseTree("",false,[],"defg"); // low-level plumbing, the rules described here act on ParseTree's not strings. - // It's equivalent to "defg" as input -auto result = rule(input); - -assert(result.successful); // OK -assert(result.matches == ["d"]); // stores the (in this case) only match -assert(result.children.length == 1); // one child, the result of "abc" or [a-z], depending on which rule succeeded. - -input.input = "abc"; // changing the input string; -assert(rule(input)).successful); // Still OK -input.input = "1abc"; -assert(!rule(input)).successful); // NOK, does not begin by abc nor by [a-z] ----- - -If it fails, the last children will contain the failed node that matched furthest (longes match). -That way, when printing, as sort of diagnostic is given: - ----- -alias or!(literal!"abc", and!(literal!"ab", charRange!('0','9'))) rule; // 'abc' or 'ab[0-9]' -ParseTree input = ParseTree("",false,[],"abd"); // equivalent to "abd" - -auto failure = rule(input); -writeln(failure); -/+ -or (failure) - +-and (failure) - +-literal(ab) [0, 2]["ab"] - +-charRange(0,9) failure at line 0, col 2, after "ab" expected a char between '0' and '9', but got "d" -+/ ----- - -So we know 'or' failed, that the 'and' sub-rule had the longest match, matching 'ab' and failing for [0-9] on index 2. + Basic operator: it matches if one of its subrules (stored in the rules template parameter tuple) match + the input. The subrules are tested in order, from rules[0] to rules[$-1]. + + The matching subrule parse trees is stored as its only child and its matches field + will contain all the subrule matches, in order. + + ---- + alias or!(literal!"abc", charRange!('a','z')) rule; // abc or, failing that, any letter between a and z. + ParseTree input = ParseTree("",false,[],"defg"); // low-level plumbing, the rules described here act on ParseTree's not strings. + // It's equivalent to "defg" as input + auto result = rule(input); + + assert(result.successful); // OK + assert(result.matches == ["d"]); // stores the (in this case) only match + assert(result.children.length == 1); // one child, the result of "abc" or [a-z], depending on which rule succeeded. + + input.input = "abc"; // changing the input string; + assert(rule(input)).successful); // Still OK + input.input = "1abc"; + assert(!rule(input)).successful); // NOK, does not begin by abc nor by [a-z] + ---- + + If it fails, the last children will contain the failed node that matched furthest (longes match). + That way, when printing, as sort of diagnostic is given: + + ---- + alias or!(literal!"abc", and!(literal!"ab", charRange!('0','9'))) rule; // 'abc' or 'ab[0-9]' + ParseTree input = ParseTree("",false,[],"abd"); // equivalent to "abd" + + auto failure = rule(input); + writeln(failure); + /+ + or (failure) + +-and (failure) + +-literal(ab) [0, 2]["ab"] + +-charRange(0,9) failure at line 0, col 2, after "ab" expected a char between '0' and '9', but got "d" + +/ + ---- + + So we know 'or' failed, that the 'and' sub-rule had the longest match, matching 'ab' and failing for [0-9] on index 2. */ -template or(rules...) if (rules.length > 0) -{ - string ctfeGetNameOr() - { - string name = "or!("; - foreach(i,rule; rules) - name ~= getName!(rule) +template orT(ParseTree, rules...) if (rules.length > 0) { + @safe { + string ctfeGetNameOr() + { + string name = "or!("; + foreach(i,rule; rules) + name ~= getName!(rule) ~ (i < rules.length -1 ? ", " : ""); - name ~= ")"; - return name; - } - - enum name = ctfeGetNameOr(); - - ParseTree or(ParseTree p) - { - // error-management - ParseTree longestFail = ParseTree(name, false, [], p.input, p.end, 0); - string[] errorStrings; - size_t errorStringChars; - string orErrorString; + name ~= ")"; + return name; + } - ParseTree[rules.length] results; - string[rules.length] names; - size_t[rules.length] failedLength; - size_t maxFailedLength; + enum name = ctfeGetNameOr(); - version (tracer) + ParseTree orT(ParseTree p) { - incTraceLevel(); - } + // error-management + ParseTree longestFail = ParseTree(name, false, [], p.input, p.end, 0); + string[] errorStrings; + size_t errorStringChars; + //string orErrorString; + + ParseTree[rules.length] results; + string[rules.length] names; + size_t[rules.length] failedLength; + size_t maxFailedLength; - // Real 'or' loop - foreach(i,r; rules) - { version (tracer) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(p, name, getName!(r)())); + incTraceLevel(); } - ParseTree temp = r(p); - if (temp.successful) + + // Real 'or' loop + foreach(i,r; rules) { - temp.children = [temp]; - temp.name = name; - // if there is a child that failed but parsed more - if (longestFail.failEnd > temp.end) { - temp.failEnd = longestFail.failEnd; - temp.failedChild = [longestFail]; - } version (tracer) { if (shouldTrace(getName!(r)(), p)) - trace(traceResultMsg(temp, getName!(r)())); - decTraceLevel(); + trace(traceMsg(p, name, getName!(r)())); } - return temp; - } - else - { - version (tracer) + ParseTree temp = r(p); + if (temp.successful) { - if (shouldTrace(getName!(r)(), p)) - trace(traceResultMsg(temp, getName!(r)())); + temp.children = [temp]; + temp.name = name; + // if there is a child that failed but parsed more + if (longestFail.failEnd > temp.end) { + temp.failEnd = longestFail.failEnd; + temp.failedChild = [longestFail]; + } + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceResultMsg(temp, getName!(r)())); + decTraceLevel(); + } + return temp; } - enum errName = " (" ~ getName!(r)() ~")"; - failedLength[i] = temp.end; - if (temp.end >= longestFail.end) + else { - if (temp.end == longestFail.end) - errorStringChars += (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; - else - errorStringChars = (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; - maxFailedLength = temp.end; - longestFail = temp; - names[i] = errName; - results[i] = temp; - + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceResultMsg(temp, getName!(r)())); + } + enum errName = " (" ~ getName!(r)() ~")"; + failedLength[i] = temp.end; + if (temp.end >= longestFail.end) + { + if (temp.end == longestFail.end) + errorStringChars += (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; + else + errorStringChars = (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; + maxFailedLength = temp.end; + longestFail = temp; + names[i] = errName; + results[i] = temp; + + } + // Else, this error parsed less input than another one: we discard it. } - // Else, this error parsed less input than another one: we discard it. } - } - version (tracer) - { - decTraceLevel(); - } + version (tracer) + { + decTraceLevel(); + } - // All subrules failed, we will take the longest match as the result - // If more than one node failed at the same (farthest) position, we concatenate their error messages + // All subrules failed, we will take the longest match as the result + // If more than one node failed at the same (farthest) position, we concatenate their error messages - char[] errString;// = new char[](errorStringChars); - errString.length = errorStringChars; - uint start = 0; - foreach(i; 0..rules.length) - { - if (failedLength[i] == maxFailedLength && results[i].matches.length > 0) + char[] errString;// = new char[](errorStringChars); + errString.length = errorStringChars; + uint start = 0; + foreach(i; 0..rules.length) { - auto temp = results[i]; - auto len = temp.matches[$-1].length; - auto nlen = names[i].length; - errString[start .. start+len] = temp.matches[$-1][]; - errString[start+len .. start+len+names[i].length] = names[i][]; - errString[start+len+nlen .. start+len+nlen+4] = " or "; - start += len + names[i].length + 4; + if (failedLength[i] == maxFailedLength && results[i].matches.length > 0) + { + auto temp = results[i]; + auto len = temp.matches[$-1].length; + auto nlen = names[i].length; + errString[start .. start+len] = temp.matches[$-1][]; + errString[start+len .. start+len+names[i].length] = names[i][]; + errString[start+len+nlen .. start+len+nlen+4] = " or "; + start += len + names[i].length + 4; + } } - } - orErrorString = cast(string)(errString[0..$-4]); + string orErrorString = errString[0..$-4].idup; - longestFail.matches = longestFail.matches.length == 0 ? [orErrorString] : - longestFail.matches[0..$-1] // discarding longestFail error message - ~ [orErrorString]; // and replacing it by the new, concatenated one. - auto children = results[].getUpto(maxFailedLength); - return ParseTree(name, false, longestFail.matches, p.input, p.end, longestFail.end, children, children.maxFailEnd); - } - ParseTree or(string input) - { - return .or!(rules)(ParseTree("",false,[],input)); - } + longestFail.matches = longestFail.matches.length == 0 ? [orErrorString] : + longestFail.matches[0..$-1] // discarding longestFail error message + ~ [orErrorString]; // and replacing it by the new, concatenated one. + auto children = ParseTree.getUpto(results, maxFailedLength); + return ParseTree(name, false, longestFail.matches, p.input, p.end, longestFail.end, children, children.maxFailEnd); + } - string or(GetName g) - { - return name; - } -} + ParseTree orT(string input) + { + return orT!(ParseTree,rules)(ParseTree("",false,[],input)); + } -auto getUpto(ParseTree[] children, size_t minFailedLength) { - return children.filter!(r => max(r.end, r.failEnd) >= minFailedLength).array(); + string orT(GetName g) + { + return name; + } + } } -unittest // 'or' unit test +@safe unittest // 'or' unit test { + + mixin DefaultPatters!ParseTree; alias charRange!('a','b') ab; alias charRange!('c','d') cd; @@ -1813,8 +1713,8 @@ unittest // 'or' unit test assert(!result.successful, "or!([a-b],[c-d]) fails on '_abcdefghi'"); assert(result.end == input.end+0, "or!([a-b],[c-d]) does not advance the index."); assert(result.matches == - [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] - , "or!([a-b],[c-d]) error message. |" ~ result.matches[0]~ "|"); + [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] + , "or!([a-b],[c-d]) error message. |" ~ result.matches[0]~ "|"); input.input = ""; @@ -1823,147 +1723,153 @@ unittest // 'or' unit test assert(!result.successful, "or!([a-b],[c-d]) fails on and empty input"); assert(result.end == input.end+0, "or!([a-b],[c-d]) does not advance the index."); assert(result.matches == - [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] - , "or!([a-b],[c-d]) error message."); + [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] + , "or!([a-b],[c-d]) error message."); } /** -Basic operator: it matches if one of its subrules (stored in the rules template parameter tuple) match -the input. All subrules are tested and the one producing the longest match is taken. + Basic operator: it matches if one of its subrules (stored in the rules template parameter tuple) match + the input. All subrules are tested and the one producing the longest match is taken. -The longest matching subrule's parse tree is stored as its only child and its matches field -will contain all the subrule matches, in order. + The longest matching subrule's parse tree is stored as its only child and its matches field + will contain all the subrule matches, in order. */ -template longest_match(rules...) if (rules.length > 0) +template longest_matchT(ParseTree, rules...) if (rules.length > 0) { - string ctfeGetNameOr() - { - string name = "longest_match!("; - foreach(i,rule; rules) - name ~= getName!(rule) + @safe { + string ctfeGetNameOr() + { + string name = "longest_match!("; + foreach(i,rule; rules) + name ~= getName!(rule) ~ (i < rules.length -1 ? ", " : ""); - name ~= ")"; - return name; - } - - enum name = ctfeGetNameOr(); - - ParseTree longest_match(ParseTree p) - { - // error-management - ParseTree longest, longestFail = ParseTree(name, false, [], p.input, p.end, 0); - string[] errorStrings; - size_t errorStringChars; - string orErrorString; + name ~= ")"; + return name; + } - ParseTree[rules.length] results; - string[rules.length] names; - size_t[rules.length] failedLength; - size_t maxFailedLength; + enum name = ctfeGetNameOr(); - version (tracer) + ParseTree longest_matchT(ParseTree p) { - incTraceLevel(); - } + // error-management + ParseTree longest, longestFail = ParseTree(name, false, [], p.input, p.end, 0); + string[] errorStrings; + size_t errorStringChars; + //string orErrorString; + + ParseTree[rules.length] results; + string[rules.length] names; + size_t[rules.length] failedLength; + size_t maxFailedLength; - // Real 'longest_match' loop - foreach(i,r; rules) - { version (tracer) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(p, name, getName!(r)())); + incTraceLevel(); + } + + // Real 'longest_match' loop + foreach(i,r; rules) + { + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(p, name, getName!(r)())); + } + ParseTree temp = r(p); + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceResultMsg(temp, getName!(r)())); + } + + if (temp.successful) + { + if (temp.end > longest.end) + longest = temp; + // Else, this rule parsed less input than another one: we discard it. + } + else + { + enum errName = " (" ~ getName!(r)() ~")"; + failedLength[i] = temp.end; + if (temp.end >= longestFail.end) + { + maxFailedLength = temp.end; + longestFail = temp; + names[i] = errName; + results[i] = temp; + + if (temp.end == longestFail.end) + errorStringChars += (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; + else + errorStringChars = (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; + } + // Else, this error parsed less input than another one: we discard it. + } } - ParseTree temp = r(p); version (tracer) { - if (shouldTrace(getName!(r)(), p)) - trace(traceResultMsg(temp, getName!(r)())); + decTraceLevel(); } - - if (temp.successful) + if (longest.successful) { - if (temp.end > longest.end) - longest = temp; - // Else, this rule parsed less input than another one: we discard it. + longest.children = [longest]; + longest.name = name; + return longest; } - else + + // All subrules failed, we will take the longest match as the result + // If more than one node failed at the same (farthest) position, we concatenate their error messages + + char[] errString;// = new char[](errorStringChars); + errString.length = errorStringChars; + uint start = 0; + foreach(i; 0..rules.length) { - enum errName = " (" ~ getName!(r)() ~")"; - failedLength[i] = temp.end; - if (temp.end >= longestFail.end) + if (failedLength[i] == maxFailedLength && results[i].matches.length > 0) { - maxFailedLength = temp.end; - longestFail = temp; - names[i] = errName; - results[i] = temp; - - if (temp.end == longestFail.end) - errorStringChars += (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; - else - errorStringChars = (temp.matches.length > 0 ? temp.matches[$-1].length : 0) + errName.length + 4; + auto temp = results[i]; + auto len = temp.matches[$-1].length; + auto nlen = names[i].length; + errString[start .. start+len] = temp.matches[$-1][]; + errString[start+len .. start+len+names[i].length] = names[i][]; + errString[start+len+nlen .. start+len+nlen+4] = " or "; + start += len + names[i].length + 4; } - // Else, this error parsed less input than another one: we discard it. } + (() @trusted { + string orErrorString = cast(string)errString[0..$-4]; + + longestFail.matches = longestFail.matches.length == 0 ? [orErrorString] : + longestFail.matches[0..$-1] // discarding longestFail error message + ~ [orErrorString]; // and replacing it by the new, concatenated one. + })(); + longestFail.name = name; + longestFail.begin = p.end; + return longestFail; } - version (tracer) - { - decTraceLevel(); - } - if (longest.successful) + + ParseTree longest_matchT(string input) { - longest.children = [longest]; - longest.name = name; - return longest; + return orT!(ParseTree, rules)(ParseTree("",false,[],input)); } - // All subrules failed, we will take the longest match as the result - // If more than one node failed at the same (farthest) position, we concatenate their error messages - - char[] errString;// = new char[](errorStringChars); - errString.length = errorStringChars; - uint start = 0; - foreach(i; 0..rules.length) + string longest_matchT(GetName g) { - if (failedLength[i] == maxFailedLength && results[i].matches.length > 0) - { - auto temp = results[i]; - auto len = temp.matches[$-1].length; - auto nlen = names[i].length; - errString[start .. start+len] = temp.matches[$-1][]; - errString[start+len .. start+len+names[i].length] = names[i][]; - errString[start+len+nlen .. start+len+nlen+4] = " or "; - start += len + names[i].length + 4; - } + return name; } - orErrorString = cast(string)(errString[0..$-4]); - - longestFail.matches = longestFail.matches.length == 0 ? [orErrorString] : - longestFail.matches[0..$-1] // discarding longestFail error message - ~ [orErrorString]; // and replacing it by the new, concatenated one. - longestFail.name = name; - longestFail.begin = p.end; - return longestFail; - } - - ParseTree longest_match(string input) - { - return .or!(rules)(ParseTree("",false,[],input)); - } - - string longest_match(GetName g) - { - return name; } } -unittest // 'longest_match' unit test +@safe unittest // 'longest_match' unit test { - alias charRange!('a','b') ab; - alias charRange!('c','d') cd; + mixin DefaultPatters!ParseTree; - alias longest_match!(ab) abOr; - alias longest_match!(ab,cd) abOrcd; + alias ab = charRange!('a','b'); + alias cd = charRange!('c','d'); + + alias abOr = longest_match!(ab); + alias abOrcd = longest_match!(ab,cd); assert(getName!(ab)() == "charRange!('a','b')"); assert(getName!(cd)() == "charRange!('c','d')"); @@ -2007,8 +1913,8 @@ unittest // 'longest_match' unit test assert(!result.successful, "longest_match!([a-b],[c-d]) fails on '_abcdefghi'"); assert(result.end == input.end+0, "longest_match!([a-b],[c-d]) does not advance the index."); assert(result.matches == - [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] - , "longest_match!([a-b],[c-d]) error message. |" ~ result.matches[0]~ "|"); + [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] + , "longest_match!([a-b],[c-d]) error message. |" ~ result.matches[0]~ "|"); input.input = ""; @@ -2017,8 +1923,8 @@ unittest // 'longest_match' unit test assert(!result.successful, "longest_match!([a-b],[c-d]) fails on and empty input"); assert(result.end == input.end+0, "longest_match!([a-b],[c-d]) does not advance the index."); assert(result.matches == - [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] - , "longest_match!([a-b],[c-d]) error message."); + [ "a char between 'a' and 'b' (charRange!('a','b')) or a char between 'c' and 'd' (charRange!('c','d'))"] + , "longest_match!([a-b],[c-d]) error message."); // Now test longest match behaviour: @@ -2031,7 +1937,7 @@ unittest // 'longest_match' unit test /** -Compile-time switch trie from Brian Schott + Compile-time switch trie from Brian Schott */ class Trie(V) : TrieNode!(V) { @@ -2078,11 +1984,11 @@ string printCaseStatements(V)(TrieNode!(V) node, string indentString) put("case '"); switch(k) { - case '\n': append("\\n"); break; - case '\t': append("\\t"); break; - case '\r': append("\\r"); break; - case 92: append("\\"); break; - default: append(to!string(k)); + case '\n': append("\\n"); break; + case '\t': append("\\t"); break; + case '\r': append("\\r"); break; + case 92: append("\\"); break; + default: append(to!string(k)); } append("':\n"); incIndent(); @@ -2143,87 +2049,88 @@ string generateCaseTrie(string[] args ...) } /** -or special case for literal list ("abstract"/"alias"/...) + or special case for literal list ("abstract"/"alias"/...) */ -template keywords(kws...) if (kws.length > 0) +template keywordsT(ParseTree,kws...) if (kws.length > 0) { string ctfeGetNameKeywords() - { - string name= "keywords!("; - foreach(i,kw;kws) - name ~= "\"" ~ kw ~ "\""~ (i < kws.length -1 ? ", " : ""); - name ~= ")"; - return name; - } + { + string name= "keywords!("; + foreach(i,kw;kws) + name ~= "\"" ~ kw ~ "\""~ (i < kws.length -1 ? ", " : ""); + name ~= ")"; + return name; + } string ctfeConcatKeywords() - { - string s = "["; - foreach(i, k; kws) { - s ~= "\"" ~ k ~ "\""; - if (i < kws.length - 1) - s ~= ", "; + string s = "["; + foreach(i, k; kws) + { + s ~= "\"" ~ k ~ "\""; + if (i < kws.length - 1) + s ~= ", "; + } + return s ~= "]"; } - return s ~= "]"; - } enum name = ctfeGetNameKeywords(); enum failString = "one among " ~ ctfeConcatKeywords(); - ParseTree keywords(ParseTree p) - { - string keywordCode(string[] keywords) + ParseTree keywordsT(ParseTree p) { - string result; - foreach(kw; keywords) - result ~= "if (p.end+"~to!string(kw.length) ~ " <= p.input.length " - ~" && p.input[p.end..p.end+"~to!string(kw.length)~"]==`" - ~kw~"`) return ParseTree(`" - ~name~"`,true,[`"~kw~"`],p.input,p.end,p.end+" - ~to!string(kw.length)~");\n"; + string keywordCode(string[] keywords) + { + string result; + foreach(kw; keywords) + result ~= "if (p.end+"~to!string(kw.length) ~ " <= p.input.length " + ~" && p.input[p.end..p.end+"~to!string(kw.length)~"]==`" + ~kw~"`) return ParseTree(`" + ~name~"`,true,[`"~kw~"`],p.input,p.end,p.end+" + ~to!string(kw.length)~");\n"; - result ~= "return ParseTree(`"~name~"`,false,[`" ~ failString ~ "`],p.input,p.end,p.end);"; + result ~= "return ParseTree(`"~name~"`,false,[`" ~ failString ~ "`],p.input,p.end,p.end);"; - return result; - } + return result; + } - static if (KEYWORDS == IFCHAIN) - { - mixin(keywordCode([kws])); - } - else static if (KEYWORDS == TRIE) - { - auto temp = p; - if (p.end < p.input.length) // is this conditional required? + static if (KEYWORDS == IFCHAIN) { - switch(p.input[p.end]) - { - mixin(generateCaseTrie([kws])); - mixin("default: return ParseTree(`"~name~"`,false,[`" ~ failString ~ "`],p.input,p.end,p.end);"); - } + mixin(keywordCode([kws])); } - else + else static if (KEYWORDS == TRIE) { - mixin("return ParseTree(`"~name~"`,false,[`" ~ failString ~ "`],p.input,p.end,p.end);"); + auto temp = p; + if (p.end < p.input.length) // is this conditional required? + { + switch(p.input[p.end]) + { + mixin(generateCaseTrie([kws])); + mixin("default: return ParseTree(`"~name~"`,false,[`" ~ failString ~ "`],p.input,p.end,p.end);"); + } + } + else + { + mixin("return ParseTree(`"~name~"`,false,[`" ~ failString ~ "`],p.input,p.end,p.end);"); + } } } - } - ParseTree keywords(string input) - { - return .keywords!(kws)(ParseTree("",false,[],input)); - } + ParseTree keywordsT(string input) + { + return keywordsT!(ParseTree, kws)(ParseTree("",false,[],input)); + } - string keywords(GetName g) - { - return name; - } + string keywordsT(GetName g) + { + return name; + } } -unittest +@safe unittest { - alias keywords!("abc","de","f") kw; + + alias kw = ParseTree.keywords!("abc","de","f"); assert(getName!(kw)() == `keywords!("abc", "de", "f")`); @@ -2268,102 +2175,103 @@ unittest /** -Tries to match subrule 'r' zero or more times. It always succeeds, since if 'r' fails -from the very beginning, it matched 'r' zero times... - -Its matches are those of its subrules (they might be different for each match) and its -children are all the parse trees returned by the successive application of 'r'. - ----- -alias zeroOrMore!(or!(literal!"abc", literal!"d")) rule; // in PEG-speak: '("abc" / "d")*' -ParseTree input = ParseTree("",false,[], "abcdabce"); - -ParseTree result = rule(input); - -assert(result.successful); -assert(result.matches == ["abc", "d", "abc"]); -assert(result.end == 7); // matched "abcdabce"[0..7] => "abcdabc". "e" at the end is not part of the parse tree. -assert(result.children.length == 3); -writeln(result); -/+ -writes: -zeroOrMore [0, 7]["abc", "d", "abc"] - +-or [0, 3]["abc"] - | +-literal(abc) [0, 3]["abc"] - +-or [3, 4]["d"] - | +-literal(d) [3, 4]["d"] - +-or [4, 7]["abc"] - +-literal(abc) [4, 7]["abc"] -+/ ----- - -So we know the first child used the 'literal!"abc"' sub-rule and matched input[0..3]. -The second matched input[3..4] and the third input[4..7]. - ----- -input = ParseTree("",false,[], "efgh"); -result = rule(input); -assert(result.successful); // succeed, even though all patterns failed. -assert(result.children.length == 0); ----- + Tries to match subrule 'r' zero or more times. It always succeeds, since if 'r' fails + from the very beginning, it matched 'r' zero times... + + Its matches are those of its subrules (they might be different for each match) and its + children are all the parse trees returned by the successive application of 'r'. + + ---- + alias zeroOrMore!(or!(literal!"abc", literal!"d")) rule; // in PEG-speak: '("abc" / "d")*' + ParseTree input = ParseTree("",false,[], "abcdabce"); + + ParseTree result = rule(input); + + assert(result.successful); + assert(result.matches == ["abc", "d", "abc"]); + assert(result.end == 7); // matched "abcdabce"[0..7] => "abcdabc". "e" at the end is not part of the parse tree. + assert(result.children.length == 3); + writeln(result); + /+ + writes: + zeroOrMore [0, 7]["abc", "d", "abc"] + +-or [0, 3]["abc"] + | +-literal(abc) [0, 3]["abc"] + +-or [3, 4]["d"] + | +-literal(d) [3, 4]["d"] + +-or [4, 7]["abc"] + +-literal(abc) [4, 7]["abc"] + +/ + ---- + + So we know the first child used the 'literal!"abc"' sub-rule and matched input[0..3]. + The second matched input[3..4] and the third input[4..7]. + + ---- + input = ParseTree("",false,[], "efgh"); + result = rule(input); + assert(result.successful); // succeed, even though all patterns failed. + assert(result.children.length == 0); + ---- */ -template zeroOrMore(alias r) +template zeroOrMoreT(ParseTree, alias r) { enum name = "zeroOrMore!(" ~ getName!(r) ~ ")"; - ParseTree zeroOrMore(ParseTree p) - { - auto result = ParseTree(name, true, [], p.input, p.end, p.end); - version (tracer) - { - incTraceLevel(); - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(result, name, getName!(r)())); - } - auto temp = r(result); - while(temp.successful - && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules - || temp.name.startsWith("discard!("))) + ParseTree zeroOrMoreT(ParseTree p) { - result.matches ~= temp.matches; - result.children ~= temp; - result.end = temp.end; - result.failEnd = max(result.failEnd, temp.failEnd); + auto result = ParseTree(name, true, [], p.input, p.end, p.end); version (tracer) { + incTraceLevel(); if (shouldTrace(getName!(r)(), p)) trace(traceMsg(result, name, getName!(r)())); } - temp = r(result); - } - auto maxFail = max(temp.failEnd, temp.end); - if (maxFail > result.failEnd && maxFail > result.end) { - result.failedChild = [temp]; - result.failEnd = maxFail; + auto temp = r(result); + while(temp.successful + && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules + || temp.name.startsWith("discard!("))) + { + result.matches ~= temp.matches; + result.children ~= temp; + result.end = temp.end; + result.failEnd = max(result.failEnd, temp.failEnd); + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(result, name, getName!(r)())); + } + temp = r(result); + } + auto maxFail = max(temp.failEnd, temp.end); + if (maxFail > result.failEnd && maxFail > result.end) { + result.failedChild = [temp]; + result.failEnd = maxFail; + } + result.successful = true; + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceResultMsg(result, getName!(r)())); + decTraceLevel(); + } + return result; } - result.successful = true; - version (tracer) + + ParseTree zeroOrMoreT(string input) { - if (shouldTrace(getName!(r)(), p)) - trace(traceResultMsg(result, getName!(r)())); - decTraceLevel(); + return zeroOrMoreT!(ParseTree, r)(ParseTree("",false,[],input)); } - return result; - } - ParseTree zeroOrMore(string input) - { - return .zeroOrMore!(r)(ParseTree("",false,[],input)); - } - - string zeroOrMore(GetName g) - { - return name; - } + string zeroOrMoreT(GetName g) + { + return name; + } } -unittest // 'zeroOrMore' unit test +@safe unittest // 'zeroOrMore' unit test { + mixin DefaultPatters!ParseTree; alias literal!"a" a; alias literal!"abc" abc; alias charRange!('a','z') az; @@ -2428,118 +2336,119 @@ unittest // 'zeroOrMore' unit test } /** -Tries to match subrule 'r' one or more times. If 'r' fails -from the very beginning, it fails and else succeeds. - -Its matches are those of its subrules (they might be different for each match) and its -children are all the parse trees returned by the successive application of 'r'. - ----- -alias oneOrMore!(or!(literal!"abc", literal!"d")) rule; // in PEG-speak: '("abc" / "d")*' -ParseTree input = ParseTree("",false,[], "abcdabce"); - -ParseTree result = rule(input); - -assert(result.successful); -assert(result.matches == ["abc", "d", "abc"]); -assert(result.end == 7); // matched "abcdabce"[0..7] => "abcdabc". "e" at the end is not part of the parse tree. -assert(result.children.length == 3); -writeln(result); -/+ -writes: -oneOrMore [0, 7]["abc", "d", "abc"] - +-or [0, 3]["abc"] - | +-literal(abc) [0, 3]["abc"] - +-or [3, 4]["d"] - | +-literal(d) [3, 4]["d"] - +-or [4, 7]["abc"] - +-literal(abc) [4, 7]["abc"] -+/ ----- - -So we know the first child used the 'literal!"abc"' sub-rule and matched input[0..3]. -The second matched input[3..4] and the third input[4..7]. - ----- -input = ParseTree("",false,[], "efgh"); -result = rule(input); -assert(!result.successful); // fails, since it failed on the first try. ----- + Tries to match subrule 'r' one or more times. If 'r' fails + from the very beginning, it fails and else succeeds. + + Its matches are those of its subrules (they might be different for each match) and its + children are all the parse trees returned by the successive application of 'r'. + + ---- + alias oneOrMore!(or!(literal!"abc", literal!"d")) rule; // in PEG-speak: '("abc" / "d")*' + ParseTree input = ParseTree("",false,[], "abcdabce"); + + ParseTree result = rule(input); + + assert(result.successful); + assert(result.matches == ["abc", "d", "abc"]); + assert(result.end == 7); // matched "abcdabce"[0..7] => "abcdabc". "e" at the end is not part of the parse tree. + assert(result.children.length == 3); + writeln(result); + /+ + writes: + oneOrMore [0, 7]["abc", "d", "abc"] + +-or [0, 3]["abc"] + | +-literal(abc) [0, 3]["abc"] + +-or [3, 4]["d"] + | +-literal(d) [3, 4]["d"] + +-or [4, 7]["abc"] + +-literal(abc) [4, 7]["abc"] + +/ + ---- + + So we know the first child used the 'literal!"abc"' sub-rule and matched input[0..3]. + The second matched input[3..4] and the third input[4..7]. + + ---- + input = ParseTree("",false,[], "efgh"); + result = rule(input); + assert(!result.successful); // fails, since it failed on the first try. + ---- */ -template oneOrMore(alias r) +template oneOrMoreT(ParseTree, alias r) { enum name = "oneOrMore!(" ~ getName!(r) ~ ")"; - ParseTree oneOrMore(ParseTree p) - { - auto result = ParseTree(name, false, [], p.input, p.end, p.end); - version (tracer) + ParseTree oneOrMoreT(ParseTree p) { - incTraceLevel(); - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(result, name, getName!(r)())); - } - auto temp = r(result); + auto result = ParseTree(name, false, [], p.input, p.end, p.end); + version (tracer) + { + incTraceLevel(); + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(result, name, getName!(r)())); + } + auto temp = r(result); - if (!temp.successful) - { - result.matches = temp.matches; - result.children = [temp]; - result.end = temp.end; - } - else - { - while( temp.successful - && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules - || temp.name.startsWith("discard!("))) + if (!temp.successful) { - result.matches ~= temp.matches; - result.children ~= temp; + result.matches = temp.matches; + result.children = [temp]; result.end = temp.end; - result.failEnd = max(result.failEnd, temp.failEnd); - version (tracer) + } + else + { + while( temp.successful + && (temp.begin < temp.end // To avoid infinite loops on epsilon-matching rules + || temp.name.startsWith("discard!("))) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(result, name, getName!(r)())); + result.matches ~= temp.matches; + result.children ~= temp; + result.end = temp.end; + result.failEnd = max(result.failEnd, temp.failEnd); + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(result, name, getName!(r)())); + } + temp = r(result); } - temp = r(result); + auto maxFail = max(temp.failEnd, temp.end); + if (maxFail > result.failEnd && maxFail > result.end) { + result.failedChild = [temp]; + result.failEnd = maxFail; + } + result.successful = true; } - auto maxFail = max(temp.failEnd, temp.end); - if (maxFail > result.failEnd && maxFail > result.end) { - result.failedChild = [temp]; - result.failEnd = maxFail; + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceResultMsg(result, getName!(r)())); + decTraceLevel(); } - result.successful = true; + return result; } - version (tracer) + + ParseTree oneOrMoreT(string input) { - if (shouldTrace(getName!(r)(), p)) - trace(traceResultMsg(result, getName!(r)())); - decTraceLevel(); + return oneOrMoreT!(ParseTree, r)(ParseTree("",false,[],input)); } - return result; - } - ParseTree oneOrMore(string input) - { - return .oneOrMore!(r)(ParseTree("",false,[],input)); - } - - string oneOrMore(GetName g) - { - return name; - } + string oneOrMoreT(GetName g) + { + return name; + } } -unittest // 'oneOrMore' unit test +@safe unittest // 'oneOrMore' unit test { - alias literal!"a" a; - alias literal!"abc" abc; - alias charRange!('a','z') az; + mixin DefaultPatters!(ParseTree, [q{literal}, q{charRange}, q{oneOrMore}]); + alias a = literal!"a"; + alias abc = literal!"abc"; + alias az = charRange!('a','z'); - alias oneOrMore!(a) as; - alias oneOrMore!(abc) abcs; - alias oneOrMore!(az) azs; + alias as = oneOrMore!(a); + alias abcs = oneOrMore!(abc); + alias azs = oneOrMore!(az); assert(getName!(as)() == `oneOrMore!(literal!("a"))`); assert(getName!(abcs)() == `oneOrMore!(literal!("abc"))`); @@ -2598,51 +2507,52 @@ unittest // 'oneOrMore' unit test } /** -Given a subrule 'r', represents the expression 'r?'. It tries to match 'r' and if this matches -successfully, it returns this match. If 'r' failed, 'r?' is still a success, but without any child nor match. - ----- -alias option!(literal!"abc") rule; // Aka '"abc"?' -ParseTree input = ParseTree("",false,[],"abcd"); - -ParseTree result = rule(input); -assert(result.successful); -assert(result.matches == ["abc"]); -assert(result.children.length == 1); -assert(result.children[0] == literal!"abc"(input)); ----- + Given a subrule 'r', represents the expression 'r?'. It tries to match 'r' and if this matches + successfully, it returns this match. If 'r' failed, 'r?' is still a success, but without any child nor match. + + ---- + alias option!(literal!"abc") rule; // Aka '"abc"?' + ParseTree input = ParseTree("",false,[],"abcd"); + + ParseTree result = rule(input); + assert(result.successful); + assert(result.matches == ["abc"]); + assert(result.children.length == 1); + assert(result.children[0] == literal!"abc"(input)); + ---- */ -template option(alias r) +template optionT(ParseTree, alias r) { enum name = "option!(" ~ getName!(r) ~ ")"; - ParseTree option(ParseTree p) - { - version (tracer) + ParseTree optionT(ParseTree p) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(p, name, getName!(r)())); + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(p, name, getName!(r)())); + } + ParseTree result = r(p); + if (result.successful) + return ParseTree(name, true, result.matches, result.input, result.begin, result.end, [result], result.failEnd); + else + return ParseTree(name, true, [], p.input, p.end, p.end, null, max(result.end,result.failEnd), [result]); } - ParseTree result = r(p); - if (result.successful) - return ParseTree(name, true, result.matches, result.input, result.begin, result.end, [result], result.failEnd); - else - return ParseTree(name, true, [], p.input, p.end, p.end, null, max(result.end,result.failEnd), [result]); - } - ParseTree option(string input) - { - return .option!(r)(ParseTree("",false,[],input)); - } + ParseTree optionT(string input) + { + return optionT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string option(GetName g) - { - return name; - } + string optionT(GetName g) + { + return name; + } } -unittest // 'option' unit test +@safe unittest // 'option' unit test { + mixin DefaultPatters!(ParseTree, [q{literal}, q{option}]); alias literal!"a" a; alias literal!"abc" abc; @@ -2703,45 +2613,47 @@ unittest // 'option' unit test } /** -Tries 'r' on the input. If it succeeds, the rule also succeeds, without consuming any input. -If 'r' fails, then posLookahead!r also fails. Low-level implementation of '&r'. + Tries 'r' on the input. If it succeeds, the rule also succeeds, without consuming any input. + If 'r' fails, then posLookahead!r also fails. Low-level implementation of '&r'. */ -template posLookahead(alias r) +template posLookaheadT(ParseTree, alias r) { enum name = "posLookahead!(" ~ getName!(r) ~ ")"; - ParseTree posLookahead(ParseTree p) - { - version (tracer) + ParseTree posLookaheadT(ParseTree p) + { + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(p, name, getName!(r)())); + } + ParseTree temp = r(p); + if (temp.successful) + return ParseTree(name, temp.successful, [], p.input, p.end, p.end); + else + return ParseTree(name, temp.successful, [temp.matches[$-1]], p.input, p.end, p.end); + } + + ParseTree posLookaheadT(string input) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(p, name, getName!(r)())); + return posLookaheadT!(ParseTree, r)(ParseTree("",false,[],input)); } - ParseTree temp = r(p); - if (temp.successful) - return ParseTree(name, temp.successful, [], p.input, p.end, p.end); - else - return ParseTree(name, temp.successful, [temp.matches[$-1]], p.input, p.end, p.end); - } - ParseTree posLookahead(string input) - { - return .posLookahead!(r)(ParseTree("",false,[],input)); - } - - string posLookahead(GetName g) - { - return name; - } + string posLookaheadT(GetName g) + { + return name; + } } -unittest // 'posLookahead' unit test +@safe unittest // 'posLookahead' unit test { - alias literal!"a" a; - alias literal!"abc" abc; + mixin DefaultPatters!(ParseTree, [q{literal}, q{posLookahead}]); + + alias a = literal!"a"; + alias abc = literal!"abc"; - alias posLookahead!(a) a_; - alias posLookahead!(abc) abc_; + alias a_ = posLookahead!(a); + alias abc_ = posLookahead!(abc); assert(getName!(a_)() == `posLookahead!(literal!("a"))`); assert(getName!(abc_)() == `posLookahead!(literal!("abc"))`); @@ -2794,45 +2706,48 @@ unittest // 'posLookahead' unit test } /** -Tries 'r' on the input. If it fails, the rule succeeds, without consuming any input. -If 'r' succeeds, then negLookahead!r fails. Low-level implementation of '!r'. + Tries 'r' on the input. If it fails, the rule succeeds, without consuming any input. + If 'r' succeeds, then negLookahead!r fails. Low-level implementation of '!r'. */ -template negLookahead(alias r) +template negLookaheadT(ParseTree, alias r) { enum name = "negLookahead!(" ~ getName!(r) ~ ")"; - ParseTree negLookahead(ParseTree p) - { - version (tracer) + ParseTree negLookaheadT(ParseTree p) { - if (shouldTrace(getName!(r)(), p)) - trace(traceMsg(p, name, getName!(r)())); + version (tracer) + { + if (shouldTrace(getName!(r)(), p)) + trace(traceMsg(p, name, getName!(r)())); + } + + ParseTree temp = r(p); + if (temp.successful) + return ParseTree(name, false, ["anything but \"" ~ p.input[temp.begin..temp.end] ~ "\""], p.input, p.end, p.end); + else + return ParseTree(name, true, [], p.input, p.end, p.end); } - ParseTree temp = r(p); - if (temp.successful) - return ParseTree(name, false, ["anything but \"" ~ p.input[temp.begin..temp.end] ~ "\""], p.input, p.end, p.end); - else - return ParseTree(name, true, [], p.input, p.end, p.end); - } - ParseTree negLookahead(string input) - { - return .negLookahead!(r)(ParseTree("",false,[],input)); - } + ParseTree negLookaheadT(string input) + { + return negLookaheadT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string negLookahead(GetName g) - { - return name; - } + string negLookaheadT(GetName g) + { + return name; + } } -unittest // 'negLookahead' unit test +@safe unittest // 'negLookahead' unit test { - alias literal!"a" a; - alias literal!"abc" abc; + mixin DefaultPatters!(ParseTree, [q{literal}, q{negLookahead}]); - alias negLookahead!(a) a_; - alias negLookahead!(abc) abc_; + alias a = literal!"a"; + alias abc = literal!"abc"; + + alias a_ = negLookahead!(a); + alias abc_ = negLookahead!(abc); assert(getName!(a_)() == `negLookahead!(literal!("a"))`); assert(getName!(abc_)() == `negLookahead!(literal!("abc"))`); @@ -2885,23 +2800,23 @@ unittest // 'negLookahead' unit test } /** -Internal helper template, to get a parse tree node with a name. For example, given: ----- -alias or!(literal!("abc"), charRange!('0','9')) myRule; ----- + Internal helper template, to get a parse tree node with a name. For example, given: + ---- + alias or!(literal!("abc"), charRange!('0','9')) myRule; + ---- -myRule gives nodes named "or", since its the parent rule. If you want nodes to be named "myRule", -use named. named just overwrites the original root node name, the children are left untouched. + myRule gives nodes named "or", since its the parent rule. If you want nodes to be named "myRule", + use named. named just overwrites the original root node name, the children are left untouched. -See_Also: defined. + See_Also: defined. ----- -alias or!(literal!("abc"), charRange!('0','9')) rule; -alias named!(rule, "myRule") myRule; + ---- + alias or!(literal!("abc"), charRange!('0','9')) rule; + alias named!(rule, "myRule") myRule; -auto input = "abc3"; -auto p1 = rule(input); -auto p2 = myRule(input); + auto input = "abc3"; + auto p1 = rule(input); + auto p2 = myRule(input); // They are both successful assert(p1.successful && p2.successful); @@ -2914,30 +2829,32 @@ assert(p2.children == p1.children); ---- */ -template named(alias r, string name) +template namedT(ParseTree, alias r, string name) { - ParseTree named(ParseTree p) - { - ParseTree result = r(p); - result.name = name; - return result; - } + ParseTree namedT(ParseTree p) + { + ParseTree result = r(p); + result.name = name; + return result; + } - ParseTree named(string input) - { - return .named!(r,name)(ParseTree("",false,[],input)); - } + ParseTree namedT(string input) + { + return namedT!(ParseTree, r, name)(ParseTree("",false,[],input)); + } - string named(GetName g) - { - return name; - } + string namedT(GetName g) + { + return name; + } } -unittest // 'named' unit test +@safe unittest // 'named' unit test { - alias or!(literal!("abc"), charRange!('0','9')) rule; - alias named!(rule, "myRule") myRule; + mixin DefaultPatters!(ParseTree, [q{literal}, q{or}, q{named}, q{charRange}]); + + alias rule = or!(literal!("abc"), charRange!('0','9')); + alias myRule = named!(rule, "myRule"); assert(getName!(rule)() == `or!(literal!("abc"), charRange!('0','9'))`); assert(getName!(myRule)() == "myRule"); @@ -2966,24 +2883,24 @@ unittest // 'named' unit test } /** -Internal helper template, to get a parse tree node with a name, while keeping the original node (see also named). -For example, given: ----- -alias or!(literal!("abc"), charRange!('0','9')) myRule; ----- + Internal helper template, to get a parse tree node with a name, while keeping the original node (see also named). + For example, given: + ---- + alias or!(literal!("abc"), charRange!('0','9')) myRule; + ---- -myRule gives nodes named "or", since its the parent rule. If you want nodes to be named "myRule", -use defined. Contrary to named (see before), the original node is pushed as the child. + myRule gives nodes named "or", since its the parent rule. If you want nodes to be named "myRule", + use defined. Contrary to named (see before), the original node is pushed as the child. -See_Also: named. + See_Also: named. ----- -alias or!(literal!("abc"), charRange!('0','9')) rule; -alias defined!(rule, "myRule") myRule; + ---- + alias or!(literal!("abc"), charRange!('0','9')) rule; + alias defined!(rule, "myRule") myRule; -auto input = "abc3"; -auto p1 = rule(input); -auto p2 = myRule(input); + auto input = "abc3"; + auto p1 = rule(input); + auto p2 = myRule(input); // They are both successful assert(p1.successful && p2.successful); @@ -2995,31 +2912,33 @@ assert(p2.name == `myRule`); assert(p2.children[0] == p1); ---- */ -template defined(alias r, string name) +template definedT(ParseTree, alias r, string name) { - ParseTree defined(ParseTree p) - { - ParseTree result = r(p); - result.children = [result]; - result.name = name; - return result; - } + ParseTree definedT(ParseTree p) + { + ParseTree result = r(p); + result.children = [result]; + result.name = name; + return result; + } - ParseTree defined(string input) - { - return .defined!(r,name)(ParseTree("",false,[],input)); - } + ParseTree definedT(string input) + { + return definedT!(ParseTree, r,name)(ParseTree("",false,[],input)); + } - string defined(GetName g) - { - return name; - } + string definedT(GetName g) + { + return name; + } } -unittest // 'defined' unit test +@safe unittest // 'defined' unit test { - alias or!(literal!("abc"), charRange!('0','9')) rule; - alias defined!(rule, "myRule") myRule; + mixin DefaultPatters!(ParseTree, [q{literal}, q{or}, q{named}, q{charRange}, q{defined}]); + + alias rule = or!(literal!("abc"), charRange!('0','9')); + alias myRule = defined!(rule, "myRule"); assert(getName!(rule)() == `or!(literal!("abc"), charRange!('0','9'))`); assert(getName!(myRule)() == "myRule"); @@ -3048,36 +2967,37 @@ unittest // 'defined' unit test } /** -Low-level representation for the expression 'r {act}'. That is, it applies rule 'r' -on the input and then calls 'act' on the resulting ParseTree. + Low-level representation for the expression 'r {act}'. That is, it applies rule 'r' + on the input and then calls 'act' on the resulting ParseTree. */ -template action(alias r, alias act) +template actionT(ParseTree, alias r, alias act) { - ParseTree action(ParseTree p) - { - return act(r(p)); - } + ParseTree actionT(ParseTree p) + { + return act(r(p)); + } - ParseTree action(string input) - { - return .action!(r,act)(ParseTree("",false,[],input)); - } + ParseTree actionT(string input) + { + return actionT!(ParseTree, r,act)(ParseTree("",false,[],input)); + } - string action(GetName g) - { - enum name = "action!("~ getName!(r)() ~ ", " ~ __traits(identifier, act) ~ ")"; - return name; - } + string actionT(GetName g) + { + enum name = "action!("~ getName!(r)() ~ ", " ~ __traits(identifier, act) ~ ")"; + return name; + } } -unittest // 'action' unit test +@safe unittest // 'action' unit test { + mixin DefaultPatters!(ParseTree, [q{literal}, q{action}]); + ParseTree foo(ParseTree p) { p.matches ~= p.matches; // doubling matches return p; } - alias literal!("abc") abc; alias action!(abc, foo) abcfoo; @@ -3107,40 +3027,42 @@ unittest // 'action' unit test } /** -Concatenates a ParseTree's matches as one match and discards its children. Equivalent to the expression '~r'. + Concatenates a ParseTree's matches as one match and discards its children. Equivalent to the expression '~r'. */ -template fuse(alias r) +template fuseT(ParseTree, alias r) { - ParseTree fuse(ParseTree p) - { - p = r(p); - if(p.successful) + ParseTree fuseT(ParseTree p) { - if (p.matches.length != 0) - p.matches = [std.array.join(p.matches)]; + p = r(p); + if(p.successful) + { + if (p.matches.length != 0) + p.matches = [std.array.join(p.matches)]; - p.children = null; // also discard children + p.children = null; // also discard children + } + return p; } - return p; - } - ParseTree fuse(string input) - { - return .fuse!(r)(ParseTree("",false,[],input)); - } + ParseTree fuseT(string input) + { + return fuseT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string fuse(GetName g) - { - enum name = "fuse!(" ~ getName!(r)() ~ ")"; - return name; - } + string fuseT(GetName g) + { + enum name = "fuse!(" ~ getName!(r)() ~ ")"; + return name; + } } -unittest // 'fuse' unit test +@safe unittest // 'fuse' unit test { - alias oneOrMore!(literal!("abc")) abcs; + mixin DefaultPatters!(ParseTree, [q{literal}, q{oneOrMore}, q{fuse}, q{discard}]); + + alias abcs = oneOrMore!(literal!("abc")); - alias fuse!(abcs) f; + alias f = fuse!(abcs); assert(getName!(f) == `fuse!(oneOrMore!(literal!("abc")))`); @@ -3166,8 +3088,8 @@ unittest // 'fuse' unit test assert(result.end == reference.end); assert(result.children == reference.children); - alias discard!(literal!("abc")) dabc; - alias fuse!(dabc) f2; + alias dabc = discard!(literal!("abc")); + alias f2 = fuse!(dabc); result = f2("abcabc"); reference = dabc("abcabc"); @@ -3180,89 +3102,91 @@ unittest // 'fuse' unit test } /** -Calls 'r' on the input and then discards its children nodes. + Calls 'r' on the input and then discards its children nodes. */ -template discardChildren(alias r) +template discardChildrenT(ParseTree, alias r) { - ParseTree discardChildren(ParseTree p) - { - p = r(p); - p.children = null; - return p; - } + ParseTree discardChildrenT(ParseTree p) + { + p = r(p); + p.children = null; + return p; + } - ParseTree discardChildren(string input) - { - return .discardChildren!(r)(ParseTree("",false,[],input)); - } + ParseTree discardChildrenT(string input) + { + return .discardChildrenT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string discardChildren(GetName g) - { - enum name = "discardChildren!(" ~ getName!(r)() ~ ")"; - return name; - } + string discardChildrenT(GetName g) + { + enum name = "discardChildren!(" ~ getName!(r)() ~ ")"; + return name; + } } /** -Calls 'r' on the input and then discards its matches. + Calls 'r' on the input and then discards its matches. */ -template discardMatches(alias r) +template discardMatchesT(ParseTree, alias r) { - ParseTree discardMatches(ParseTree p) - { - p = r(p); - if (p.successful) - p.matches = null; - return p; - } + ParseTree discardMatchesT(ParseTree p) + { + p = r(p); + if (p.successful) + p.matches = null; + return p; + } - ParseTree discardMatches(string input) - { - return .discardMatches!(r)(ParseTree("",false,[],input)); - } + ParseTree discardMatchesT(string input) + { + return discardMatchesT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string discardMatches(GetName g) - { - enum name = "discardMatches!(" ~ getName!(r)() ~ ")"; - return name; - } + string discardMatchesT(GetName g) + { + enum name = "discardMatches!(" ~ getName!(r)() ~ ")"; + return name; + } } /** -Calls 'r' on the input and then discard everything 'r' returned: no children, no match and index -put at the end of the match. It's the low-level engine behind ':r'. + Calls 'r' on the input and then discard everything 'r' returned: no children, no match and index + put at the end of the match. It's the low-level engine behind ':r'. */ -template discard(alias r) +template discardT(ParseTree, alias r) { - ParseTree discard(ParseTree p) - { - ParseTree result = r(p); - result.name = "discard!(" ~ getName!(r)() ~ ")"; - //result.begin = result.end; - result.children = null; - if (result.successful) - result.matches = null;//to keep error messages, if any + ParseTree discardT(ParseTree p) + { + ParseTree result = r(p); + result.name = "discard!(" ~ getName!(r)() ~ ")"; + //result.begin = result.end; + result.children = null; + if (result.successful) + result.matches = null;//to keep error messages, if any - return result; - } + return result; + } - ParseTree discard(string input) - { - return .discard!(r)(ParseTree("",false,[],input)); - } + ParseTree discardT(string input) + { + return discardT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string discard(GetName g) - { - return "discard!(" ~ getName!(r)() ~ ")"; - } + string discardT(GetName g) + { + return "discard!(" ~ getName!(r)() ~ ")"; + } } -unittest // 'discard' unit test +@safe unittest // 'discard' unit test { - alias literal!"abc" abc; - alias oneOrMore!abc abcs; - alias discard!(literal!("abc")) dabc; - alias discard!(oneOrMore!(literal!("abc")))dabcs; + mixin DefaultPatters!(ParseTree, [q{literal}, q{oneOrMore}, q{discard}, q{and}]); + + alias abc = literal!"abc"; + alias abcs = oneOrMore!abc; + alias dabc = discard!(literal!("abc")); + alias dabcs = discard!(oneOrMore!(literal!("abc"))); ParseTree reference = abc("abc"); ParseTree result =dabc("abc"); @@ -3299,7 +3223,7 @@ unittest // 'discard' unit test assert(result.children is null); // Action on 'and' - alias and!(abc,dabc,abc) discardMiddle; + alias discardMiddle = and!(abc,dabc,abc) discardMiddle; result = discardMiddle("abcabcabc"); assert(result.successful); @@ -3311,38 +3235,40 @@ unittest // 'discard' unit test } /** -Calls 'r' on the input and then discards everything 'r' did, except its matches (so that -they propagate upwards). Equivalent to ';r'. + Calls 'r' on the input and then discards everything 'r' did, except its matches (so that + they propagate upwards). Equivalent to ';r'. */ -template drop(alias r) +template dropT(ParseTree, alias r) { - ParseTree drop(ParseTree p) - { - ParseTree result = r(p); - //result.begin = result.end; - result.children = null; - if (result.successful) - result.name = "drop!(" ~ getName!(r)() ~ ")"; - return result; - } + ParseTree dropT(ParseTree p) + { + ParseTree result = r(p); + //result.begin = result.end; + result.children = null; + if (result.successful) + result.name = "drop!(" ~ getName!(r)() ~ ")"; + return result; + } - ParseTree drop(string input) - { - return .drop!(r)(ParseTree("",false,[],input)); - } + ParseTree dropT(string input) + { + return dropT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string drop(GetName g) - { - return "drop!(" ~ getName!(r)() ~ ")"; - } + string dropT(GetName g) + { + return "drop!(" ~ getName!(r)() ~ ")"; + } } -unittest // 'drop' unit test +@safe unittest // 'drop' unit test { - alias literal!"abc" abc; - alias oneOrMore!abc abcs; - alias drop!(literal!("abc")) dabc; - alias drop!(oneOrMore!(literal!("abc"))) dabcs; + mixin DefaultPatters!(ParseTree, [q{literal}, q{charRange}, q{drop}, q{oneOrMore}, q{and}]); + + alias abc = literal!"abc"; + alias abcs = oneOrMore!abc; + alias dabc = drop!(literal!("abc")); + alias dabcs = drop!(oneOrMore!(literal!("abc"))); ParseTree reference = abc("abc"); ParseTree result =dabc("abc"); @@ -3391,86 +3317,87 @@ unittest // 'drop' unit test } /** -Makes r disappear in a sequence, letting its children take its place. It's equivalent -to the '%' operator. Given A <- B %C D and C <- E F, a successful parse for A will -generate a three with four children: B, E, F and D parse trees. + Makes r disappear in a sequence, letting its children take its place. It's equivalent + to the '%' operator. Given A <- B %C D and C <- E F, a successful parse for A will + generate a three with four children: B, E, F and D parse trees. */ -template propagate(alias r) +template propagateT(ParseTree, alias r) { - ParseTree propagate(ParseTree p) - { - ParseTree result = r(p); - if (result.successful) - result.name = "propagate!(" ~ getName!(r)() ~ ")"; - return result; - } + ParseTree propagateT(ParseTree p) + { + ParseTree result = r(p); + if (result.successful) + result.name = "propagate!(" ~ getName!(r)() ~ ")"; + return result; + } - ParseTree propagate(string input) - { - return .propagate!(r)(ParseTree("",false,[],input)); - } + ParseTree propagateT(string input) + { + return propagateT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string propagate(GetName g) - { - return "propagate!(" ~ getName!(r)() ~ ")"; - } + string propagateT(GetName g) + { + return "propagate!(" ~ getName!(r)() ~ ")"; + } } /** -Makes 'r's result be kept when it would be discarded by the tree-decimation done by a grammar. -Equivalent to '^r'. + Makes 'r's result be kept when it would be discarded by the tree-decimation done by a grammar. + Equivalent to '^r'. */ -template keep(alias r) +template keepT(ParseTree, alias r) { - ParseTree keep(ParseTree p) - { - ParseTree result = r(p); - if (result.successful) + ParseTree keepT(ParseTree p) { - result.children = [result]; - result.name = "keep!(" ~ getName!(r)() ~ ")"; + ParseTree result = r(p); + if (result.successful) + { + result.children = [result]; + result.name = "keep!(" ~ getName!(r)() ~ ")"; + } + return result; } - return result; - } - ParseTree keep(string input) - { - return .keep!(r)(ParseTree("",false,[],input)); - } + ParseTree keepT(string input) + { + return keepT!(ParseTree, r)(ParseTree("",false,[],input)); + } - string keep(GetName g) - { - return "keep!(" ~ getName!(r)() ~ ")"; - } + string keepT(GetName g) + { + return "keep!(" ~ getName!(r)() ~ ")"; + } } -unittest // 'keep' unit test +@safe unittest // 'keep' unit test { + mixin DefaultPatters!(ParseTree, [q{literal}, q{and}, q{named}, q{keep}]); // Grammar mimicry - struct KeepTest + static struct KeepTest { static bool isRule(string s) - { - if (s == "A" || s == "KA") - return true; - else - return false; - } + { + if (s == "A" || s == "KA") + return true; + else + return false; + } - mixin decimateTree; + mixin decimateTree!ParseTree; // Equivalent to A <- 'a' 'b' static ParseTree A(string s) - { - return decimateTree(named!(and!(literal!"a", literal!"b"), "A")(s)); - } + { + return decimateTree(named!(and!(literal!"a", literal!"b"), "A")(s)); + } // Here we use keep to protect 'b' // Equivalent to KA <- 'a' ^'b' static ParseTree KA(string s) - { - return decimateTree(named!(and!(literal!"a", keep!(literal!"b")), "KA")(s)); - } + { + return decimateTree(named!(and!(literal!"a", keep!(literal!"b")), "KA")(s)); + } } ParseTree reference = KeepTest.A("abc"); @@ -3486,113 +3413,66 @@ unittest // 'keep' unit test assert(result.children == [literal!("b")(literal!("a")("abc"))], "'b' node was kept."); } -/* ****************** predefined rules ******************** */ - -alias named!(or!(literal!("\r\n"), literal!("\n"), literal!("\r")), "endOfLine") endOfLine; /// predefined end-of-line parser -alias endOfLine eol; /// helper alias. - -alias or!(literal!(" "), literal!("\t"), literal!("\v")) space; /// predefined space-recognizing parser (space or tabulation). -alias named!(literal!"\t", "tab") tab; /// A parser recognizing \t (tabulation) -alias named!(fuse!(discardChildren!(oneOrMore!space)), - "spaces") spaces; /// aka '~space+' -alias or!(space, endOfLine) blank; /// Any blank char (spaces or end of line). -alias named!(discard!(zeroOrMore!blank), - "spacing") spacing; /// The basic space-management parser: discard zero or more blank spaces. - -alias charRange!('0', '9') digit; /// Decimal digit: [0-9] -alias named!(fuse!(discardChildren!(oneOrMore!digit)), "digits") digits; /// [0-9]+ - -alias or!(charRange!('0','9'), charRange!('a','f'), charRange!('A', 'F')) hexDigit; /// Hexadecimal digit: [0-9a-fA-F] - -alias charRange!('a', 'z') alpha; /// [a-z] -alias charRange!('A', 'Z') Alpha; /// [A-Z] - -alias and!(oneOrMore!(or!(alpha, Alpha, literal!("_"))), zeroOrMore!(or!(digit, alpha, Alpha, literal!("_")))) ident; -alias named!(fuse!(discardChildren!ident), - "identifier") identifier; /// [a-zA-Z_][a-zA-Z_0-9]*, the basic C-family identifier -alias named!(fuse!(discardChildren!(and!(identifier, zeroOrMore!(and!(literal!".", identifier))))), - "qualifiedIdentifier") qualifiedIdentifier; /// qualified identifiers (ids separated by dots: abd.def.g). - -alias named!(literal!"/", "slash") slash; /// A parser recognizing '/' -alias named!(literal!"\\", "backslash") backslash; /// A parser recognizing '\' -alias named!(literal!"'", "quote") quote; /// A parser recognizing ' (single quote) -alias named!(literal!"\"", "doublequote") doublequote; /// A parser recognizing " (double quote) -alias named!(literal!"`", "backquote") backquote; /// A parser recognizing $(BACKTICK) (backquote) - -/// A list of elem's separated by sep's. One element minimum. -template list(alias elem, alias sep) -{ - alias named!(spaceAnd!(oneOrMore!blank, and!(elem, zeroOrMore!(spaceAnd!(discardMatches!(sep), elem)))), "list") list; -} - -/// A list of elem's separated by sep's. The empty list (no elem, no sep) is OK. -template list0(alias elem, alias sep) -{ - alias named!(spaceAnd!(oneOrMore!blank, option!(and!(elem, zeroOrMore!(spaceAnd!(discardMatches!(sep), elem))))), "list0") list0; -} - -template AddSpace(alias sp) +template AddSpaceT(ParseTree, alias sp) { - template AddSpace(alias r) + template AddSpaceT(alias r) { - alias TypeTuple!(r, discard!sp) AddSpace; + alias AddSpaceT=TypeTuple!(r, discardT!(ParseTree,sp)); } } /** -The engine formerly behind the '< ' Pegged rule: all sequence subelements of a rule are interspersed -with a space-consuming rule, given as the first template parameter. It's not used by Pegged anymore -but can be useful for low-level code. It might become deprecated, but it's not there yet. + The engine formerly behind the '< ' Pegged rule: all sequence subelements of a rule are interspersed + with a space-consuming rule, given as the first template parameter. It's not used by Pegged anymore + but can be useful for low-level code. It might become deprecated, but it's not there yet. ----- -alias and!(literal!"abc", literal!"def") rule1; // "abc" "def", equivalent to "abcdef" -alias spaceAnd!(oneOrMore!blank, literal!"abc", literal!"def") rule2; // "abc" "def", but with spaces in-between. + ---- + alias and!(literal!"abc", literal!"def") rule1; // "abc" "def", equivalent to "abcdef" + alias spaceAnd!(oneOrMore!blank, literal!"abc", literal!"def") rule2; // "abc" "def", but with spaces in-between. -string input1 = "abcdef"; -string input2 = " abc + string input1 = "abcdef"; + string input2 = " abc -def "; // with spaces and end of line markers. + def "; // with spaces and end of line markers. -assert(rule1(input1).successful); // OK -assert(!rule1(input2).successful); // NOK, couldn't find "def" after "abc" + assert(rule1(input1).successful); // OK + assert(!rule1(input2).successful); // NOK, couldn't find "def" after "abc" -assert(rule2(input1).successful); // OK -assert(rule2(input2).successful); // Still OK -assert(rule2(input2).matches == ["abc","def"]);// rule2 finds the literals among the spaces ----- + assert(rule2(input1).successful); // OK + assert(rule2(input2).successful); // Still OK + assert(rule2(input2).matches == ["abc","def"]);// rule2 finds the literals among the spaces + ---- -As you can see on the previous line, spaceAnd discards the matched spaces -and returns matches only for the 'real' subrules. + As you can see on the previous line, spaceAnd discards the matched spaces + and returns matches only for the 'real' subrules. -Note: by using a non-space rule as the first template argument, -you can use spaceAnd as a generic 'find these patterns, possibly separated by this pattern' rule. + Note: by using a non-space rule as the first template argument, + you can use spaceAnd as a generic 'find these patterns, possibly separated by this pattern' rule. -For example, using digits as separators: ----- -alias spaceAnd!(digit, literal!"abc", litera!"def") rule3; + For example, using digits as separators: + ---- + alias spaceAnd!(digit, literal!"abc", litera!"def") rule3; -ParseTree result = rule3("123abc45def67890"); -assert(rule3.successful); -assert(rule3.matches == ["abc", "def"]); -assert(rule3.children.length == 2); + ParseTree result = rule3("123abc45def67890"); + assert(rule3.successful); + assert(rule3.matches == ["abc", "def"]); + assert(rule3.children.length == 2); -assert(rule3.begin == 0;) -assert(rule3.end == "123abc45def67890".length); ----- + assert(rule3.begin == 0;) + assert(rule3.end == "123abc45def67890".length); + ---- */ -template spaceAnd(alias sp, rules...) -{ - alias and!(discard!(zeroOrMore!sp), staticMap!(AddSpace!(zeroOrMore!sp), rules)) spaceAnd; -} -unittest // 'spaceAnd' unit test +@safe unittest // 'spaceAnd' unit test { - alias literal!"a" a; - alias literal!"b" b; + mixin DefaultPatters!(ParseTree, [q{literal}, q{and}, q{oneOrMore}, q{spaceAnd}, q{blank}, q{digit}]); + + alias a = literal!"a"; + alias b = literal!"b"; //Basic use - alias and!(a,b) ab; - alias spaceAnd!(oneOrMore!blank, a, b) a_b; + alias ab = and!(a,b); + alias a_b = spaceAnd!(oneOrMore!(blank), a, b); ParseTree reference = ab("ab"); ParseTree result = a_b("ab"); @@ -3627,7 +3507,7 @@ unittest // 'spaceAnd' unit test assert(!result.successful); // With another separator than spaces - alias spaceAnd!(digit, a, b) a0b; + alias a0b = spaceAnd!(digit, a, b); assert(a0b("ab").successful); assert(!a0b(" a b ").successful); @@ -3642,83 +3522,83 @@ unittest // 'spaceAnd' unit test } /// Mixin to simplify a parse tree inside a grammar -mixin template decimateTree() +mixin template decimateTree(ParseTree) { static ParseTree decimateTree(ParseTree p) - { - if(p.children.length == 0) return p; + { + if(p.children.length == 0) return p; - bool parseFailed = !p.successful; + bool parseFailed = !p.successful; - ParseTree[] filterChildren(ParseTree pt) - { - ParseTree[] result; - foreach(child; pt.children) + ParseTree[] filterChildren(ParseTree pt) { - import std.algorithm : startsWith; - - if ( (isRule(child.name) && (child.matches.length != 0 || parseFailed)) - || (!child.successful && child.children.length == 0) - || (!child.successful && child.name.startsWith("or!") && child.children.length > 1) - || (!pt.successful && child.successful && child.children.length == 0 && child.failedChild.length > 0)) - { - child.children = filterChildren(child); - result ~= child; - } - else if (child.name.startsWith("keep!(")) // 'keep' node are never discarded. - // They have only one child, the node to keep - { - result ~= child.children[0]; - } - else // discard this node, but see if its children contain nodes to keep + ParseTree[] result; + foreach(child; pt.children) { - result ~= filterChildren(child); + import std.algorithm : startsWith; + + if ( (isRule(child.name) && (child.matches.length != 0 || parseFailed)) + || (!child.successful && child.children.length == 0) + || (!child.successful && child.name.startsWith("or!") && child.children.length > 1) + || (!pt.successful && child.successful && child.children.length == 0 && child.failedChild.length > 0)) + { + child.children = filterChildren(child); + result ~= child; + } + else if (child.name.startsWith("keep!(")) // 'keep' node are never discarded. + // They have only one child, the node to keep + { + result ~= child.children[0]; + } + else // discard this node, but see if its children contain nodes to keep + { + result ~= filterChildren(child); + } } + return result; } - return result; - } - void filterFailedChildren(ref ParseTree pt) - { - foreach(ref child; pt.children) + void filterFailedChildren(ref ParseTree pt) { - filterFailedChildren(child); - import std.algorithm : startsWith; - - if ( (isRule(child.name) && (child.matches.length != 0 || parseFailed)) - || (!child.successful && child.children.length == 0) - || (!child.successful && child.name.startsWith("or!") && child.children.length > 1) - || (!pt.successful && child.successful && child.children.length == 0 && child.failedChild.length > 0)) + foreach(ref child; pt.children) { + filterFailedChildren(child); + import std.algorithm : startsWith; + + if ( (isRule(child.name) && (child.matches.length != 0 || parseFailed)) + || (!child.successful && child.children.length == 0) + || (!child.successful && child.name.startsWith("or!") && child.children.length > 1) + || (!pt.successful && child.successful && child.children.length == 0 && child.failedChild.length > 0)) + { + } + else if (child.name.startsWith("keep!(")) // 'keep' node are never discarded. + // They have only one child, the node to keep + { + } + else if (child.failedChild.length > 0)// discard this node, but see if its children contain nodes to keep + { + pt.failedChild ~= child.failedChild; + child.failedChild = []; + } } - else if (child.name.startsWith("keep!(")) // 'keep' node are never discarded. - // They have only one child, the node to keep + foreach(ref child; pt.failedChild) { + filterFailedChildren(child); + child.children = filterChildren(child); } - else if (child.failedChild.length > 0)// discard this node, but see if its children contain nodes to keep - { - pt.failedChild ~= child.failedChild; - child.failedChild = []; - } - } - foreach(ref child; pt.failedChild) - { - filterFailedChildren(child); - child.children = filterChildren(child); } + if (!p.successful) + filterFailedChildren(p); + p.children = filterChildren(p); + return p; } - if (!p.successful) - filterFailedChildren(p); - p.children = filterChildren(p); - return p; - } } /** -Discard one-child nodes and replace them with their children. -Most grammar tend to produce long one-child/one-child branches, -simplifyTree compacts these. + Discard one-child nodes and replace them with their children. + Most grammar tend to produce long one-child/one-child branches, + simplifyTree compacts these. */ -ParseTree simplifyTree(ParseTree p) +ParseTree simplifyTree(ParseTree)(ParseTree p) { foreach(ref child; p.children) child = simplifyTree(child); @@ -3730,31 +3610,173 @@ ParseTree simplifyTree(ParseTree p) } /** -Returns: the number of nodes in a parse tree. + Returns: the number of nodes in a parse tree. */ -size_t size(ParseTree p) +size_t size(ParseTree)(ParseTree p) { - size_t result = 1; - foreach(child; p.children) - result += size(child); - return result; + size_t result = 1; + foreach(child; p.children) + result += size(child); + return result; } /** -Generic ParseTree modifier: -predicate must be callable with a ParseTree and return a boolean. -modifier must be callable with a ParseTree and return a ParseTree. + Generic ParseTree modifier: + predicate must be callable with a ParseTree and return a boolean. + modifier must be callable with a ParseTree and return a ParseTree. -If predicate is true on input, modify calls modifier on input and return the result. -If not, it continues with the children. + If predicate is true on input, modify calls modifier on input and return the result. + If not, it continues with the children. */ -ParseTree modify(alias predicate, alias modifier)(ParseTree input) +ParseTree modify(ParseTree, alias predicate, alias modifier)(ParseTree input) if (isParseTree!ParseTree) { foreach(ref child; input.children) - child = modify!(predicate, modifier)(child); + child = modify!(ParseTree, predicate, modifier)(child); if (predicate(input)) input = modifier(input); return input; } + +// mixin template ParseCollections(alias ParseTreeT=void) { +// static if (is(ParseTreeT == void)) { +// alias ParseTree = typeof(this); +// } +// else { +// alias ParseTree = ParseTreeT; +// } +// mixin ParseCollectionsM; +// } + +mixin template ParseCollectionsM() { +// static assert(isParseTree!ParseTree, "ParseTreeT must be a isParseTree type"); + @safe: + import pegged.peg; + alias eoi = eoiT!ParseTree; + + alias eps = epsT!ParseTree; + alias any = anyT!ParseTree; + alias fail = failT!ParseTree; + alias literal(string s) = literalT!(ParseTree, s); + alias caseInsensitiveLiteral(string s) = caseInsensitiveLiteralT!(ParseTree, s); + alias charRange(dchar begin, dchar end) = charRangeT!(ParseTree, begin, end); + + alias wrapAround(alias before, alias target, alias after) = wrapAroundT!(ParseTree, before, target, after); + alias and(rules...) = andT!(ParseTree, rules); + alias or(rules...) = orT!(ParseTree, rules); + alias longest_match(rules...) = longest_matchT!(ParseTree, rules); + alias keywords(kws...) = keywordsT!(ParseTree, kws); + alias zeroOrMore(alias r) = zeroOrMoreT!(ParseTree, r); + alias oneOrMore(alias r) = oneOrMoreT!(ParseTree, r); + alias option(alias r) = optionT!(ParseTree, r); + alias posLookahead(alias r) = posLookaheadT!(ParseTree, r); + alias negLookahead(alias r) = negLookaheadT!(ParseTree, r); + alias named(alias r, string name) = namedT!(ParseTree, r, name); + alias defined(alias r, string name)= definedT!(ParseTree, r, name); + alias action(alias r, alias act) = actionT!(ParseTree, r, act); + alias fuse(alias r) = fuseT!(ParseTree, r); + alias discardChildren(alias r) = discardChildrenT!(ParseTree, r); + alias discardMatches(alias r) = discardMatchesT!(ParseTree, r); + alias discard(alias r) = discardT!(ParseTree, r); + alias drop(alias r) = dropT!(ParseTree, r); + alias propagate(alias r) = propagateT!(ParseTree, r); + alias keep(alias r) = keepT!(ParseTree, r); + alias AddSpace(alias sp) = AddSpaceT!(ParseTree, sp); + +// } + +// mixin template DefaultParsePatterns() { + import std.meta : staticMap; + /* ****************** predefined rules ******************** */ + + alias endOfLine = named!(or!(literal!("\r\n"), literal!("\n"), literal!("\r")), "endOfLine"); /// predefined end-of-line parser + alias eol = endOfLine; /// helper alias. + + alias space = or!(literal!(" "), literal!("\t"), literal!("\v")); /// predefined space-recognizing parser (space or tabulation). + alias tab = named!(literal!"\t", "tab"); /// A parser recognizing \t (tabulation) + alias spaces = named!(fuse!(discardChildren!(oneOrMore!space)), + "spaces"); /// aka '~space+' + alias blank = or!(space, endOfLine); /// Any blank char (spaces or end of line). + alias spacing = named!(discard!(zeroOrMore!blank), + "spacing"); /// The basic space-management parser: discard zero or more blank spaces. + + alias digit = charRange!('0', '9'); /// Decimal digit: [0-9] + alias digits = named!(fuse!(discardChildren!(oneOrMore!digit)), "digits"); /// [0-9]+ + + alias hexDigit = or!(charRange!('0','9'), charRange!('a','f'), charRange!('A', 'F')); /// Hexadecimal digit: [0-9a-fA-F] + + alias alpha = charRange!('a', 'z'); /// [a-z] + alias Alpha = charRange!('A', 'Z'); /// [A-Z] + + alias ident = and!(oneOrMore!(or!(alpha, Alpha, literal!("_"))), zeroOrMore!(or!(digit, alpha, Alpha, literal!("_")))); + alias identifier = named!(fuse!(discardChildren!ident), + "identifier"); /// [a-zA-Z_][a-zA-Z_0-9]*, the basic C-family identifier + alias qualifiedIdentifier = named!(fuse!(discardChildren!(and!(identifier, zeroOrMore!(and!(literal!".", identifier))))), + "qualifiedIdentifier"); /// qualified identifiers (ids separated by dots: abd.def.g). + + alias slash = named!(literal!"/", "slash"); /// A parser recognizing '/' + alias backslash = named!(literal!"\\", "backslash"); /// A parser recognizing '\' + alias quote = named!(literal!"'", "quote"); /// A parser recognizing ' (single quote) + alias doublequote = named!(literal!"\"", "doublequote"); /// A parser recognizing " (double quote) + alias backquote = named!(literal!"`", "backquote"); /// A parser recognizing $(BACKTICK) (backquote) + /// A list of elem's separated by sep's. One element minimum. + alias list(alias elem, alias sep) = named!(spaceAnd!(oneOrMore!blank, and!(elem, zeroOrMore!(spaceAnd!(discardMatches!(sep), elem)))), "list"); + +/// A list of elem's separated by sep's. The empty list (no elem, no sep) is OK. + alias list0(alias elem, alias sep) = named!(spaceAnd!(oneOrMore!blank, option!(and!(elem, zeroOrMore!(spaceAnd!(discardMatches!(sep), elem))))), "list0"); + + alias spaceAnd(alias sp, rules...) = and!(discard!(zeroOrMore!sp), staticMap!(AddSpace!(zeroOrMore!sp), rules)); +} + +enum defaultNames =[ + "eol", + "eoi", + "named", + "blank", + "quote", + "doublequote", + "backquote", + "alpha", + "Alpha", + "spacing", + "identifier", + "ident", + "backslash", + "hexDigit", + "endOfLine", + "qualifiedIdentifier", + "literal", + "posLookahead", + "negLookahead", + "option", + "defined", + "eps", + "literal", + "zeroOrMore", + "oneOrMore", + "literal", + "list", + "and", + "or", + "fail", + "fuse", + "digits", + "charRange", + "discard", + "longest_match", + "spaceAnd", + "space", + "digit", + ]; + +/** + Change the namespace of the grammar pattern in the ParseTree to scope if the mixin. + names is the list of the pattern-names inside the ParseTree +*/ +mixin template DefaultPatters(ParseTree, string[] names = defaultNames) { + private import std.format; + static foreach(name; names) { + mixin(format!q{alias %1$s = ParseTree.%1$s;}(name)); + } +} diff --git a/pegged/tester/grammartester.d b/pegged/tester/grammartester.d index 89f2b70a..013732aa 100644 --- a/pegged/tester/grammartester.d +++ b/pegged/tester/grammartester.d @@ -15,7 +15,7 @@ import std.string : stripRight, stripLeft, lineSplitter; import pegged.tester.testerparser; import pegged.grammar; -class GrammarTester(grammar, string startSymbol) +@safe class GrammarTester(grammar, string startSymbol) { bool soft = false; @@ -111,7 +111,7 @@ class GrammarTester(grammar, string startSymbol) return runTest(file, lineNo, textToParse, desiredTreeRepresentation, true); } - static auto getDifferencer(T,P)( auto ref T treeRoot, auto ref P patternRoot ) + static auto getDifferencer(T,P)( auto ref T treeRoot, auto ref P patternRoot ) @trusted { Differencer!(T,P) t; t.treeRoot = &treeRoot; @@ -120,7 +120,7 @@ class GrammarTester(grammar, string startSymbol) } } -private struct Differencer(T,P) +@safe private struct Differencer(T,P) { size_t level = 0; size_t differences = 0; @@ -161,7 +161,7 @@ private struct Differencer(T,P) return diffText.data; } - private void diffNode( const(T*) node, const(P*) pattern ) + private void diffNode( const(T*) node, const(P*) pattern ) @trusted { assert(pattern); switch ( pattern.name ) @@ -221,7 +221,7 @@ private struct Differencer(T,P) } } - private void traverseUnexpected( const(T*) node ) + private void traverseUnexpected( const(T*) node ) @trusted { assert(node); lineDiff(node, null); @@ -231,7 +231,7 @@ private struct Differencer(T,P) level--; } - private void diffBranch( const(T*) node, const(P*) pattern, bool[] visited, ref size_t cursor ) + private void diffBranch( const(T*) node, const(P*) pattern, bool[] visited, ref size_t cursor ) @trusted { assert(pattern); switch ( pattern.name ) @@ -386,7 +386,7 @@ private struct Differencer(T,P) } } -unittest +@safe unittest { string normalizeStr(string str) { @@ -575,7 +575,7 @@ TesterGrammar.Root = Root assert(tester.errorText.length > 0); } -unittest +@safe unittest { mixin(grammar(` Arithmetic: @@ -628,5 +628,3 @@ unittest /+ For reference: +/ - - diff --git a/pegged/tester/testerparser.d b/pegged/tester/testerparser.d index b91745d5..700fa905 100644 --- a/pegged/tester/testerparser.d +++ b/pegged/tester/testerparser.d @@ -24,7 +24,7 @@ UnorderedBranch < Spacing <: (blank / Comment)* -Comment <- +Comment <- / '//' (!eol .)* (eol) / '/*' (!'*/' .)* '*/' / NestedComment @@ -39,8 +39,14 @@ NestedCommentEnd <- '+/' module pegged.tester.testerparser; public import pegged.peg; -struct GenericTesterGrammar(TParseTree) +private import pegged.parsetree; +@safe struct GenericTesterGrammar(ParseTree) { + alias PEG=ParseTree; + mixin DefaultPatters!ParseTree; + //alias PEG=PeggedT!ParseTree; +// mixin DefaultParsePatterns!PEG; + struct TesterGrammar { enum name = "TesterGrammar"; @@ -62,135 +68,135 @@ struct GenericTesterGrammar(TParseTree) return false; } } - mixin decimateTree; - static TParseTree Root(TParseTree p) + mixin decimateTree!ParseTree; + static ParseTree Root(ParseTree p) { - return pegged.peg.named!(pegged.peg.and!(pegged.peg.wrapAround!(Spacing, Node, Spacing), pegged.peg.wrapAround!(Spacing, eoi, Spacing)), "TesterGrammar.Root")(p); + return PEG.named!(PEG.and!(PEG.wrapAround!(Spacing, Node, Spacing), PEG.wrapAround!(Spacing, PEG.eoi, Spacing)), "TesterGrammar.Root")(p); } - static TParseTree Root(string s) + static ParseTree Root(string s) { - return pegged.peg.named!(pegged.peg.and!(pegged.peg.wrapAround!(Spacing, Node, Spacing), pegged.peg.wrapAround!(Spacing, eoi, Spacing)), "TesterGrammar.Root")(TParseTree("", false,[], s)); + return PEG.named!(PEG.and!(PEG.wrapAround!(Spacing, Node, Spacing), PEG.wrapAround!(Spacing, PEG.eoi, Spacing)), "TesterGrammar.Root")(ParseTree("", false,[], s)); } static string Root(GetName g) { return "TesterGrammar.Root"; } - static TParseTree Node(TParseTree p) + static ParseTree Node(ParseTree p) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("^"), Spacing)), pegged.peg.wrapAround!(Spacing, identifier, Spacing)), pegged.peg.and!(pegged.peg.wrapAround!(Spacing, identifier, Spacing), pegged.peg.zeroOrMore!(pegged.peg.wrapAround!(Spacing, pegged.peg.propagate!(pegged.peg.wrapAround!(Spacing, Branch, Spacing)), Spacing)))), "TesterGrammar.Node")(p); + return PEG.named!(PEG.or!(PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("^"), Spacing)), PEG.wrapAround!(Spacing, identifier, Spacing)), PEG.and!(PEG.wrapAround!(Spacing, identifier, Spacing), PEG.zeroOrMore!(PEG.wrapAround!(Spacing, PEG.propagate!(PEG.wrapAround!(Spacing, Branch, Spacing)), Spacing)))), "TesterGrammar.Node")(p); } - static TParseTree Node(string s) + static ParseTree Node(string s) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("^"), Spacing)), pegged.peg.wrapAround!(Spacing, identifier, Spacing)), pegged.peg.and!(pegged.peg.wrapAround!(Spacing, identifier, Spacing), pegged.peg.zeroOrMore!(pegged.peg.wrapAround!(Spacing, pegged.peg.propagate!(pegged.peg.wrapAround!(Spacing, Branch, Spacing)), Spacing)))), "TesterGrammar.Node")(TParseTree("", false,[], s)); + return PEG.named!(PEG.or!(PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("^"), Spacing)), PEG.wrapAround!(Spacing, identifier, Spacing)), PEG.and!(PEG.wrapAround!(Spacing, identifier, Spacing), PEG.zeroOrMore!(PEG.wrapAround!(Spacing, PEG.propagate!(PEG.wrapAround!(Spacing, Branch, Spacing)), Spacing)))), "TesterGrammar.Node")(ParseTree("", false,[], s)); } static string Node(GetName g) { return "TesterGrammar.Node"; } - static TParseTree Branch(TParseTree p) + static ParseTree Branch(ParseTree p) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.wrapAround!(Spacing, OrderedBranch, Spacing), pegged.peg.wrapAround!(Spacing, UnorderedBranch, Spacing)), "TesterGrammar.Branch")(p); + return PEG.named!(PEG.or!(PEG.wrapAround!(Spacing, OrderedBranch, Spacing), PEG.wrapAround!(Spacing, UnorderedBranch, Spacing)), "TesterGrammar.Branch")(p); } - static TParseTree Branch(string s) + static ParseTree Branch(string s) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.wrapAround!(Spacing, OrderedBranch, Spacing), pegged.peg.wrapAround!(Spacing, UnorderedBranch, Spacing)), "TesterGrammar.Branch")(TParseTree("", false,[], s)); + return PEG.named!(PEG.or!(PEG.wrapAround!(Spacing, OrderedBranch, Spacing), PEG.wrapAround!(Spacing, UnorderedBranch, Spacing)), "TesterGrammar.Branch")(ParseTree("", false,[], s)); } static string Branch(GetName g) { return "TesterGrammar.Branch"; } - static TParseTree OrderedBranch(TParseTree p) + static ParseTree OrderedBranch(ParseTree p) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("->"), Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("{"), Spacing)), pegged.peg.oneOrMore!(pegged.peg.wrapAround!(Spacing, Node, Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("}"), Spacing))), pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("->"), Spacing)), pegged.peg.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.OrderedBranch")(p); + return PEG.named!(PEG.or!(PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("->"), Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("{"), Spacing)), PEG.oneOrMore!(PEG.wrapAround!(Spacing, Node, Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("}"), Spacing))), PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("->"), Spacing)), PEG.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.OrderedBranch")(p); } - static TParseTree OrderedBranch(string s) + static ParseTree OrderedBranch(string s) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("->"), Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("{"), Spacing)), pegged.peg.oneOrMore!(pegged.peg.wrapAround!(Spacing, Node, Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("}"), Spacing))), pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("->"), Spacing)), pegged.peg.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.OrderedBranch")(TParseTree("", false,[], s)); + return PEG.named!(PEG.or!(PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("->"), Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("{"), Spacing)), PEG.oneOrMore!(PEG.wrapAround!(Spacing, Node, Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("}"), Spacing))), PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("->"), Spacing)), PEG.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.OrderedBranch")(ParseTree("", false,[], s)); } static string OrderedBranch(GetName g) { return "TesterGrammar.OrderedBranch"; } - static TParseTree UnorderedBranch(TParseTree p) + static ParseTree UnorderedBranch(ParseTree p) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("~>"), Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("{"), Spacing)), pegged.peg.oneOrMore!(pegged.peg.wrapAround!(Spacing, Node, Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("}"), Spacing))), pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("~>"), Spacing)), pegged.peg.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.UnorderedBranch")(p); + return PEG.named!(PEG.or!(PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("~>"), Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("{"), Spacing)), PEG.oneOrMore!(PEG.wrapAround!(Spacing, Node, Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("}"), Spacing))), PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("~>"), Spacing)), PEG.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.UnorderedBranch")(p); } - static TParseTree UnorderedBranch(string s) + static ParseTree UnorderedBranch(string s) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("~>"), Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("{"), Spacing)), pegged.peg.oneOrMore!(pegged.peg.wrapAround!(Spacing, Node, Spacing)), pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("}"), Spacing))), pegged.peg.and!(pegged.peg.discard!(pegged.peg.wrapAround!(Spacing, pegged.peg.literal!("~>"), Spacing)), pegged.peg.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.UnorderedBranch")(TParseTree("", false,[], s)); + return PEG.named!(PEG.or!(PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("~>"), Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("{"), Spacing)), PEG.oneOrMore!(PEG.wrapAround!(Spacing, Node, Spacing)), PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("}"), Spacing))), PEG.and!(PEG.discard!(PEG.wrapAround!(Spacing, PEG.literal!("~>"), Spacing)), PEG.wrapAround!(Spacing, Node, Spacing))), "TesterGrammar.UnorderedBranch")(ParseTree("", false,[], s)); } static string UnorderedBranch(GetName g) { return "TesterGrammar.UnorderedBranch"; } - static TParseTree Spacing(TParseTree p) + static ParseTree Spacing(ParseTree p) { - return pegged.peg.named!(pegged.peg.discard!(pegged.peg.zeroOrMore!(pegged.peg.or!(blank, Comment))), "TesterGrammar.Spacing")(p); + return PEG.named!(PEG.discard!(PEG.zeroOrMore!(PEG.or!(blank, Comment))), "TesterGrammar.Spacing")(p); } - static TParseTree Spacing(string s) + static ParseTree Spacing(string s) { - return pegged.peg.named!(pegged.peg.discard!(pegged.peg.zeroOrMore!(pegged.peg.or!(blank, Comment))), "TesterGrammar.Spacing")(TParseTree("", false,[], s)); + return PEG.named!(PEG.discard!(PEG.zeroOrMore!(PEG.or!(blank, Comment))), "TesterGrammar.Spacing")(ParseTree("", false,[], s)); } static string Spacing(GetName g) { return "TesterGrammar.Spacing"; } - static TParseTree Comment(TParseTree p) + static ParseTree Comment(ParseTree p) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.literal!("//"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(eol), pegged.peg.any)), eol), pegged.peg.and!(pegged.peg.literal!("/*"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("*/")), pegged.peg.any)), pegged.peg.literal!("*/")), NestedComment), "TesterGrammar.Comment")(p); + return PEG.named!(PEG.or!(PEG.and!(PEG.literal!("//"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(eol), PEG.any)), eol), PEG.and!(PEG.literal!("/*"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("*/")), PEG.any)), PEG.literal!("*/")), NestedComment), "TesterGrammar.Comment")(p); } - static TParseTree Comment(string s) + static ParseTree Comment(string s) { - return pegged.peg.named!(pegged.peg.or!(pegged.peg.and!(pegged.peg.literal!("//"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(eol), pegged.peg.any)), eol), pegged.peg.and!(pegged.peg.literal!("/*"), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.negLookahead!(pegged.peg.literal!("*/")), pegged.peg.any)), pegged.peg.literal!("*/")), NestedComment), "TesterGrammar.Comment")(TParseTree("", false,[], s)); + return PEG.named!(PEG.or!(PEG.and!(PEG.literal!("//"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(eol), PEG.any)), eol), PEG.and!(PEG.literal!("/*"), PEG.zeroOrMore!(PEG.and!(PEG.negLookahead!(PEG.literal!("*/")), PEG.any)), PEG.literal!("*/")), NestedComment), "TesterGrammar.Comment")(ParseTree("", false,[], s)); } static string Comment(GetName g) { return "TesterGrammar.Comment"; } - static TParseTree NestedComment(TParseTree p) + static ParseTree NestedComment(ParseTree p) { - return pegged.peg.named!(pegged.peg.and!(pegged.peg.literal!("/+"), pegged.peg.or!(pegged.peg.and!(pegged.peg.negLookahead!(NestedCommentEnd), pegged.peg.any), NestedComment), NestedCommentEnd), "TesterGrammar.NestedComment")(p); + return PEG.named!(PEG.and!(PEG.literal!("/+"), PEG.or!(PEG.and!(PEG.negLookahead!(NestedCommentEnd), PEG.any), NestedComment), NestedCommentEnd), "TesterGrammar.NestedComment")(p); } - static TParseTree NestedComment(string s) + static ParseTree NestedComment(string s) { - return pegged.peg.named!(pegged.peg.and!(pegged.peg.literal!("/+"), pegged.peg.or!(pegged.peg.and!(pegged.peg.negLookahead!(NestedCommentEnd), pegged.peg.any), NestedComment), NestedCommentEnd), "TesterGrammar.NestedComment")(TParseTree("", false,[], s)); + return PEG.named!(PEG.and!(PEG.literal!("/+"), PEG.or!(PEG.and!(PEG.negLookahead!(NestedCommentEnd), PEG.any), NestedComment), NestedCommentEnd), "TesterGrammar.NestedComment")(ParseTree("", false,[], s)); } static string NestedComment(GetName g) { return "TesterGrammar.NestedComment"; } - static TParseTree NestedCommentEnd(TParseTree p) + static ParseTree NestedCommentEnd(ParseTree p) { - return pegged.peg.named!(pegged.peg.literal!("+/"), "TesterGrammar.NestedCommentEnd")(p); + return PEG.named!(PEG.literal!("+/"), "TesterGrammar.NestedCommentEnd")(p); } - static TParseTree NestedCommentEnd(string s) + static ParseTree NestedCommentEnd(string s) { - return pegged.peg.named!(pegged.peg.literal!("+/"), "TesterGrammar.NestedCommentEnd")(TParseTree("", false,[], s)); + return PEG.named!(PEG.literal!("+/"), "TesterGrammar.NestedCommentEnd")(ParseTree("", false,[], s)); } static string NestedCommentEnd(GetName g) { return "TesterGrammar.NestedCommentEnd"; } - static TParseTree opCall(TParseTree p) + static ParseTree opCall(ParseTree p) { - TParseTree result = decimateTree(Root(p)); + ParseTree result = decimateTree(Root(p)); result.children = [result]; result.name = "TesterGrammar"; return result; } - static TParseTree opCall(string input) + static ParseTree opCall(string input) { - return TesterGrammar(TParseTree(``, false, [], input, 0, 0)); + return TesterGrammar(ParseTree(``, false, [], input, 0, 0)); } static string opCall(GetName g) { @@ -200,5 +206,5 @@ struct GenericTesterGrammar(TParseTree) } } -alias GenericTesterGrammar!(ParseTree).TesterGrammar TesterGrammar; - +import pegged.defaultparsetree : DefaultParseTree; +alias GenericTesterGrammar!(DefaultParseTree).TesterGrammar TesterGrammar; diff --git a/pegged/tohtml.d b/pegged/tohtml.d index 2a51c916..fa2f4a18 100644 --- a/pegged/tohtml.d +++ b/pegged/tohtml.d @@ -4,6 +4,7 @@ import std.stdio; import std.conv, std.string; import std.algorithm.searching; import pegged.peg; +import pegged.parsetree : isParseTree; enum Expand { @@ -21,8 +22,8 @@ enum Expand * p = The ParseTree to represent. * file = The file where to write the tree. */ -void toHTML(Expand e = Expand.no, Details...)(const ref ParseTree p, - File file) +void toHTML(ParseTree, Expand e = Expand.no, Details...)(const ref ParseTree p, + File file) if (isParseTree!ParseTree) { file.write(` @@ -163,10 +164,10 @@ details.leaf summary::-webkit-details-marker { * p = The ParseTree to represent. * filename = The name of file where tree is written. */ -void toHTML(Expand e = Expand.no, Details...)(const ref ParseTree p, - string filename) +void toHTML(ParseTree, Expand e = Expand.no, Details...)(const ref ParseTree p, + string filename) if(isParseTree!ParseTree) { if (filename.endsWith(".html", ".htm") == 0) filename ~= ".html"; - toHTML!(e, Details)(p, File(filename, "w")); + toHTML!(ParseTree, e, Details)(p, File(filename, "w")); } diff --git a/setup.mk b/setup.mk new file mode 100644 index 00000000..cfe4c947 --- /dev/null +++ b/setup.mk @@ -0,0 +1 @@ +DFILES := ${shell find pegged -name "*.d" -not \( -path "*dev*" -o -path "*tester*" -o -path "*performancetest*" -o -path "*tohtml.d" \) }