Expression Runtime
6 02 2009I recently encountered a bizarre requirement for an application. The client required a flexible expression syntax that would allow for the calculation of product prices in their administrative module. The solution for this ended up being a fun exercise so I thought I would share my findings.
A Little Background
The application being built is a combination of three existing systems with the primary administrative system being a Microsoft Acess database. The access database leverages Visual Basic for Applications to handle the cost equations and the expectation was to have similar functionality within the web application. Obviously it wasn’t going to come CLOSE to the power of VBA, but the current equations only made use of a few features of the platform.
Step One: Defining a Grammar
I went back and forth in my head and with one of my co-workers on the possible solutions to this problem. Our first initial understanding of the requirements were quite different so our solutions varied greatly. However, after fully understanding the client’s needs, we realized that we would need to allow them to manually input the expressions and we would need to evaluate them. Rather than writing a parser manually (which could take FOREVER), I ventured off on google and started looking up expression evaluators in C#.
Two google searches later, I stumbled upon an article that explain a grammar definition in Extended Backus Naur Form that did almost everything that I needed it to do. It was written to be parsed by Antlr and had all the code examples I could possibly imagine. Since the current solution leveraged the power of VBA, that meant that they had the power of retrieving the current values of textboxes. We wouldn’t be operating in the same fashion so I built the concept of variables into the grammar.
I should mention that we have another project that requires something similar. It doesn’t necessarily require the same level of power, it still requires the basic evaluation of expressions so I decided to build this as another feature into our shared framework. As such, the grammar and the evaluation of expressions was designed with extensibility in mind.
Step Two: Test It!
The examples that I found were outstanding. After various tweaks of the overall object model to allow for extensibility, and to conform to our framework design guidelines, a skeleton platofrm was in place and ready to be created.
Since I was creating a simplified version of VBA that meant that I needed some support for functions. The most frequently used function in the sample equations I had was the IIF function - which is simply a ternary operator. The grammar supported the use of functions (e.g., iif(arg0, arg1, arg2)) so it wasn’t too hard to implement a quick few blocks of code to run the sample equations that I had. In fact, the syntax barely changed!
So I have this quick and dirty console application that sits on top of my class library and evaluates a simple expression. I’m feeling pretty good about it but I just wrote an IF statement to check the name of the function being called and wrote some code that was very specific to just that function. Knowing that this needs to be extensible, I wasn’t very pleased with that…knowing how often requirements change, I couldn’t help but imagine the question being asked: “what if I need to…”
Step Three: Design for Extensibility
There were two points of extensibility that needed to be addressed. I’m a fan of the idea that support for extensibility is what truly separates a class library from a framework. By designing particular points of extensibility, I was pretty comfortable calling my little library a framework at this point. OK, so where does the framework look for functions? Do we support namespaces (e.g., alias.functionName)? Well, the grammar allows the syntax for namespaces…I got it! I’ll build a provider for evaluating functions. The provider implementation will be responsible for knowing how to look up functions.
After writing the abstracted code to support the provider, I created a default implementation that would use reflection to invoke function calls. I then wrote yet another provider to tell the reflection provider where to look for “libraries” for future support of namespaces. This also meant that I can write any function I want in C# and make it available to the expression runtime.

Figure 1.1
Step Four: Test It (Again)!
The default expression function library only contained the VBA mapping of the “IIF” function and it was working great. It was also evaluating variables perfectly so I decided to have a little fun and add some mathematical functions in C# and see what happened…and they worked! The reflection implementation simply operates off of the ExpressionFunctionAttribute class so it’s really easy to extend the runtime.
It definitely wasn’t your everyday requirement but it was a lot of fun to write =).
1 Comment



