1 module view.parser; 2 3 import std.stdio; 4 import std.conv; 5 import std.algorithm; 6 import std.variant; 7 import std.array; 8 import std.string; 9 import std.typetuple; 10 11 import view; 12 13 abstract class Expression 14 { 15 public string Evaluate(ViewContext ctx = null); 16 } 17 class Constant : Expression 18 { 19 public string value; 20 public this(string value) 21 { 22 this.value = value; 23 } 24 override public string Evaluate(ViewContext ctx = null ) 25 { 26 return " str ~= `" ~ value ~ "`;"; 27 } 28 } 29 30 class VariableReference : Expression 31 { 32 public string value; 33 public this(string value) 34 { 35 this.value = value; 36 } 37 override public string Evaluate(ViewContext ctx = null) 38 { 39 return " str ~= std.conv.to!string(" ~ value ~ ");"; 40 } 41 } 42 class ExecuteBlock : Expression 43 { 44 public string value; 45 public this(string value) 46 { 47 this.value = value; 48 } 49 override public string Evaluate(ViewContext ctx = null) 50 { 51 return value; 52 } 53 } 54 class Operation : Expression 55 { 56 public Expression left; 57 public Expression value; 58 public Expression right; 59 public this(Expression left,Expression value,Expression right) 60 { 61 this.left = left; 62 this.value = value; 63 this.right = right; 64 } 65 override public string Evaluate(ViewContext ctx = null) 66 { 67 auto x = left.Evaluate(ctx); 68 auto y = right.Evaluate(ctx); 69 return x ~ value.Evaluate(ctx) ~ y; 70 } 71 } 72 Expression strToTree(string str,int s,int t) 73 { 74 if(s >= t)return new Constant(null); 75 76 bool findVar = false; 77 bool findExe = false; 78 int ves,vet; 79 static import std.algorithm; 80 for(int i = s;i<t;i++) 81 { 82 if((i+2 <= t) && canFind(["{{","{%"],str[i..i+2])) 83 { 84 ves = i; 85 if(str[i+1] == '{') findVar = true; 86 else findExe = true; 87 for(int k = i;k<t;k++) 88 { 89 if(canFind(["}}","%}"],str[k..k+2])) 90 { 91 vet = k+2; 92 break; 93 } 94 } 95 break; 96 } 97 } 98 if(ves==0 && !findVar && !findExe)return new Constant(str[s..t]); 99 if(findVar && ves==s && vet==t)return new VariableReference(str[ves+2 .. vet-2]); 100 if(findExe && ves==s && vet==t)return new ExecuteBlock(str[ves+2 .. vet-2]); 101 if(str[ves .. ves+2] == "{%") 102 return new Operation(strToTree(str,s,ves),new ExecuteBlock(str[ves+2 .. vet-2]),strToTree(str,vet,t)); 103 else 104 return new Operation(strToTree(str,s,ves),new VariableReference(str[ves+2 .. vet-2]),strToTree(str,vet,t)); 105 } 106 107 class Parser 108 { 109 public string str; 110 public string FunHeader = ` 111 static string TempleFunc(ViewContext var,CompiledTemple* ct = null){ 112 static import std.conv; 113 string render(string _view_file)(){ 114 return render_with!_view_file(var); 115 } 116 string render_with(string _view_file)(ViewContext var = null){ 117 auto r = display!(_view_file)(); 118 return r.toString(var); 119 } 120 string yield(){ 121 return ct.toString(var); 122 } 123 string str; 124 with(var){ 125 `; 126 public string FunFooter = ` 127 } 128 return str; 129 }`; 130 public Expression stt = null; 131 public ViewContext ctx = null; 132 this(string str) 133 { 134 this.str = str; 135 this.stt = strToTree(str,0,str.length.to!int); 136 } 137 override string toString() 138 { 139 return FunHeader ~ stt.Evaluate(ctx) ~ FunFooter; 140 } 141 } 142 143 unittest 144 { 145 auto p = new Parser(```{% import std.stdio; %}<div>{{value["name"]}}```); 146 assert(p.stt.Evaluate() == " str ~= ``; import std.stdio; str ~= `<div>`; str ~= std.conv.to!string(value[\"name\"]); str ~= ``;"); 147 }