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 		node.children[0].accept(this);
58 		app.put("?");
59 		node.children[1].accept(this);
60 		app.put(":");
61 		node.children[2].accept(this);
62 	}
63 
64 	override void visit(IndexOp node) {
65 		node.children[0].accept(this);
66 		app.put("[");
67 		node.children[1].accept(this);
68 		app.put("]");
69 	}
70 
71 	override void visit(SliceOp node) {
72 		node.children[0].accept(this);
73 		app.put("[");
74 		node.children[1].accept(this);
75 		app.put("..");
76 		node.children[2].accept(this);
77 		app.put("]");
78 	}
79 
80 	override void visit(DispatchOp node) {
81 		node.children[0].accept(this);
82 		app.put(".");
83 		app.put(node.target.value);
84 	}
85 
86 	override void visit(FunctionCall node) {
87 		node.children[0].accept(this);
88 		app.put("(");
89 		foreach (i, child; node.children[1..$]) {
90 			child.accept(this);
91 			if ((i + 2) != node.children.length)
92 				app.put(",");
93 		}
94 		app.put(")");
95 	}
96 
97 	override void visit(WithExpression node) {
98 		node.children[0].accept(this);
99 		if (!node.name.empty) {
100 			app.put(" as ");
101 			app.put(node.name.value);
102 		}
103 	}
104 
105 	override void visit(WithStatement node) {
106 		app.put("with(");
107 		foreach (i, child; node.children[0..$-1]) {
108 			child.accept(this);
109 			if ((i + 2) != node.children.length)
110 				app.put(",");
111 		}
112 		app.put(")");
113 		node.children[$-1].accept(this);
114 	}
115 
116 	override void visit(IfStatement node) {
117 		app.put("if(");
118 		node.children[0].accept(this);
119 		app.put(")");
120 		node.children[1].accept(this);
121 
122 		if (node.children[2] !is null) {
123 			app.put("else");
124 			node.children[2].accept(this);
125 		}
126 	}
127 
128 	override void visit(Output node) {
129 		app.put("out(");
130 		node.children[0].accept(this);
131 		app.put(")");
132 	}
133 
134 	override void visit(LoopStatement node) {
135 		app.put("foreach(");
136 		if (!node.key.empty) {
137 			app.put(node.key.value);
138 			app.put(',');
139 		}
140 		app.put(node.value.value);
141 		app.put(';');
142 
143 		node.children[0].accept(this);
144 		if (node.children[1] !is null) {
145 			app.put("..");
146 			node.children[1].accept(this);
147 		}
148 		app.put(")");
149 
150 		node.children[2].accept(this);
151 	}
152 
153 	override void visit(StatementBlock node) {
154 		app.put("{");
155 		foreach (child; node.children) {
156 			child.accept(this);
157 			app.put(";");
158 		}
159 		app.put("}");
160 	}
161 
162 	override void visit(Module node) {
163 		foreach (child; node.children) {
164 			child.accept(this);
165 			app.put(";");
166 		}
167 	}
168 
169 	void print(ref Appender app, Node root) {
170 		this.app = &app;
171 
172 		root.accept(this);
173 	}
174 
175 	private Appender* app;
176 }
177 
178 
179 string print(Node root) {
180 	auto app = appender!string;
181 	auto printer = new Printer!(typeof(app));
182 	printer.print(app, root);
183 	return app.data;
184 }