1 /** 2 Copyright: 2018 Mark Fisher 3 4 License: 5 Permission is hereby granted, free of charge, to any person obtaining a copy of 6 this software and associated documentation files (the "Software"), to deal in 7 the Software without restriction, including without limitation the rights to 8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 of the Software, and to permit persons to whom the Software is furnished to do 10 so, subject to the following conditions: 11 12 The above copyright notice and this permission notice shall be included in all 13 copies or substantial portions of the Software. 14 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 SOFTWARE. 22 **/ 23 module dxx.util.minitemplt; 24 25 private import pegged.grammar; 26 27 private import std.array; 28 private import std.typecons; 29 private import std..string; 30 31 private import metad.compiler; 32 private import metad.interp; 33 34 enum _GRAMMAR = q{ 35 MiniTemplateGrammar: 36 Doc <- Line+ :endOfInput 37 Line <- (Var / Text) 38 Var <- LDelim ^Inner RDelim 39 LDelim < "{{" 40 RDelim < "}}" 41 Text <- ~((!LDelim) Char )* 42 Char <- . 43 Inner <- ~((!RDelim) Char )* 44 }; 45 mixin(grammar(_GRAMMAR)); 46 47 template MiniTemplate(alias idParser) { 48 struct MiniTemplateCompiler(ParseTree T,alias Parser=MiniTemplateCompiler) { 49 mixin Compiler!(T,Parser); 50 mixin (compilerOverride!("MiniTemplateGrammar.Text","T.matches.join(\"\")")); 51 mixin (compilerOverride!("MiniTemplateGrammar.Inner","idParser!T()")); 52 } 53 } 54 55 unittest { 56 static string v(ParseTree T)() { 57 //pragma(msg,"** Value:"~ T.name); 58 //pragma(msg,"** = "~ T.matches.join); 59 return "<" ~ T.matches.join ~ ">"; 60 } 61 enum inputText = q{ 62 {{MyValue}}.{{MyVal2}} 63 }; 64 enum c= MiniTemplate!(v).MiniTemplateCompiler!(MiniTemplateGrammar(inputText)).compileNode.strip; 65 static assert(c == "<MyValue>.<MyVal2>",c); 66 } 67 68 template miniTemplateParser(alias idParser,string txt) { 69 enum miniTemplateParser = MiniTemplate!(idParser).MiniTemplateCompiler!(MiniTemplateGrammar(txt)).compileNode(); 70 } 71 72 template miniTemplate(alias idParser,alias txt) { 73 static string __id(ParseTree T)() { 74 return idParser!(T.matches.join)(); 75 } 76 auto miniTemplate() { 77 enum data = MiniTemplateGrammar(txt); 78 return MiniTemplate!(__id).MiniTemplateCompiler!(data).compileNode(); 79 } 80 } 81 82 unittest { 83 static string v(ParseTree T)() { 84 //pragma(msg,"++ Value:"~ T.name); 85 //pragma(msg,"++ = "~ T.matches.join); 86 return "[" ~ T.matches.join ~ "]"; 87 } 88 enum inputText = q{ 89 {{MyValue.a.b.c}}.{{MyVal2.d.e.f}} 90 }; 91 enum c = miniTemplateParser!(v,inputText).strip; 92 static assert(c == "[MyValue.a.b.c].[MyVal2.d.e.f]"); 93 } 94 95 unittest { 96 static string v(string k)() { 97 // pragma(msg,"v = "~ k); 98 return "[" ~ k ~ "]"; 99 } 100 enum inputText = q{ 101 123{{MyValue.a.b.c}}.{{MyVal2.d.e.f}}456 102 }; 103 enum c = miniTemplate!(v,inputText).strip; 104 static assert(c == "123[MyValue.a.b.c].[MyVal2.d.e.f]456"); 105 } 106 107 template MiniInterpreter(T) { 108 static auto MiniInterpreter(T idParser,ParseTree t) { 109 import std.variant; 110 import std.algorithm; 111 Variant delegate(ParseTree)[string] nodes; 112 nodes["MiniTemplateGrammar.LDelim"] = f=>Variant(""); 113 nodes["MiniTemplateGrammar.RDelim"] = f=>Variant(""); 114 nodes["MiniTemplateGrammar.Text"] = f=>Variant(f.matches.join); 115 //nodes["GRAMMAR.Inner"] = (f)=>idParser(f.matches.join("")); 116 nodes["MiniTemplateGrammar.Inner"] = (f)=>Variant(idParser(f.matches.join)); 117 //return Interpreter!(string,typeof(nodes))(nodes,t).join; 118 return Interpreter(nodes,t).map!(x=>x.get!string).join; 119 } 120 } 121 122 unittest { 123 static string v(string f) { 124 return "<" ~ f ~ ">"; 125 } 126 enum inputText = q{ 127 {{MyValue}}.{{MyVal2}} 128 }; 129 auto d = MiniTemplateGrammar(inputText); 130 string c = MiniInterpreter(&v,d).strip; 131 assert("<MyValue>.<MyVal2>" == c); 132 } 133 /*unittest { 134 static string v(string f) { 135 return "<" ~ f ~ ">"; 136 } 137 enum inputText = q{ 138 {MyValue}.{MyVal2} 139 }; 140 auto d = MiniTemplateGrammar(inputText); 141 string c = MiniInterpreter(&v,d).strip; 142 assert("<MyValue>.<MyVal2>" == c); 143 }*/ 144 145 template miniInterpreter(alias idParser) { 146 //static string __id(ParseTree t) { 147 // return idParser(t.matches.join("")); 148 //} 149 static string __id(string t) { 150 return idParser(t); 151 } 152 auto miniInterpreter(string txt) { 153 auto data = MiniTemplateGrammar(txt); 154 //auto compiler = MiniInterpreter!(__id).MiniTemplateInterpreter!(data).interp(); 155 //return MiniInterpreter!(typeof(&__id))(&__id,data); 156 return MiniInterpreter!(typeof(&__id))(&__id,data); 157 //return I.MiniTemplateInterperter!(data).interpNode(); 158 //return compiler(); 159 } 160 } 161 unittest { 162 /*static string v(ParseTree T) { 163 //pragma(msg,"++ Value:"~ T.name); 164 //pragma(msg,"++ = "~ T.matches.join("")); 165 return "[" ~ T.matches.join("") ~ "]"; 166 }*/ 167 static string v(string x) { 168 return "[" ~ x ~ "]"; 169 } 170 171 enum inputText = q{ 172 {{MyValue.a.b.c}}.{{MyVal2.d.e.f}} 173 }; 174 auto c = miniInterpreter!(v)(inputText).strip; 175 assert(c == "[MyValue.a.b.c].[MyVal2.d.e.f]"); 176 } 177 178 /*unittest { 179 180 static string v(string x) { 181 return "[" ~ x ~ "]"; 182 } 183 184 enum inputText = q{ 185 {MyValue.a.b.c}.{MyVal2.d.e.f} 186 }; 187 auto c = miniInterpreter!(v,"{","}")(inputText).strip; 188 assert(c == "[MyValue.a.b.c].[MyVal2.d.e.f]"); 189 }*/ 190 191 unittest { 192 static string v(string k) { 193 //pragma(msg,"v = "~ k); 194 return "[" ~ k ~ "]"; 195 } 196 enum inputText = q{ 197 123{{MyValue.a.b.c}}.{{MyVal2.d.e.f}}456 198 }; 199 auto c = miniInterpreter!(v)(inputText); 200 assert(c == "123[MyValue.a.b.c].[MyVal2.d.e.f]456"); 201 } 202 /* 203 unittest { 204 static string v(string k) { 205 pragma(msg,"v = "~ k); 206 return "[" ~ k ~ "]"; 207 } 208 enum inputText = q{ 209 123{MyValue.a.b.c}.{MyVal2.d.e.f}456 210 }; 211 auto c = miniInterpreter!(v,"{","}")(inputText); 212 assert(c == "123[MyValue.a.b.c].[MyVal2.d.e.f]456"); 213 } 214 */