1 /* 2 * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design. 3 * 4 * Copyright (C) 2015-2019, HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.framework.view.ast.Printer; 13 14 private 15 { 16 import hunt.framework.view.ast.Node; 17 import hunt.framework.view.ast.Visitor; 18 } 19 20 21 class NullVisitor : VisitorInterface 22 { 23 static foreach(NT; NodeTypes) 24 { 25 void visit(NT node) 26 { 27 import std.stdio: wl = writeln; 28 wl("# ", NT.stringof, " #"); 29 } 30 } 31 } 32 33 34 class Printer : NullVisitor 35 { 36 import std.stdio: wl = writeln, w = write; 37 import std.format: fmt = format; 38 39 uint _tab = 0; 40 41 override void visit(StmtBlockNode node) 42 { 43 print("Statement Block:"); 44 _tab++; 45 foreach(ch; node.children) 46 { 47 ch.accept(this); 48 } 49 _tab--; 50 } 51 52 53 override void visit(TemplateNode node) 54 { 55 print("Template:"); 56 57 _tab++; 58 59 if (!node.blocks.length) 60 print("Blocks: NONE"); 61 else 62 { 63 print("Blocks:"); 64 _tab++; 65 foreach (key, block; node.blocks) 66 print(key); 67 _tab--; 68 } 69 70 print("Statements:"); 71 _tab++; 72 if (!node.stmt.isNull) 73 node.stmt.get.accept(this); 74 _tab--; 75 76 _tab--; 77 } 78 79 80 override void visit(BlockNode node) 81 { 82 print("Block: %s".fmt(node.name)); 83 _tab++; 84 if (!node.stmt.isNull) 85 node.stmt.get.accept(this); 86 _tab--; 87 } 88 89 90 override void visit(RawNode node) 91 { 92 import std.array : replace; 93 print("Raw block: \"%s\"".fmt(node.raw.replace("\n", "\\n").replace(" ", "."))); 94 } 95 96 97 override void visit(ExprNode node) 98 { 99 print("Expression block:"); 100 _tab++; 101 node.expr.get.accept(this); 102 _tab--; 103 } 104 105 106 override void visit(InlineIfNode node) 107 { 108 print("Inline If:"); 109 110 _tab++; 111 112 if (node.cond.isNull) 113 print("If: NONE"); 114 else 115 { 116 print("If:"); 117 _tab++; 118 node.cond.get.accept(this); 119 _tab--; 120 } 121 122 print("Expression:"); 123 _tab++; 124 node.expr.get.accept(this); 125 _tab--; 126 127 if (node.other.isNull) 128 print("Else: nil"); 129 else 130 { 131 print("Else:"); 132 _tab++; 133 node.other.get.accept(this); 134 _tab--; 135 } 136 137 _tab--; 138 } 139 140 141 override void visit(BinOpNode node) 142 { 143 print("BinaryOp: %s".fmt(node.op)); 144 _tab++; 145 node.lhs.accept(this); 146 node.rhs.accept(this); 147 _tab--; 148 } 149 150 151 override void visit(UnaryOpNode node) 152 { 153 print("UnaryOp: %s".fmt(node.op)); 154 _tab++; 155 node.expr.accept(this); 156 _tab--; 157 } 158 159 160 override void visit(NumNode node) 161 { 162 if (node.type == NumNode.Type.Integer) 163 print("Integer: %d".fmt(node.data._integer)); 164 else 165 print("Float: %f".fmt(node.data._float)); 166 } 167 168 169 override void visit(BooleanNode node) 170 { 171 print("Bool: %s".fmt(node.boolean)); 172 } 173 174 175 override void visit(NilNode node) 176 { 177 print("Nil"); 178 } 179 180 181 override void visit(IdentNode node) 182 { 183 print("Ident: '%s'".fmt(node.name)); 184 if (node.subIdents.length) 185 { 186 print("Sub idents:"); 187 _tab++; 188 foreach (id; node.subIdents) 189 id.accept(this); 190 _tab--; 191 } 192 } 193 194 195 override void visit(AssignableNode node) 196 { 197 print("Assignable: %s".fmt(node.name)); 198 if (node.subIdents.length) 199 { 200 _tab++; 201 print("Sub idents:"); 202 _tab++; 203 foreach (id; node.subIdents) 204 id.accept(this); 205 _tab--; 206 _tab--; 207 } 208 } 209 210 211 override void visit(StringNode node) 212 { 213 print("String: %s".fmt(node.str)); 214 } 215 216 217 override void visit(ListNode node) 218 { 219 print("List:"); 220 _tab++; 221 foreach (l; node.list) 222 l.accept(this); 223 _tab--; 224 } 225 226 227 override void visit(DictNode node) 228 { 229 print("Dict:"); 230 _tab++; 231 foreach (key, value; node.dict) 232 { 233 print("Key: %s".fmt(key)); 234 print("Value:"); 235 _tab++; 236 value.accept(this); 237 _tab--; 238 } 239 _tab--; 240 } 241 242 243 override void visit(IfNode node) 244 { 245 print("If:"); 246 _tab++; 247 248 print("Condition:"); 249 _tab++; 250 node.cond.accept(this); 251 _tab--; 252 253 print("Then:"); 254 _tab++; 255 node.then.accept(this); 256 _tab--; 257 258 if (node.other) 259 { 260 print("Else:"); 261 _tab++; 262 node.other.accept(this); 263 _tab--; 264 } 265 else 266 print("Else: NONE"); 267 _tab--; 268 } 269 270 271 override void visit(ForNode node) 272 { 273 print("For:"); 274 _tab++; 275 276 print("Keys:"); 277 _tab++; 278 foreach (key; node.keys) 279 print(key); 280 _tab--; 281 282 print("Iterable:"); 283 _tab++; 284 node.iterable.get.accept(this); 285 _tab--; 286 287 print("Block:"); 288 _tab++; 289 node.block.get.accept(this); 290 _tab--; 291 292 if (!node.cond.isNull) 293 { 294 print("Condition:"); 295 _tab++; 296 node.cond.get.accept(this); 297 _tab--; 298 } 299 else 300 print("Condition: NONE"); 301 302 303 if (!node.other.isNull) 304 { 305 print("Else:"); 306 _tab++; 307 node.other.get.accept(this); 308 _tab--; 309 } 310 else 311 print("Else: NONE"); 312 313 print("Recursive: %s".fmt(node.isRecursive)); 314 315 _tab--; 316 } 317 318 319 override void visit(SetNode node) 320 { 321 print("Set:"); 322 _tab++; 323 324 print("Assigns:"); 325 _tab++; 326 foreach (assign; node.assigns) 327 assign.accept(this); 328 _tab--; 329 330 print("Expression:"); 331 _tab++; 332 node.expr.accept(this); 333 _tab--; 334 335 _tab--; 336 } 337 338 339 override void visit(MacroNode node) 340 { 341 print("Macro: '%s'".fmt(node.name)); 342 343 _tab++; 344 if (!node.args.length) 345 print("Args: NONE"); 346 else 347 { 348 print("Args:"); 349 _tab++; 350 foreach(arg; node.args) 351 { 352 print("Name: %s".fmt(arg.name)); 353 if (!arg.defaultExpr.isNull) 354 { 355 _tab++; 356 print("Default:"); 357 _tab++; 358 arg.defaultExpr.get.accept(this); 359 _tab--; 360 _tab--; 361 } 362 } 363 _tab--; 364 } 365 366 print("Body:"); 367 _tab++; 368 node.block.get.accept(this); 369 _tab--; 370 371 _tab--; 372 373 print("Return: %s".fmt(node.isReturn)); 374 } 375 376 377 override void visit(CallNode node) 378 { 379 print("Call: '%s'".fmt(node.macroName)); 380 381 _tab++; 382 383 if (!node.formArgs.length) 384 print("Formal args: NONE"); 385 else 386 { 387 print("Formal args:"); 388 _tab++; 389 foreach(arg; node.formArgs) 390 { 391 print("Name: %s".fmt(arg.name)); 392 if (!arg.defaultExpr.isNull) 393 { 394 _tab++; 395 print("Default:"); 396 _tab++; 397 arg.defaultExpr.get.accept(this); 398 _tab--; 399 _tab--; 400 } 401 } 402 _tab--; 403 } 404 405 if (node.factArgs.isNull) 406 print("Fact args: NONE"); 407 else 408 { 409 print("Fact args:"); 410 _tab++; 411 node.factArgs.get.accept(this); 412 _tab--; 413 } 414 415 print("Body:"); 416 _tab++; 417 node.block.get.accept(this); 418 _tab--; 419 420 _tab--; 421 } 422 423 424 override void visit(FilterBlockNode node) 425 { 426 print("Filter: '%s'".fmt(node.filterName)); 427 428 _tab++; 429 430 if (node.args.isNull) 431 print("Args: NONE"); 432 else 433 { 434 print("Args:"); 435 _tab++; 436 node.args.get.accept(this); 437 _tab--; 438 } 439 440 print("Body:"); 441 _tab++; 442 node.block.get.accept(this); 443 _tab--; 444 445 _tab--; 446 } 447 448 449 override void visit(ImportNode node) 450 { 451 print("Import: '%s'".fmt(node.fileName)); 452 453 _tab++; 454 455 if (!node.macrosNames.length) 456 print("Macros: all"); 457 else 458 { 459 print("Macros:"); 460 _tab++; 461 foreach(name; node.macrosNames) 462 print("%s -> %s".fmt(name.was, name.become)); 463 _tab--; 464 } 465 466 if (node.tmplBlock.isNull) 467 print("Block: Missing"); 468 else 469 print("Block: %s children".fmt(node.tmplBlock.get.stmt.get.children.length)); 470 471 if (node.withContext) 472 print("Context: with"); 473 else 474 print("Context: without"); 475 476 _tab--; 477 } 478 479 480 override void visit(IncludeNode node) 481 { 482 print("Include: '%s'".fmt(node.fileName)); 483 484 _tab++; 485 486 if (node.tmplBlock.isNull) 487 print("Block: Missing"); 488 else 489 print("Block: %s children".fmt(node.tmplBlock.get.stmt.get.children.length)); 490 491 if (node.withContext) 492 print("Context: with"); 493 else 494 print("Context: without"); 495 496 _tab--; 497 } 498 499 500 override void visit(ExtendsNode node) 501 { 502 print("Extends: '%s'".fmt(node.fileName)); 503 504 _tab++; 505 506 if (node.tmplBlock.isNull) 507 print("Block: Missing"); 508 else 509 print("Block: %s children".fmt(node.tmplBlock.get.stmt.get.children.length)); 510 511 _tab--; 512 } 513 514 515 protected: 516 517 518 void print(string str) 519 { 520 foreach(i; 0 .. _tab) 521 w("- "); 522 wl(str); 523 } 524 }