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 }