1 module vayne.ast.printer;
2 
3 
4 import std.array;
5 
6 import vayne.ast.node;
7 import vayne.ast.visitor;
8 
9 
10 class Printer(Appender) : Visitor {
11 	override void visit(Expression node) {
12 		if (node.parenthesis)
13 			app.put("(");
14 
15 		super.visit(node);
16 
17 		if (node.parenthesis)
18 			app.put(")");
19 	}
20 
21 	override void visit(Constant node) {
22 		app.put(node.tok.toString);
23 	}
24 
25 	override void visit(Identifier node) {
26 		app.put(node.tok.toString);
27 	}
28 
29 	override void visit(UnaryOp node) {
30 		app.put(node.tok.toString);
31 
32 		node.children[0].accept(this);
33 	}
34 
35 	override void visit(PrefixOp node) {
36 		app.put(node.tok.toString);
37 
38 		node.children[0].accept(this);
39 	}
40 
41 	override void visit(SuffixOp node) {
42 		node.children[0].accept(this);
43 		app.put(node.tok.toString);
44 	}
45 
46 	override void visit(BinaryOp node) {
47 		app.put("(");
48 		node.children[0].accept(this);
49 		app.put(" ");
50 		app.put(node.tok.toString);
51 		app.put(" ");
52 		node.children[1].accept(this);
53 		app.put(")");
54 	}
55 
56 	override void visit(ConditionalExpression node) {
57 		app.put("(");
58 		node.children[0].accept(this);
59 		app.put(" ? ");
60 		node.children[1].accept(this);
61 		app.put(" : ");
62 		node.children[2].accept(this);
63 		app.put(")");
64 	}
65 
66 	override void visit(IndexOp node) {
67 		node.children[0].accept(this);
68 		app.put("[");
69 		node.children[1].accept(this);
70 		app.put("]");
71 	}
72 
73 	override void visit(SliceOp node) {
74 		node.children[0].accept(this);
75 		app.put("[");
76 		node.children[1].accept(this);
77 		app.put("..");
78 		node.children[2].accept(this);
79 		app.put("]");
80 	}
81 
82 	override void visit(DispatchOp node) {
83 		node.children[0].accept(this);
84 		app.put(".");
85 		app.put(node.target.value);
86 	}
87 
88 	override void visit(FunctionCall node) {
89 		node.children[0].accept(this);
90 		app.put("(");
91 		foreach (i, child; node.children[1..$]) {
92 			child.accept(this);
93 			if ((i + 2) != node.children.length)
94 				app.put(",");
95 		}
96 		app.put(")");
97 	}
98 
99 	override void visit(WithExpression node) {
100 		node.children[0].accept(this);
101 		if (!node.name.empty) {
102 			app.put(" as ");
103 			app.put(node.name.value);
104 		}
105 	}
106 
107 	override void visit(WithStatement node) {
108 		app.put("with(");
109 		foreach (i, child; node.children[0..$-1]) {
110 			child.accept(this);
111 			if ((i + 2) != node.children.length)
112 				app.put(",");
113 		}
114 		app.put(")");
115 		node.children[$-1].accept(this);
116 	}
117 
118 	override void visit(IfStatement node) {
119 		app.put("if(");
120 		node.children[0].accept(this);
121 		app.put(")");
122 		node.children[1].accept(this);
123 
124 		if (node.children[2] !is null) {
125 			app.put("else");
126 			node.children[2].accept(this);
127 		}
128 	}
129 
130 	override void visit(Output node) {
131 		app.put("out(");
132 		node.children[0].accept(this);
133 		app.put(")");
134 	}
135 
136 	override void visit(LoopStatement node) {
137 		app.put("foreach(");
138 		if (!node.key.empty) {
139 			app.put(node.key.value);
140 			app.put(',');
141 		}
142 		app.put(node.value.value);
143 		app.put(';');
144 
145 		node.children[0].accept(this);
146 		if (node.children[1] !is null) {
147 			app.put("..");
148 			node.children[1].accept(this);
149 		}
150 		app.put(")");
151 
152 		node.children[2].accept(this);
153 	}
154 
155 	override void visit(StatementBlock node) {
156 		app.put("{");
157 		foreach (child; node.children) {
158 			child.accept(this);
159 			app.put(";");
160 		}
161 		app.put("}");
162 	}
163 
164 	override void visit(Module node) {
165 		foreach (child; node.children) {
166 			child.accept(this);
167 			app.put(";");
168 		}
169 	}
170 
171 	void print(ref Appender app, Node root) {
172 		this.app = &app;
173 
174 		root.accept(this);
175 	}
176 
177 	private Appender* app;
178 }
179 
180 
181 string print(Node root) {
182 	auto app = appender!string;
183 	auto printer = new Printer!(typeof(app));
184 	printer.print(app, root);
185 	return app.data;
186 }