1 /++ 2 Used for debugging compiler 3 Generates a HTML page that represents a readable representation of AST nodes 4 Only available in `qsCompiler` configuration (`dub -c=qsCompiler`) 5 +/ 6 module qscript.compiler.asthtml; 7 8 import qscript.compiler.ast; 9 10 import utils.misc; 11 import utils.lists; 12 13 import std.conv : to; 14 15 version (compiler){ 16 /// stores the style sheet for the page 17 private enum STYLESHEET = "<style>*{font-family:monospace;border:1px solid #cccccc;border-collapse:collapse;}</style>"; 18 /// some commonly used html codes 19 private enum HTML : string{ 20 TABLE_HEADING_START = "<table><tr><th>", 21 TABLE_HEADING_END = "</th></tr>", 22 TABLE_END = "</table>", 23 ROW_START = "<tr>", 24 ROW_END = "</tr>", 25 DATA_START = "<td>", 26 DATA_END = "</td>", 27 BOLD_START = "<b>", 28 BOLD_END = "</b>", 29 } 30 /// to generate an html page representing AST nodes 31 class ASTHtml{ 32 private: 33 /// stores the html page while it's being generated 34 List!string _html; 35 /// replaces non alpabet, non numeric chars with html codes 36 static string htmlEncode(string str){ 37 if (str.isAlphabet || str.isNum) 38 return str; 39 char[] r; 40 foreach (c; str){ 41 if ((cast(string)[c]).isAlphabet || (cast(string)[c]).isNum) 42 r ~= c; 43 else 44 r ~= "&#"~((cast(int)c).to!string)~';'; 45 } 46 return cast(string)r; 47 } 48 /// appends a new table with a heading 49 void tableNew(string heading, bool asRow = false){ 50 if (asRow) 51 _html.append(HTML.ROW_START); 52 _html.append(HTML.TABLE_HEADING_START~htmlEncode(heading)~HTML.TABLE_HEADING_END); 53 if (asRow) 54 _html.append(HTML.ROW_END); 55 } 56 /// appends a table end tag 57 void tableEnd(){ 58 _html.append(HTML.TABLE_END); 59 } 60 /// appends a row to table 61 void tableRow(string[] values, bool bold=false){ 62 _html.append(HTML.ROW_START); 63 if (bold) 64 _html.append(HTML.BOLD_START); 65 foreach (val; values) 66 _html.append(HTML.DATA_START~htmlEncode(val)~HTML.DATA_END); 67 if (bold) 68 _html.append(HTML.BOLD_END); 69 _html.append(HTML.ROW_END); 70 } 71 72 /// generate html for EnumNodes 73 void generateHtml(EnumNode[] nodes){ 74 tableNew("enums"); 75 tableRow(["id", "name", "visibility", "members"], true); 76 foreach (i, node; nodes) 77 tableRow([i.to!string, node.name, node.visibility.to!string, node.members.to!string]); 78 tableEnd(); 79 } 80 /// generates html for StructNodes 81 void generateHtml(StructNode[] nodes){ 82 tableNew("structs"); 83 foreach (i, node; nodes){ 84 tableNew(node.name, true); 85 tableRow(["id", i.to!string]); 86 tableRow(["visibility", node.visibility.to!string]); 87 tableRow(["containsRef", node.containsRef.to!string]); 88 tableRow(["members:"], true); 89 foreach (memberId; 0 .. node.membersName.length) 90 tableRow([node.membersDataType[memberId].name, node.membersName[i]]); 91 tableEnd(); 92 } 93 tableEnd(); 94 } 95 /// generates html for global variables 96 void generateHtml(VarDeclareNode[] nodes){ 97 tableNew("global variables"); 98 foreach (i, node; nodes){ 99 100 } 101 tableEnd(); 102 } 103 /// generates html for VarDeclareNode 104 void generateHtml(VarDeclareNode node, bool asRow = false){ 105 if (asRow){ 106 // id, data type, name, value 107 //foreach (node.) TODO 108 } 109 } 110 public: 111 /// constructor 112 this(){ 113 _html = new List!string; 114 } 115 ~this(){ 116 .destroy(_html); 117 } 118 /// generates html page for ScriptNode 119 void generateHtml(ScriptNode node){ 120 // throw stylesheet first 121 _html.append(STYLESHEET); 122 if (node.imports.length){ 123 tableNew("imports"); 124 foreach (i, importName; node.imports) 125 tableRow([to!string(i), importName]); 126 tableEnd(); 127 } 128 if (node.enums.length){ 129 generateHtml(node.enums); 130 } 131 if (node.structs.length){ 132 tableNew("structs"); 133 /*foreach (structNode; node.structs) 134 this.generateHtml(structNode); 135 tableEnd(); 136 } 137 if (node.variables.length){ 138 tableNew("global variables"); 139 foreach(var; node.variables) 140 generateHtml(var); 141 tableEnd(); 142 } 143 if (node.functions.length){ 144 tableNew("functions"); 145 foreach (func; node.functions) 146 generateHtml(func); 147 tableEnd();*/ 148 } 149 } 150 /// Returns: generated page as a string[] where each string is a separate line. does **not** include endl characters 151 @property string[] html(){ 152 return _html.toArray; 153 } 154 } 155 }