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 }