Mercurial > projects > dil
diff trunk/src/main.d @ 322:ed4ef0173793
- Moved out large TOK switch case to function printToken().
- Renamed tokensToXML() to tokensToDoc() and added parameter 'options'.
- Not using string literals anymore to print XML tags. Created an enum and two tables, for XML and HTML, with entries for every tag that needs to be printed.
- Added function getShortClassName() which returns the short class name of a class that inherits from Node.
- Added new styles to and changed some in format.css.
author | aziz |
---|---|
date | Mon, 20 Aug 2007 19:59:04 +0000 |
parents | 29c33ce6c5bb |
children | 6259fb93e3dd |
line wrap: on
line diff
--- a/trunk/src/main.d Mon Aug 20 19:47:03 2007 +0000 +++ b/trunk/src/main.d Mon Aug 20 19:59:04 2007 +0000 @@ -23,8 +23,30 @@ switch (command) { case "hl", "highlight": - if (args.length == 3) - tokensToXML(args[2]); + char[] fileName; + DocOption options; + foreach (arg; args[2..$]) + { + switch (arg) + { + case "--tokens": + options |= DocOption.Tokens; break; + case "--syntax": + options |= DocOption.Syntax; break; + case "--xml": + options |= DocOption.XML; break; + case "--html": + options |= DocOption.HTML; break; + default: + fileName = arg; + } + } + if (!(options & (DocOption.XML | DocOption.HTML))) + options |= DocOption.XML; // Default to XML. + if (options & DocOption.Syntax) + syntaxToDoc(fileName, options); + else + tokensToDoc(fileName, options); break; case "parse": if (args.length == 3) @@ -34,6 +56,14 @@ } } +enum DocOption +{ + Tokens, + Syntax = 1<<1, + HTML = 1<<2, + XML = 1<<3 +} + void parse(string fileName) { auto sourceText = cast(char[]) std.file.read(fileName); @@ -71,27 +101,305 @@ return result; } -void tokensToXML(string fileName) +char[] getShortClassName(Node n) +{ + alias std.string.find find; + char[] name = n.classinfo.name; + name = name[find(name, ".")+1 .. $]; // Remove module name + char[] remove; + switch (n.category) + { + alias NodeCategory NC; + case NC.Declaration: remove = "Declaration"; break; + case NC.Statement: + if (n.kind == NodeKind.Statements) + return name; + remove = "Statement"; + break; + case NC.Expression: remove = "Expression"; break; + case NC.Type: remove = "Type"; break; + case NC.Other: return name; + default: + } + // Remove common suffix. + auto idx = find(name, remove); + if (idx != -1) + name = name[0 .. idx]; + return name; +} + +enum DocPart { + Head, + CompBegin, + CompEnd, + Error, + SyntaxBegin, + SyntaxEnd, + SrcBegin, + SrcEnd, + Tail, + // Tokens: + Identifier, + Comment, + StringLiteral, + CharLiteral, + Operator, + LorG, + LessEqual, + GreaterEqual, + AndLogical, + OrLogical, + NotEqual, + Not, + Number, + Bracket, + SpecialToken, + Shebang, + Keyword, +} + +auto html_tags = [ + // Head + `<html>`\n + `<head>`\n + `<meta http-equiv="Content-Type" content="text/html; charset=utf-8">`\n + `<link href="dil_html.css" rel="stylesheet" type="text/css">`\n + `</head>`\n + `<body>`[], + // CompBegin + `<div class="compilerinfo">`, + // CompEnd + `</div>`, + // Error + `<p class="error %s">%s(%d)%s: %s</p>`, + // SyntaxBegin + `<span class="%s %s">`, + // SyntaxEnd + `</span>`, + // SrcBegin + `<pre class="sourcecode">`, + // SrcEnd + `</pre>`, + // Tail + `</html>`, + // Identifier + `<span class="i">%s</span>`, + // Comment + `<span class="c%s">%s</span>`, + // StringLiteral + `<span class="sl">%s</span>`, + // CharLiteral + `<span class="cl">%s</span>`, + // Operator + `<span class="op">%s</span>`, + // LorG + `<span class="oplg"><></span>`, + // LessEqual + `<span class="ople"><=</span>`, + // GreaterEqual + `<span class="opge">>=</span>`, + // AndLogical + `<span class="opaa">&&</span>`, + // OrLogical + `<span class="opoo">||</span>`, + // NotEqual + `<span class="opne">!=</span>`, + // Not + `<span class="opn">!</span>`, + // Number + `<span class="n">%s</span>`, + // Bracket + `<span class="br">%s</span>`, + // SpecialToken + `<span class="st">%s</span>`, + // Shebang + `<span class="shebang">%s</span>`, + // Keyword + `<span class="k">%s</span>`, +]; + +auto xml_tags = [ + // Head + `<?xml version="1.0"?>`\n + `<?xml-stylesheet href="format.css" type="text/css"?>`\n + `<root>`[], + // CompBegin + `<compilerinfo>`, + // CompEnd + `</compilerinfo>`, + // Error + `<error t="%s">%s(%d)%s: %s</error>`, + // SyntaxBegin + `<%s t="%s">`, + // SyntaxEnd + `</%s>`, + // SrcBegin + `<sourcecode>`, + // SrcEnd + `</sourcecode>`, + // Tail + `</root>`, + // Identifier + "<i>%s</i>", + // Comment + `<c t="%s">%s</c>`, + // StringLiteral + "<sl>%s</sl>", + // CharLiteral + "<cl>%s</cl>", + // Operator + "<op>%s</op>", + // LorG + `<op t="lg"><></op>`, + // LessEqual + `<op t="le"><=</op>`, + // GreaterEqual + `<op t="ge">>=</op>`, + // AndLogical + `<op t="aa">&&</op>`, + // OrLogical + `<op t="oo">||</op>`, + // NotEqual + `<op t="ne">!=</op>`, + // Not + `<op t="n">!</op>`, + // Number + "<n>%s</n>", + // Bracket + "<br>%s</br>", + // SpecialToken + "<st>%s</st>", + // Shebang + "<shebang>%s</shebang>", + // Keyword + "<k>%s</k>", +]; + +static assert(html_tags.length == DocPart.max+1); +static assert(xml_tags.length == DocPart.max+1); + +void syntaxToDoc(string fileName, DocOption options) +{ + auto tags = options & DocOption.HTML ? html_tags : xml_tags; + auto sourceText = cast(char[]) std.file.read(fileName); + auto parser = new Parser(sourceText, fileName); + parser.start(); + auto root = parser.parseModule(); + auto lx = parser.lx; + + auto token = lx.head; + char* end = lx.text.ptr; + + writefln(tags[DocPart.Head]); + // Output error messages. + if (lx.errors.length || parser.errors.length) + { + writefln(tags[DocPart.CompBegin]); + foreach (error; lx.errors) + { + writefln(tags[DocPart.Error], "L", lx.fileName, error.loc, "L", xml_escape(error.getMsg)); + } + foreach (error; parser.errors) + { + writefln(tags[DocPart.Error], "P", lx.fileName, error.loc, "P", xml_escape(error.getMsg)); + } + writefln(tags[DocPart.CompEnd]); + } + writef(tags[DocPart.SrcBegin]); + + Node[][Token*] beginNodes, endNodes; + + void populateAAs(Node[] nodes) + { + foreach (node; nodes) + { + auto begin = node.begin; + if (begin) + { + auto end = node.end; + assert(end); + beginNodes[begin] ~= node; + endNodes[end] ~= node; + } + if (node.children.length) + populateAAs(node.children); + } + } + populateAAs(root.children); + + char[] getTag(NodeCategory nc) + { + char[] tag; + switch (nc) + { + alias NodeCategory NC; + case NC.Declaration: tag = "d"; break; + case NC.Statement: tag = "s"; break; + case NC.Expression: tag = "e"; break; + case NC.Type: tag = "t"; break; + case NC.Other: tag = "o"; break; + default: + } + return tag; + } + + // Traverse linked list and print tokens. + while (token.type != TOK.EOF) + { + token = token.next; + + // Print whitespace between previous and current token. + if (end != token.start) + writef("%s", end[0 .. token.start - end]); + + Node[]* nodes = token in beginNodes; + + if (nodes) + { + foreach (node; *nodes) + writef(tags[DocPart.SyntaxBegin], getTag(node.category), getShortClassName(node)); + } + + printToken(token, tags); + + nodes = token in endNodes; + + if (nodes) + { + foreach_reverse (node; *nodes) + if (options & DocOption.HTML) + writef(tags[DocPart.SyntaxEnd]); + else + writef(tags[DocPart.SyntaxEnd], getTag(node.category)); + } + + end = token.end; + } + writef(tags[DocPart.SrcEnd], tags[DocPart.Tail]); +} + +void tokensToDoc(string fileName, DocOption options) +{ + auto tags = options & DocOption.HTML ? html_tags : xml_tags; auto sourceText = cast(char[]) std.file.read(fileName); auto lx = new Lexer(sourceText, fileName); auto token = lx.getTokens(); char* end = lx.text.ptr; - writefln(`<?xml version="1.0"?>`\n - `<?xml-stylesheet href="format.css" type="text/css"?>`\n - `<root>`); + writefln(tags[DocPart.Head]); + if (lx.errors.length) { - writefln("<compilerinfo>"); + writefln(tags[DocPart.CompBegin]); foreach (error; lx.errors) { - writefln(`<error t="%s">%s(%d): %s</error>`, "l", lx.fileName, error.loc, xml_escape(error.getMsg)); + writefln(tags[DocPart.Error], "L", lx.fileName, error.loc, "L", xml_escape(error.getMsg)); } - writefln("</compilerinfo>"); + writefln(tags[DocPart.CompEnd]); } - writef(`<sourcetext>`); + writef(tags[DocPart.SrcBegin]); // Traverse linked list and print tokens. while (token.type != TOK.EOF) @@ -101,103 +409,108 @@ // Print whitespace between previous and current token. if (end != token.start) writef("%s", xml_escape(end[0 .. token.start - end])); - - string srcText = xml_escape(token.srcText); - - switch(token.type) - { - case TOK.Identifier: - writef("<i>%s</i>", srcText); - break; - case TOK.Comment: - string c; - switch (token.start[1]) - { - case '/': c = "l"; break; - case '*': c = "b"; break; - case '+': c = "n"; break; - default: - assert(0); - } - writef(`<c c="%s">%s</c>`, c, srcText); - break; - case TOK.String: - writef("<sl>%s</sl>", srcText); - break; - case TOK.CharLiteral, TOK.WCharLiteral, TOK.DCharLiteral: - writef("<cl>%s</cl>", srcText); - break; - case TOK.Assign, TOK.Equal, - TOK.Less, TOK.Greater, - TOK.LShiftAssign, TOK.LShift, - TOK.RShiftAssign, TOK.RShift, - TOK.URShiftAssign, TOK.URShift, - TOK.OrAssign, TOK.OrBinary, - TOK.AndAssign, TOK.AndBinary, - TOK.PlusAssign, TOK.PlusPlus, TOK.Plus, - TOK.MinusAssign, TOK.MinusMinus, TOK.Minus, - TOK.DivAssign, TOK.Div, - TOK.MulAssign, TOK.Mul, - TOK.ModAssign, TOK.Mod, - TOK.XorAssign, TOK.Xor, - TOK.CatAssign, - TOK.Tilde, - TOK.Unordered, - TOK.UorE, - TOK.UorG, - TOK.UorGorE, - TOK.UorL, - TOK.UorLorE, - TOK.LorEorG: - writef("<op>%s</op>", srcText); - break; - case TOK.LorG: - writef(`<op c="lg"><></op>`); - break; - case TOK.LessEqual: - writef(`<op c="le"><=</op>`); - break; - case TOK.GreaterEqual: - writef(`<op c="ge">>=</op>`); - break; - case TOK.AndLogical: - writef(`<op c="aa">&&</op>`); - break; - case TOK.OrLogical: - writef(`<op c="oo">||</op>`); - break; - case TOK.NotEqual: - writef(`<op c="ne">!=</op>`); - break; - case TOK.Not: - // Check if this is part of a template instantiation. - // TODO: comments aren't skipped. - if (token.prev.type == TOK.Identifier && token.next.type == TOK.LParen) - goto default; - writef(`<op c="n">!</op>`); - break; - case TOK.Int32, TOK.Int64, TOK.Uint32, TOK.Uint64, - TOK.Float32, TOK.Float64, TOK.Float80, - TOK.Imaginary32, TOK.Imaginary64, TOK.Imaginary80: - writef("<n>%s</n>", srcText); - break; - case TOK.LParen, TOK.RParen, TOK.LBracket, - TOK.RBracket, TOK.LBrace, TOK.RBrace: - writef("<br>%s</br>", srcText); - break; - case TOK.Special: - writef("<st>%s</st>", srcText); - break; - case TOK.Shebang: - writef("<shebang>%s</shebang>", srcText); - break; - default: - if (token.isKeyword()) - writef("<k>%s</k>", srcText); - else - writef("%s", srcText); - } + printToken(token, tags); end = token.end; } - writef("\n</sourcetext>\n</root>"); -} \ No newline at end of file + writef(\n, tags[DocPart.SrcEnd], \n, tags[DocPart.Tail]); +} + +void printToken(Token* token, string[] tags) +{ + alias DocPart DP; + string srcText = xml_escape(token.srcText); + + switch(token.type) + { + case TOK.Identifier: + writef(tags[DP.Identifier], srcText); + break; + case TOK.Comment: + string t; + switch (token.start[1]) + { + case '/': t = "l"; break; + case '*': t = "b"; break; + case '+': t = "n"; break; + default: + assert(0); + } + writef(tags[DP.Comment], t, srcText); + break; + case TOK.String: + writef(tags[DP.StringLiteral], srcText); + break; + case TOK.CharLiteral, TOK.WCharLiteral, TOK.DCharLiteral: + writef(tags[DP.CharLiteral], srcText); + break; + case TOK.Assign, TOK.Equal, + TOK.Less, TOK.Greater, + TOK.LShiftAssign, TOK.LShift, + TOK.RShiftAssign, TOK.RShift, + TOK.URShiftAssign, TOK.URShift, + TOK.OrAssign, TOK.OrBinary, + TOK.AndAssign, TOK.AndBinary, + TOK.PlusAssign, TOK.PlusPlus, TOK.Plus, + TOK.MinusAssign, TOK.MinusMinus, TOK.Minus, + TOK.DivAssign, TOK.Div, + TOK.MulAssign, TOK.Mul, + TOK.ModAssign, TOK.Mod, + TOK.XorAssign, TOK.Xor, + TOK.CatAssign, + TOK.Tilde, + TOK.Unordered, + TOK.UorE, + TOK.UorG, + TOK.UorGorE, + TOK.UorL, + TOK.UorLorE, + TOK.LorEorG: + writef(tags[DP.Operator], srcText); + break; + case TOK.LorG: + writef(tags[DP.LorG]); + break; + case TOK.LessEqual: + writef(tags[DP.LessEqual]); + break; + case TOK.GreaterEqual: + writef(tags[DP.GreaterEqual]); + break; + case TOK.AndLogical: + writef(tags[DP.AndLogical]); + break; + case TOK.OrLogical: + writef(tags[DP.OrLogical]); + break; + case TOK.NotEqual: + writef(tags[DP.NotEqual]); + break; + case TOK.Not: + // Check if this is part of a template instantiation. + // TODO: comments aren't skipped. + if (token.prev.type == TOK.Identifier && token.next.type == TOK.LParen) + goto default; + writef(tags[DP.Not]); + break; + case TOK.Int32, TOK.Int64, TOK.Uint32, TOK.Uint64, + TOK.Float32, TOK.Float64, TOK.Float80, + TOK.Imaginary32, TOK.Imaginary64, TOK.Imaginary80: + writef(tags[DP.Number], srcText); + break; + case TOK.LParen, TOK.RParen, TOK.LBracket, + TOK.RBracket, TOK.LBrace, TOK.RBrace: + writef(tags[DP.Bracket], srcText); + break; + case TOK.Special: + writef(tags[DP.SpecialToken], srcText); + break; + case TOK.Shebang: + writef(tags[DP.Shebang], srcText); + break; + default: + if (token.isKeyword()) + writef(tags[DP.Keyword], srcText); + else + writef("%s", srcText); + } +}