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 }