uCalc API Version: 5.7.0-preview.1 Released: 7/30/2026
Warning
uCalc API Preview Release Notice:This preview documentation describes the intended behavior of the API. It is not fully accurate or complete.The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.Use of the preview version in your production code is not recommended.
A step-by-step project to build a simple but powerful template engine, similar to Liquid or Jinja, using uCalc's Transformer and callback system.
This project will guide you through building a simple but powerful text template engine, similar to popular libraries like Shopify's Liquid or Python's Jinja. A template engine allows you to generate dynamic content by processing a template string with placeholders and logic, and filling it with data.
This is a perfect real-world showcase of how uCalc's Transformer and expression parser work together to create a custom Domain-Specific Language (DSL).
We want to create a system that can process a template like this:
Hello, {{ user_name }}!{% if is_premium_user %}Your premium access is active.{% endif %}Your items:{% for item in items %}- {{ item }}{% endfor %}Our engine will need to understand three constructs:
{{ ... }} to insert data.{% if ... %} ... {% endif %} to show content based on a condition.{% for ... %} ... {% endfor %} to iterate over a collection.First, we need some data for our template to use. We'll define these as standard variables in our uCalc instance.
csharp
// The data model for our template
uc.DefineVariable("user_name = 'Alice'");
uc.DefineVariable("is_premium_user = true");
uc.DefineVariable("items[] = {'Book', 'Pen', 'Paper'}");
{{ ... }}This is a simple find-and-replace task. We'll use a Transformer rule to find any content inside {{ }} and evaluate it.
csharp
// The {@@Eval} directive evaluates the captured 'expr' string.
t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}");
{% if ... %}For conditional blocks, we need to capture the condition and the body. We can then use the built-in IIf() function within an {@Eval} block to conditionally include the body.
Crucially, we must set RewindOnChange(true) on this rule. This tells the transformer to re-scan the output. Without it, any {{...}} placeholders inside the if block would not be processed.
csharp
// The RewindOnChange is essential for processing nested placeholders.
t.FromTo("{% if {cond} %}{body}{% endif %}", "{@@Eval: IIf({cond}, '{body}', '')}").RewindOnChange = true;
{% for ... %} via a CallbackA simple replacement can't handle loops. This requires a callback function that integrates with the host application's logic. We'll define a custom function, RenderLoop, that the transformer can call.
Our transformer rule will convert the {% for %} syntax into a call to this function:t.FromTo("{% for {var} in {collection} %}{body}{% endfor %}", "{@Eval: RenderLoop('{collection}', '{var}', '{body}')}").RewindOnChange = true;
The RenderLoop callback is the engine of our loop. It will:
uCalc instance.item).This powerful pattern allows the flexible script engine to drive complex, high-performance logic in the host application.
Dedicated template libraries like Scriban (.NET) or Jinja (Python) are powerful, but they come with a fixed, predefined syntax. You must use {{...}} or their specific keywords.
The uCalc Advantage is Flexibility. We just invented our own template language. With uCalc, the syntax is entirely under your control. You could just as easily define the syntax to be <%= ... %> or $VarName$ by simply changing the patterns in your transformer rules. This makes uCalc an ideal tool for not just using a language, but for building one tailored to your exact needs.
ID: 1368
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
// Define the data
uc.DefineVariable("user_name = 'Alice'");
// Define the placeholder rule
// '{' is a special character and must be escaped
t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}");
// Process the template
Console.WriteLine(t.Transform("Hello, {{ user_name }}!"));
Hello, Alice! using uCalcSoftware; var uc = new uCalc(); var t = uc.NewTransformer(); // Define the data uc.DefineVariable("user_name = 'Alice'"); // Define the placeholder rule // '{' is a special character and must be escaped t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}"); // Process the template Console.WriteLine(t.Transform("Hello, {{ user_name }}!"));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
// Define the data
uc.DefineVariable("user_name = 'Alice'");
// Define the placeholder rule
// '{' is a special character and must be escaped
t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}");
// Process the template
cout << t.Transform("Hello, {{ user_name }}!") << endl;
}
Hello, Alice! #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.NewTransformer(); // Define the data uc.DefineVariable("user_name = 'Alice'"); // Define the placeholder rule // '{' is a special character and must be escaped t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}"); // Process the template cout << t.Transform("Hello, {{ user_name }}!") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
'// Define the data
uc.DefineVariable("user_name = 'Alice'")
'// Define the placeholder rule
'// '{' is a special character and must be escaped
t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}")
'// Process the template
Console.WriteLine(t.Transform("Hello, {{ user_name }}!"))
End Sub
End Module
Hello, Alice! Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.NewTransformer() '// Define the data uc.DefineVariable("user_name = 'Alice'") '// Define the placeholder rule '// '{' is a special character and must be escaped t.FromTo("'{' '{' {expr} '}' '}'", "{@@Eval: expr}") '// Process the template Console.WriteLine(t.Transform("Hello, {{ user_name }}!")) End Sub End Module