Writing a compiler in C# for pre-compiled templates

I have written high performance web application frameworks for JavaScript and PHP. Today I decided to start writing a high performance web application framework in C# (on Linux using Mono). Speed and simplicity are again the goals for this MVC framework. I have read that HttpListener is very fast (comparable to NodeJS), so that seemed like a logical starting point. The framework is far from done, but one of the most interesting things I did so far was that I looked into pre-compiled templates for optimal ease of use (template errors are shown during compile time). Normally these templates can be written in T4 or Razor, but the compile time errors are not so understandable (to me).

I hand-coded a few templates in C# and wrote some input in a template language that resembles “aspx” syntax (but is not). After that I wrote a compiler that would turn the template into that exact C# code to be compiled. The template:

<%@ Page Inherits="Layouts.Default" Using="System.Text,System.Text.RegularExpressions" %>
<% Context.Data ["title"] = Context.Data ["Name"]; %>
Email: <input type="text" value="<%= Context.Data["Email"] %>"></input>
Test: <input type="text" value="<%= "some string" %>"></input>

The generated C# code:

/**
 * WARNING: Generated file, do not edit, changes will be lost!
 **/

using System;
using System.Text;
using System.Text.RegularExpressions;

namespace Maussoft.Mvc.CsTest.Views.Test
{
	public class Index: Layouts.Default
	{
		public override void Content()
		{
			WriteLine();
			Context.Data ["title"] = Context.Data ["Name"]; WriteLine();
			WriteLine(@"Email: <input type=""text"" value=""{0}""></input>",  Context.Data["Email"]);
			Write(@"Test: <input type=""text"" value=""{0}""></input>",  "some string");
		}
	}
}

I started with some regular expressions, but soon found out that I had to write a real parser. The compiler deliberately outputs multiple commands per line to ensure every line of the template corresponds to a single line of code. This is one of the design goals and this behavior should improve the ease of debugging of the code, since the errors on the compiled template will be reported on the generated C# code.

I was looking into turning this into a “Custom Tool”, but after seeing the implementation differences between MonoDevelop and Visual Studio I decided on making an executable that your run before building (as a pre-build step). Next step for the framework is probably to add something like Dapper to have simple database support. Also a run-time debugger toolbar in the browser (like symfony2 has) would be beneficial.

All code is available on Github.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *