diff --git a/analysis/output.d b/analysis/output.d
deleted file mode 100644
index 8bc2fcb..0000000
--- a/analysis/output.d
+++ /dev/null
@@ -1,251 +0,0 @@
-module analysis.output;
-
-import std.stdio;
-import std.algorithm;
-import stdx.d.lexer;
-import analysis.base;
-import analysis.linespan;
-import highlighter;
-
-void writeWhitespace(File file, string text, ref uint line, MessageSet messages,
-	ref const LineSpans spans)
-{
-	foreach (char c; text)
-	{
-		if (c == '\r')
-			continue;
-		else if (c == '\n')
-		{
-			if (spans.containsLine(line))
-				file.write("\n");
-			foreach (message; messages[].filter!(a => a.line == line - 1))
-				writeMessage(file, message);
-			bool prevWasVisible = false;
-			if (spans.containsLine(line))
-			{
-				prevWasVisible = true;
-				file.writef("<span class=\"ln\">%d</span>", line);
-			}
-			line++;
-			if (!spans.containsLine(line) && prevWasVisible)
-				file.writeln("<div class=\"separator\"/></div>");
-		}
-		else if (spans.containsLine(line))
-		{
-			if (c == '\t')
-				file.write("    ");
-			else
-				file.write(c);
-		}
-	}
-}
-
-void writeStrOrCom(File file, string text, string cssClass, ref uint line,
-	ref const LineSpans spans)
-{
-	file.write("<span class=\"", cssClass, "\">");
-	foreach (char c; text)
-	{
-		if (c == '\r')
-			continue;
-		else if (c == '\n')
-		{
-			bool prevWasVisible = false;
-			if (spans.containsLine(line))
-			{
-				prevWasVisible = true;
-				file.writef("\n</span><span class=\"ln\">%d</span><span class=\"%s\">", line, cssClass);
-			}
-			line++;
-			if (!spans.containsLine(line) && prevWasVisible)
-				file.writeln("<div class=\"separator\"/></div>");
-		}
-		else if (spans.containsLine(line))
-		{
-			if (c == '<')
-				file.write("&lt;");
-			else if (c == '&')
-				file.write("&amp;");
-			else
-				file.write(c);
-		}
-	}
-	file.write("</span>");
-}
-
-void writeToken(File file, ref const Token t, ref uint line, MessageSet messages,
-	ref const LineSpans spans)
-{
-	if (t == tok!"whitespace")
-		writeWhitespace(file, t.text, line, messages, spans);
-	else if (t.type == tok!"comment")
-		writeStrOrCom(file, t.text, "com", line, spans);
-	else if (isStringLiteral(t.type) || t.type == tok!"characterLiteral")
-		writeStrOrCom(file, t.text, "str", line, spans);
-	else if (spans.containsLine(line))
-	{
-		if (isBasicType(t.type))
-			file.writeSpan("type", str(t.type));
-		else if (isKeyword(t.type))
-			file.writeSpan("kwrd", str(t.type));
-		else if (isNumberLiteral(t.type))
-			file.writeSpan("num", t.text);
-		else if (isOperator(t.type))
-			file.writeSpan("op", str(t.type));
-		else
-			file.write(t.text);
-	}
-}
-
-void writeMessage(File file, ref const Message message)
-{
-	file.write("<div class=\"warning\">");
-	file.write(message.message);
-	file.writeln("</div>");
-}
-
-void writeHeader(File file)
-{
-	file.writeln(q"[
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>]");
-	file.writeln("<title>D-Scanner Report</title>");
-	file.writeln("<style type=\"text/css\">\n", SOLARIZED_CSS, "\n",
-		STATIC_ANALYSIS_CSS, "\n</style>");
-	file.writeln("</head>");
-	file.writeln("<body>");
-}
-
-void writeFooter(File file)
-{
-	file.writeln("</body>");
-	file.writeln("</html>");
-}
-
-void writeHtmlReport(File file, MessageSet[string] messages, shared(StringCache)* cache)
-{
-	import std.array;
-	import std.conv;
-	writeHeader(file);
-	writeSummary(file, messages);
-	foreach (fileName, messageSet; messages)
-	{
-		writeln("Processing messages for ", fileName);
-		if (messageSet.empty)
-			continue;
-		File f = File(fileName);
-		auto bytes = uninitializedArray!(ubyte[])(to!size_t(f.size));
-		f.rawRead(bytes);
-		LexerConfig config;
-		config.commentBehavior = CommentBehavior.include;
-		config.whitespaceBehavior = WhitespaceBehavior.include;
-		config.stringBehavior = StringBehavior.source;
-		const(Token)[] tokens = byToken(bytes, config, cache).array;
-		file.writeln("<div class=\"section\" name=\"", fileName, "\">");
-		file.writeln("<h1><a name=\"", fileName, "\">", fileName, "</a></h1>");
-		file.writeln("<pre>");
-		uint currentLine = 2;
-		LineSpans ls = generateLineSpans(messageSet);
-		if (ls.containsLine(1))
-			file.write("<span class=\"ln\">1</span>");
-		foreach (token; tokens)
-		{
-			writeToken(file, token, currentLine, messageSet, ls);
-		}
-		file.writeln("</pre>");
-		file.writeln("</div>");
-
-	}
-	writeFooter(file);
-}
-
-void writeSummary(File file, MessageSet[string] messages)
-{
-	size_t[string] warningCounts;
-	bool hasWarnings;
-	foreach (fileName, messageSet; messages)
-	{
-		warningCounts[fileName] = messageSet.length;
-		if (messageSet.length > 0)
-			hasWarnings = true;
-	}
-	if (!hasWarnings)
-	{
-		file.writeln("<div id=\"summary\" class=\"section\">No warnings detected</div>");
-		return;
-	}
-	file.writeln("<div id=\"summary\" class=\"section\">");
-	file.writeln("<h1>Summary</h1>");
-	file.write("<table>");
-	file.writeln("<thead><tr><th>File</th></th><th>Warning Count</th></tr></thead>");
-	file.write("<tbody>");
-	foreach (fileName, warningCount; warningCounts)
-	{
-		if (warningCount > 0)
-			file.writeln("<tr><td><a href=\"#", fileName, "\">", fileName, "</td><td>", warningCount, "</td></tr>");
-	}
-	file.write("</tbody>");
-	file.write("</table>");
-	file.write("</div>");
-}
-
-LineSpans generateLineSpans(MessageSet messages)
-{
-	LineSpans l;
-	foreach (message; messages[])
-	{
-		l.addLine(message.line);
-	}
-	return l;
-}
-
-immutable string STATIC_ANALYSIS_CSS = "
-.ln {
-	width: 5em;
-	display: inline-block;
-	margin-left: -4em;
-	border-right: .1em solid #839496;
-	margin-right: 1em;
-}
-.warning {
-	display: block;
-	border-radius: 1em;
-	border-top: .1em solid ##dc322f;
-	color: #002b36;
-	background-color: #fdf6e3;
-	padding: 1em;
-	margin: .5em 0 -.5em 0;
-}
-pre {
-	padding-left: 5em;
-	margin: 0;
-	border-radius: 0 0 1em 1em;
-}
-
-.section {
-	border: .1em solid #839496;
-	margin: 2em 0;
-	padding: 0;
-	border-radius: 1em;
-}
-
-.section h1 {
-    font-weight: normal;
-    color: #002b36;
-	background-color: #fdf6e3;
-    margin: 0;
-    padding: .5em;
-    border-radius: 1em 1em 0 0;
-    font-size: medium;
-}
-
-.separator {
-	display: block;
-	height: 1em;
-	margin: 0;
-	padding: 0;
-	border-bottom: .1em dashed #fdf6e3;
-}
-";
diff --git a/stdx/d/parser.d b/stdx/d/parser.d
index f55490a..a2415a3 100644
--- a/stdx/d/parser.d
+++ b/stdx/d/parser.d
@@ -142,7 +142,7 @@ private:
  * Returns: the parsed module
  */
 Module parseModule(const(Token)[] tokens, string fileName, CAllocator allocator = null,
-    void delegate(string, size_t, size_t, string, bool) messageFunction = null)
+    void function(string, size_t, size_t, string, bool) messageFunction = null)
 {
     auto parser = new Parser();
     parser.fileName = fileName;
@@ -6241,7 +6241,7 @@ q{doStuff(5)}c;
      * The parameters are the file name, line number, column number,
      * and the error or warning message.
      */
-    void delegate(string, size_t, size_t, string, bool) messageFunction;
+    void function(string, size_t, size_t, string, bool) messageFunction;
 
     bool isSliceExpression()
     {