uCalc Transformer is Token-Aware Readable Intelligent Hierarchical Context-Aware Declarative Recursive Extensible Selective Safe

Discover the smart, token-aware engine for finding, replacing, and restructuring text. Move beyond the limitations of RegEx to safely refactor code, build linters, and transpile data with human-readable rules that understand the structure of your strings.

Smarter Text Processing for Complex Data

Regular expressions are fantastic for flat text, but they quickly become fragile when parsing structured data like source code, configuration files, or markup languages. uCalc Transformer was built from the ground up to understand structure. By tokenizing text before matching, it provides an inherently safe, robust, and extensible way to manipulate strings without the risk of catastrophic backtracking or accidental data corruption.

Safe by Default

Automatically respects structural boundaries, preventing accidental modifications inside string literals or configured code comments.

Declarative Syntax

Ditch the cryptic backslashes. Use clear, named variables and token categories to make your parsing logic self-documenting.

Seamless Integration

Leverage the full power of the uCalc Fast Math Parser directly within your replacement rules for dynamic data formatting.

uCalc Transformer is Readable

Clear patterns, no more cryptic syntax.

Say goodbye to "write-once, read-never" regular expressions. uCalc uses declarative, human-readable patterns. Instead of writing complex character boundary assertions, you can simply use built-in token category matchers like {@Number} or {@String}, and capture values directly into named variables. Your team will actually be able to read and maintain your parsing logic months down the line.

Extracts all numbers from a string, demonstrating the simplicity of the `{@Number}` category matcher.

ID: 1338

				
					using uCalcSoftware;

var uc = new uCalc();
using (var t = new uCalc.Transformer()) {
   t.FromTo("{@Number:n}", "[NUM:{n}]");

   var text = "Order 123 has 2 items for 49.95 total.";
   Console.WriteLine(t.Transform(text));
};
				
			
Order [NUM:123] has [NUM:2] items for [NUM:49.95] total.
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   {
      uCalc::Transformer t;
      t.Owned(); // Causes t to be released when it goes out of scope
      t.FromTo("{@Number:n}", "[NUM:{n}]");

      auto text = "Order 123 has 2 items for 49.95 total.";
      cout << t.Transform(text) << endl;
   };
}
				
			
Order [NUM:123] has [NUM:2] items for [NUM:49.95] total.
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Using t As New uCalc.Transformer()
         t.FromTo("{@Number:n}", "[NUM:{n}]")
         
         Dim text = "Order 123 has 2 items for 49.95 total."
         Console.WriteLine(t.Transform(text))
      End Using
   End Sub
End Module
				
			
Order [NUM:123] has [NUM:2] items for [NUM:49.95] total.

uCalc Transformer is Token-Aware

Sees structure, not just characters.

Traditional string replacement is blind to context. If you use standard tools to rename a variable in your code, you risk corrupting identical words hidden inside comments or string literals. uCalc Transformer breaks text into meaningful tokens first, ensuring your rules only apply exactly where they belong. This structural awareness makes it the ultimate tool for safe code refactoring and static analysis.

Demonstrates the Transformer's token-aware safety by correctly renaming a variable without corrupting a string literal or comment.

ID: 1264

				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();

// Turn single-line comments into whitespace tokens (to be ignored)
t.Tokens.Add("//.*", TokenType.Whitespace);

// Define a rule to replace the alphanumeric token 'x' with 'value'
t.FromTo("x", "value");

var code = "x = 10; print('The max value is x.'); // x is 10 here";

// The Transformer correctly identifies that only the first 'x' is
// a token on its own. Imbedded occurrences of 'x' are left alone.
Console.WriteLine(t.Transform(code));
				
			
value = 10; print('The max value is x.'); // x is 10 here
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;

   // Turn single-line comments into whitespace tokens (to be ignored)
   t.Tokens().Add("//.*", TokenType::Whitespace);

   // Define a rule to replace the alphanumeric token 'x' with 'value'
   t.FromTo("x", "value");

   auto code = "x = 10; print('The max value is x.'); // x is 10 here";

   // The Transformer correctly identifies that only the first 'x' is
   // a token on its own. Imbedded occurrences of 'x' are left alone.
   cout << t.Transform(code) << endl;
}
				
			
value = 10; print('The max value is x.'); // x is 10 here
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      
      '// Turn single-line comments into whitespace tokens (to be ignored)
      t.Tokens.Add("//.*", TokenType.Whitespace)
      
      '// Define a rule to replace the alphanumeric token 'x' with 'value'
      t.FromTo("x", "value")
      
      Dim code = "x = 10; print('The max value is x.'); // x is 10 here"
      
      '// The Transformer correctly identifies that only the first 'x' is
      '// a token on its own. Imbedded occurrences of 'x' are left alone.
      Console.WriteLine(t.Transform(code))
   End Sub
End Module
				
			
value = 10; print('The max value is x.'); // x is 10 here

uCalc Transformer is Intelligent

Built-in logic and dynamic evaluation.

Replacements aren't limited to static text. You can embed the full power of the uCalc expression parser directly inside your transformation rules. Capture a string of text, convert it to a number, perform a mathematical calculation, and insert the formatted result back into the output—all in a single, elegant step.

A practical example that calculates line-item totals for a list of products by capturing quantity and price.

ID: 1218

				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
// Rule to find quantity and price, then calculate total.
// Note the explicit Double() to convert the captured numerical
// values as text into double-precision numbers for {@Eval}.
t.FromTo("Qty: {@Number:qty}, Price: {@Number:price}",
"{@Self}, Total: {@Eval: Double(qty) * Double(price)}");

var invoice = """
Item: Book, Qty: 3, Price: 15.00
Item: Pen, Qty: 10, Price: 1.50
""";

Console.WriteLine(t.Transform(invoice));
				
			
Item: Book, Qty: 3, Price: 15.00, Total: 45
Item: Pen, Qty: 10, Price: 1.50, Total: 15
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   // Rule to find quantity and price, then calculate total.
   // Note the explicit Double() to convert the captured numerical
   // values as text into double-precision numbers for {@Eval}.
   t.FromTo("Qty: {@Number:qty}, Price: {@Number:price}",
   "{@Self}, Total: {@Eval: Double(qty) * Double(price)}");

   auto invoice = R"(Item: Book, Qty: 3, Price: 15.00
Item: Pen, Qty: 10, Price: 1.50)";

   cout << t.Transform(invoice) << endl;
}
				
			
Item: Book, Qty: 3, Price: 15.00, Total: 45
Item: Pen, Qty: 10, Price: 1.50, Total: 15
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      '// Rule to find quantity and price, then calculate total.
      '// Note the explicit Double() to convert the captured numerical
      '// values as text into double-precision numbers for {@Eval}.
      t.FromTo("Qty: {@Number:qty}, Price: {@Number:price}",
      "{@Self}, Total: {@Eval: Double(qty) * Double(price)}")
      
      Dim invoice = "Item: Book, Qty: 3, Price: 15.00
Item: Pen, Qty: 10, Price: 1.50"
      
      Console.WriteLine(t.Transform(invoice))
   End Sub
End Module
				
			
Item: Book, Qty: 3, Price: 15.00, Total: 45
Item: Pen, Qty: 10, Price: 1.50, Total: 15

uCalc Transformer is Hierarchical

Conquer nested data with ease.

Real-world data is rarely flat. From HTML tags to JSON objects, nesting is everywhere. uCalc Transformer supports hierarchical parsing via local scopes, allowing you to define child rules that apply only within the boundaries of a parent match. You can effortlessly parse multi-level structures without the headache of complex regex lookarounds.

A practical example that extracts all `<a>` tags, but only from within a specific `<nav>` section of an HTML document.

ID: 1240

				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();

// Ignore multi-line formatting
t.DefaultRuleSet.StatementSensitive = false;

// 1. Parent rule captures the content of the <nav> block.
var navRule = t.Pattern("<nav>{content}</nav>");

// 2. Get the local transformer for the nav block.
var local_t = navRule.LocalTransformer;

// 3. This rule will only find `<a>` tags inside the <nav> block.
local_t.Pattern("<a href={url}>{text}</a>");

var html = """
<nav>
  <a href="/home">Home</a>
  <a href="/about">About</a>
</nav>
<main>
  <p>Some text with another <a href="/other">other link</a>.</p>
</main>
""";

t.Text = html;
t.Find();

Console.WriteLine("--- Found Links (Innermost Matches Only) ---");
// Use InnermostOnly to see only the results from the local transformer.
Console.WriteLine(t.GetMatches(MatchesOption.InnermostOnly).Text);
				
			
--- Found Links (Innermost Matches Only) ---
<a href="/home">Home</a>
<a href="/about">About</a>
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();

   // Ignore multi-line formatting
   t.DefaultRuleSet().StatementSensitive(false);

   // 1. Parent rule captures the content of the <nav> block.
   auto navRule = t.Pattern("<nav>{content}</nav>");

   // 2. Get the local transformer for the nav block.
   auto local_t = navRule.LocalTransformer();

   // 3. This rule will only find `<a>` tags inside the <nav> block.
   local_t.Pattern("<a href={url}>{text}</a>");

   auto html = R"(<nav>
  <a href="/home">Home</a>
  <a href="/about">About</a>
</nav>
<main>
  <p>Some text with another <a href="/other">other link</a>.</p>
</main>)";

   t.Text(html);
   t.Find();

   cout << "--- Found Links (Innermost Matches Only) ---" << endl;
   // Use InnermostOnly to see only the results from the local transformer.
   cout << t.GetMatches(MatchesOption::InnermostOnly).Text() << endl;
}
				
			
--- Found Links (Innermost Matches Only) ---
<a href="/home">Home</a>
<a href="/about">About</a>
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      
      '// Ignore multi-line formatting
      t.DefaultRuleSet.StatementSensitive = false
      
      '// 1. Parent rule captures the content of the <nav> block.
      Dim navRule = t.Pattern("<nav>{content}</nav>")
      
      '// 2. Get the local transformer for the nav block.
      Dim local_t = navRule.LocalTransformer
      
      '// 3. This rule will only find `<a>` tags inside the <nav> block.
      local_t.Pattern("<a href={url}>{text}</a>")
      
      Dim html = "<nav>
  <a href=""/home"">Home</a>
  <a href=""/about"">About</a>
</nav>
<main>
  <p>Some text with another <a href=""/other"">other link</a>.</p>
</main>"
      
      t.Text = html
      t.Find()
      
      Console.WriteLine("--- Found Links (Innermost Matches Only) ---")
      '// Use InnermostOnly to see only the results from the local transformer.
      Console.WriteLine(t.GetMatches(MatchesOption.InnermostOnly).Text)
   End Sub
End Module
				
			
--- Found Links (Innermost Matches Only) ---
<a href="/home">Home</a>
<a href="/about">About</a>

uCalc Transformer is Versatile

From simple swaps to complete transpilers.

Whether you are sanitizing messy server logs, validating complex configuration files, or building a transpiler to convert legacy scripts into modern code, the Transformer scales to the task. It provides a lightweight, unified engine capable of handling everything from one-liner string edits to full-blown domain-specific languages.

A practical example that transpiles a multi-line legacy script, including comments, variables, and a conditional statement with a nested action.

ID: 1377

				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
// Rules must be defined in an order that allows for proper transformation.

// 1. Comment rule
t.FromTo("REM {comment}", "// {comment}");

// 2. Variable assignment rule
t.FromTo("LET {@Alpha:var} = {val}", "var {var} = {val};");

// 3. Print statement rule
t.FromTo("PRINT {output}", "console.log({output});");

// 4. IF...THEN rule with RewindOnChange to handle nested statements
var ifRule = t.FromTo("IF {condition} THEN {action}", """
if ({condition}) {
  {action}
}
""");
ifRule.RewindOnChange = true;

// The legacy script to transpile
var legacyScript = """
REM Initialize variables
LET X = 10
LET Y = X * 2
IF Y > 15 THEN PRINT "Value is large"
""";

// Run the transformation
Console.WriteLine(t.Transform(legacyScript));
				
			
// Initialize variables
var X = 10;
var Y = X * 2;
if (Y > 15) {
  console.log("Value is large");
}
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   // Rules must be defined in an order that allows for proper transformation.

   // 1. Comment rule
   t.FromTo("REM {comment}", "// {comment}");

   // 2. Variable assignment rule
   t.FromTo("LET {@Alpha:var} = {val}", "var {var} = {val};");

   // 3. Print statement rule
   t.FromTo("PRINT {output}", "console.log({output});");

   // 4. IF...THEN rule with RewindOnChange to handle nested statements
   auto ifRule = t.FromTo("IF {condition} THEN {action}", R"(if ({condition}) {
  {action}
})");
   ifRule.RewindOnChange(true);

   // The legacy script to transpile
   auto legacyScript = R"(REM Initialize variables
LET X = 10
LET Y = X * 2
IF Y > 15 THEN PRINT "Value is large")";

   // Run the transformation
   cout << t.Transform(legacyScript) << endl;
}
				
			
// Initialize variables
var X = 10;
var Y = X * 2;
if (Y > 15) {
  console.log("Value is large");
}
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      '// Rules must be defined in an order that allows for proper transformation.
      
      '// 1. Comment rule
      t.FromTo("REM {comment}", "// {comment}")
      
      '// 2. Variable assignment rule
      t.FromTo("LET {@Alpha:var} = {val}", "var {var} = {val};")
      
      '// 3. Print statement rule
      t.FromTo("PRINT {output}", "console.log({output});")
      
      '// 4. IF...THEN rule with RewindOnChange to handle nested statements
      Dim ifRule = t.FromTo("IF {condition} THEN {action}", "if ({condition}) {
  {action}
}")
      ifRule.RewindOnChange = true
      
      '// The legacy script to transpile
      Dim legacyScript = "REM Initialize variables
LET X = 10
LET Y = X * 2
IF Y > 15 THEN PRINT ""Value is large"""
      
      '// Run the transformation
      Console.WriteLine(t.Transform(legacyScript))
   End Sub
End Module
				
			
// Initialize variables
var X = 10;
var Y = X * 2;
if (Y > 15) {
  console.log("Value is large");
}

uCalc Transformer is Declarative

Describe what you want, not how to get it.

Stop writing complex loops and state machines to parse text. With the Transformer, you simply describe the structure of your data using readable patterns and variables. Whether you are extracting an optional error code from a server log or dealing with missing data fields, the engine handles the complex branching, conditional logic, and state management for you automatically.

Parses log entries to extract an optional error code, providing a default status when it's missing by using the `{!var:...}` fallback syntax.

ID: 1205

				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
// Pattern: Match "Log:", an optional level, and the message.
// Replacement: Use `{!level:INFO}` to insert 'INFO' if {level} is empty.
t.FromTo("Log: [{level: ERROR | WARN}] {msg}",
"Status:{!level:INFO}{level} | Msg:{msg}");

// Case 1: Level is present
Console.WriteLine(t.Transform("Log: ERROR File not found"));

// Case 2: Level is missing, so the fallback is used
Console.WriteLine(t.Transform("Log: System started successfully"));
				
			
Status:ERROR | Msg:File not found
Status:INFO | Msg:System started successfully
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   // Pattern: Match "Log:", an optional level, and the message.
   // Replacement: Use `{!level:INFO}` to insert 'INFO' if {level} is empty.
   t.FromTo("Log: [{level: ERROR | WARN}] {msg}",
   "Status:{!level:INFO}{level} | Msg:{msg}");

   // Case 1: Level is present
   cout << t.Transform("Log: ERROR File not found") << endl;

   // Case 2: Level is missing, so the fallback is used
   cout << t.Transform("Log: System started successfully") << endl;
}
				
			
Status:ERROR | Msg:File not found
Status:INFO | Msg:System started successfully
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      '// Pattern: Match "Log:", an optional level, and the message.
      '// Replacement: Use `{!level:INFO}` to insert 'INFO' if {level} is empty.
      t.FromTo("Log: [{level: ERROR | WARN}] {msg}",
      "Status:{!level:INFO}{level} | Msg:{msg}")
      
      '// Case 1: Level is present
      Console.WriteLine(t.Transform("Log: ERROR File not found"))
      
      '// Case 2: Level is missing, so the fallback is used
      Console.WriteLine(t.Transform("Log: System started successfully"))
   End Sub
End Module
				
			
Status:ERROR | Msg:File not found
Status:INFO | Msg:System started successfully

uCalc Transformer is Selective

Create safe zones with SkipOver.

Sometimes the most important part of a transformation is knowing what not to touch. The Transformer allows you to define strict "dead zones" in your text. Want to apply a set of formatting rules to an entire file but completely ignore anything inside a specific XML block or a C-style comment? A single SkipOver instruction makes that content invisible to the rest of your parsing logic.

A basic example demonstrating how to ignore a block of text in parentheses, preventing other rules from matching inside it.

ID: 1210

				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
t.FromTo("word", "WORD"); // Rule to uppercase 'word'
t.SkipOver("({ignore})"); // Rule to ignore content in parentheses

var text = "transform this word, but (not this word)";
Console.WriteLine(t.Transform(text));
				
			
transform this WORD, but (not this word)
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   t.FromTo("word", "WORD"); // Rule to uppercase 'word'
   t.SkipOver("({ignore})"); // Rule to ignore content in parentheses

   auto text = "transform this word, but (not this word)";
   cout << t.Transform(text) << endl;
}
				
			
transform this WORD, but (not this word)
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      t.FromTo("word", "WORD") '// Rule to uppercase 'word'
      t.SkipOver("({ignore})") '// Rule to ignore content in parentheses
      
      Dim text = "transform this word, but (not this word)"
      Console.WriteLine(t.Transform(text))
   End Sub
End Module
				
			
transform this WORD, but (not this word)

uCalc Transformer is Recursive

Tackle nested logic and multi-pass transpilation.

Complex text processing often requires multiple passes, where the result of one transformation needs to be processed again. The Transformer features an elegant rewinding capability. After a successful replacement, the engine can automatically rewind and re-scan the new text, making it incredibly simple to evaluate deeply nested expressions or build complete transpilers that convert legacy syntax into modern scripts from the inside out.

RewindOnChange

ID: 152

				
					using uCalcSoftware;

var uc = new uCalc();
var ExprT = uc.ExpressionTransformer;  // Transformer used for Eval() and Evaluate()

ExprT.DefaultRuleSet.RewindOnChange = true;

ExprT.FromTo("AddUp({x})", "{x}");
ExprT.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))");

ExprT.FromTo("ArgCount({x})", "1");
ExprT.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))");

ExprT.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})");

var Expression = "Average(1, 2, 3, 4)";
Console.WriteLine($"Input: {Expression}");
Console.WriteLine($"Transform: {ExprT.Transform(Expression)}");
Console.WriteLine($"Eval: {uc.Eval(Expression)}");
				
			
Input: Average(1, 2, 3, 4)
Transform: (1 + (2 + (3 + 4))) / (1 + (1 + (1 + 1)))
Eval: 2.5
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto ExprT = uc.ExpressionTransformer();  // Transformer used for Eval() and Evaluate()

   ExprT.DefaultRuleSet().RewindOnChange(true);

   ExprT.FromTo("AddUp({x})", "{x}");
   ExprT.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))");

   ExprT.FromTo("ArgCount({x})", "1");
   ExprT.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))");

   ExprT.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})");

   auto Expression = "Average(1, 2, 3, 4)";
   cout << "Input: " << Expression << endl;
   cout << "Transform: " << ExprT.Transform(Expression) << endl;
   cout << "Eval: " << uc.Eval(Expression) << endl;
}
				
			
Input: Average(1, 2, 3, 4)
Transform: (1 + (2 + (3 + 4))) / (1 + (1 + (1 + 1)))
Eval: 2.5
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim ExprT = uc.ExpressionTransformer  '// Transformer used for Eval() and Evaluate()
      
      ExprT.DefaultRuleSet.RewindOnChange = true
      
      ExprT.FromTo("AddUp({x})", "{x}")
      ExprT.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))")
      
      ExprT.FromTo("ArgCount({x})", "1")
      ExprT.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))")
      
      ExprT.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})")
      
      Dim Expression = "Average(1, 2, 3, 4)"
      Console.WriteLine($"Input: {Expression}")
      Console.WriteLine($"Transform: {ExprT.Transform(Expression)}")
      Console.WriteLine($"Eval: {uc.Eval(Expression)}")
   End Sub
End Module
				
			
Input: Average(1, 2, 3, 4)
Transform: (1 + (2 + (3 + 4))) / (1 + (1 + (1 + 1)))
Eval: 2.5

uCalc Transformer supports Constraints

Advanced data validation built right in.

It is not just about finding text; it is about ensuring data integrity. You can apply structural constraints directly to your rules to build powerful linters or configuration file validators. Enforce exactly how many times a specific key must appear, ensure headers exist, and validate that the captured data meets your exact specifications before any processing takes place.

Validates a configuration file format by enforcing the number of times specific keys must appear.

ID: 1450

				
					using uCalcSoftware;

var uc = new uCalc();
using (var validator = new uCalc.Transformer()) {
   // 1. Configure the transformer
   validator.DefaultRuleSet.StatementSensitive = false;
   validator.SkipOver(";{line}"); // Ignore comments

   // 2. Define rules with validation constraints
   var serverRule = validator.Pattern("'['Server']' {body}").SetMinimum(1).SetMaximum(1);
   serverRule.Description = "Server Section";

   var local_t = serverRule.LocalTransformer;
   var hostRule = local_t.Pattern("Host = {@Alpha}").SetMinimum(1).SetMaximum(1);
   hostRule.Description = "Host Key";

   var portRule = local_t.Pattern("Port = {@Number}").SetMinimum(1);
   portRule.Description = "Port Key";

   // --- Test Data ---
   var validConfig = "[Server]\nHost = db1\nPort = 1433";
   var invalidConfig = "Host = web1\nPort = 80"; // Missing [Server] section


   // --- Validate validConfig ---
   Console.WriteLine("--- Validating valid_config.ini ---");
   validator.SetText(validConfig).Find();
   Console.WriteLine($"  Server section check passed: {serverRule.Matches.Count() == 1}");
   Console.WriteLine($"  Host key check passed: {hostRule.Matches.Count() == 1}");
   Console.WriteLine($"  Port key check passed: {portRule.Matches.Count() >= 1}");
   Console.WriteLine("");

   // --- Validate invalidConfig ---
   Console.WriteLine("--- Validating invalid_config.ini ---");
   validator.SetText(invalidConfig).Find();
   Console.WriteLine($"  Server section check passed: {serverRule.Matches.Count() == 1}");
   // The host and port rules will have 0 matches because their parent rule (serverRule) failed.
   Console.WriteLine($"  Host key check passed: {hostRule.Matches.Count() == 1}");
   Console.WriteLine($"  Port key check passed: {portRule.Matches.Count() >= 1}");
}
				
			
--- Validating valid_config.ini ---
  Server section check passed: True
  Host key check passed: True
  Port key check passed: True

--- Validating invalid_config.ini ---
  Server section check passed: False
  Host key check passed: False
  Port key check passed: False
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

#define tf(IsTrue) ((IsTrue) ? "True" : "False")

int main() {
   uCalc uc;
   {
      uCalc::Transformer validator;
      validator.Owned(); // Causes validator to be released when it goes out of scope
      // 1. Configure the transformer
      validator.DefaultRuleSet().StatementSensitive(false);
      validator.SkipOver(";{line}"); // Ignore comments

      // 2. Define rules with validation constraints
      auto serverRule = validator.Pattern("'['Server']' {body}").SetMinimum(1).SetMaximum(1);
      serverRule.Description("Server Section");

      auto local_t = serverRule.LocalTransformer();
      auto hostRule = local_t.Pattern("Host = {@Alpha}").SetMinimum(1).SetMaximum(1);
      hostRule.Description("Host Key");

      auto portRule = local_t.Pattern("Port = {@Number}").SetMinimum(1);
      portRule.Description("Port Key");

      // --- Test Data ---
      auto validConfig = "[Server]\nHost = db1\nPort = 1433";
      auto invalidConfig = "Host = web1\nPort = 80"; // Missing [Server] section


      // --- Validate validConfig ---
      cout << "--- Validating valid_config.ini ---" << endl;
      validator.SetText(validConfig).Find();
      cout << "  Server section check passed: " << tf(serverRule.Matches().Count() == 1) << endl;
      cout << "  Host key check passed: " << tf(hostRule.Matches().Count() == 1) << endl;
      cout << "  Port key check passed: " << tf(portRule.Matches().Count() >= 1) << endl;
      cout << "" << endl;

      // --- Validate invalidConfig ---
      cout << "--- Validating invalid_config.ini ---" << endl;
      validator.SetText(invalidConfig).Find();
      cout << "  Server section check passed: " << tf(serverRule.Matches().Count() == 1) << endl;
      // The host and port rules will have 0 matches because their parent rule (serverRule) failed.
      cout << "  Host key check passed: " << tf(hostRule.Matches().Count() == 1) << endl;
      cout << "  Port key check passed: " << tf(portRule.Matches().Count() >= 1) << endl;
   }
}
				
			
--- Validating valid_config.ini ---
  Server section check passed: True
  Host key check passed: True
  Port key check passed: True

--- Validating invalid_config.ini ---
  Server section check passed: False
  Host key check passed: False
  Port key check passed: False
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Using validator As New uCalc.Transformer()
         '// 1. Configure the transformer
         validator.DefaultRuleSet.StatementSensitive = false
         validator.SkipOver(";{line}") '// Ignore comments
         
         '// 2. Define rules with validation constraints
         Dim serverRule = validator.Pattern("'['Server']' {body}").SetMinimum(1).SetMaximum(1)
         serverRule.Description = "Server Section"
         
         Dim local_t = serverRule.LocalTransformer
         Dim hostRule = local_t.Pattern("Host = {@Alpha}").SetMinimum(1).SetMaximum(1)
         hostRule.Description = "Host Key"
         
         Dim portRule = local_t.Pattern("Port = {@Number}").SetMinimum(1)
         portRule.Description = "Port Key"
         
         '// --- Test Data ---
         
         Dim validConfig = "[Server]" & vbNewLine & "Host = db1" & vbNewLine & "Port = 1433"
         Dim invalidConfig = "Host = web1" & vbNewLine & "Port = 80" '// Missing [Server] section
         
         '// --- Validate validConfig ---
         Console.WriteLine("--- Validating valid_config.ini ---")
         validator.SetText(validConfig).Find()
         Console.WriteLine($"  Server section check passed: {serverRule.Matches.Count() = 1}")
         Console.WriteLine($"  Host key check passed: {hostRule.Matches.Count() = 1}")
         Console.WriteLine($"  Port key check passed: {portRule.Matches.Count() >= 1}")
         Console.WriteLine("")
         
         '// --- Validate invalidConfig ---
         Console.WriteLine("--- Validating invalid_config.ini ---")
         validator.SetText(invalidConfig).Find()
         Console.WriteLine($"  Server section check passed: {serverRule.Matches.Count() = 1}")
         '// The host and port rules will have 0 matches because their parent rule (serverRule) failed.
         Console.WriteLine($"  Host key check passed: {hostRule.Matches.Count() = 1}")
         Console.WriteLine($"  Port key check passed: {portRule.Matches.Count() >= 1}")
      End Using
   End Sub
End Module
				
			
--- Validating valid_config.ini ---
  Server section check passed: True
  Host key check passed: True
  Port key check passed: True

--- Validating invalid_config.ini ---
  Server section check passed: False
  Host key check passed: False
  Port key check passed: False

uCalc Transformer is Extensible

Build your own Domain-Specific Languages.

You are not limited to the rules provided out of the box. The Transformer acts as the perfect bridge to create custom scripting environments. By transforming natural language commands or custom syntax into mathematical expressions the core parser can evaluate, you can build everything from interactive command-line calculators to readable financial DSLs that non-programmers can easily write and maintain.

The complete financial DSL processing a multi-line script of deposits, withdrawals, and interest calculation.

ID: 1331

				
					using uCalcSoftware;

var uc = new uCalc();
// 1. Initialize the account balance
uc.DefineVariable("balance = 0.0");

// 2. Define the DSL rules on the expression transformer
var t = uc.ExpressionTransformer;
t.FromTo("DEPOSIT {@Number:amount}", "balance = balance + {amount}");
t.FromTo("WITHDRAW {@Number:amount}", "balance = balance - {amount}");
t.FromTo("INTEREST {@Number:rate}", "balance = balance * (1 + {rate} / 100.0)");

// 3. Define the multi-line transaction script
var script = """

DEPOSIT 1000.00
WITHDRAW 50.75
INTEREST 0.5
WITHDRAW 200.00

""";

Console.WriteLine($"Initial Balance: {uc.Eval("balance")}");
Console.WriteLine("Processing script...");

// 4. Evaluate the entire script.
// Note: EvalStr returns the result of the LAST line.
// The intermediate lines modify the 'balance' variable.
uc.EvalStr(script);

// 5. Get the final balance
Console.WriteLine($"Final Balance: {uc.EvalStr("balance")}");
				
			
Initial Balance: 0
Processing script...
Final Balance: 753.99625
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // 1. Initialize the account balance
   uc.DefineVariable("balance = 0.0");

   // 2. Define the DSL rules on the expression transformer
   auto t = uc.ExpressionTransformer();
   t.FromTo("DEPOSIT {@Number:amount}", "balance = balance + {amount}");
   t.FromTo("WITHDRAW {@Number:amount}", "balance = balance - {amount}");
   t.FromTo("INTEREST {@Number:rate}", "balance = balance * (1 + {rate} / 100.0)");

   // 3. Define the multi-line transaction script
   auto script = R"(
DEPOSIT 1000.00
WITHDRAW 50.75
INTEREST 0.5
WITHDRAW 200.00
)";

   cout << "Initial Balance: " << uc.Eval("balance") << endl;
   cout << "Processing script..." << endl;

   // 4. Evaluate the entire script.
   // Note: EvalStr returns the result of the LAST line.
   // The intermediate lines modify the 'balance' variable.
   uc.EvalStr(script);

   // 5. Get the final balance
   cout << "Final Balance: " << uc.EvalStr("balance") << endl;
}
				
			
Initial Balance: 0
Processing script...
Final Balance: 753.99625
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// 1. Initialize the account balance
      uc.DefineVariable("balance = 0.0")
      
      '// 2. Define the DSL rules on the expression transformer
      Dim t = uc.ExpressionTransformer
      t.FromTo("DEPOSIT {@Number:amount}", "balance = balance + {amount}")
      t.FromTo("WITHDRAW {@Number:amount}", "balance = balance - {amount}")
      t.FromTo("INTEREST {@Number:rate}", "balance = balance * (1 + {rate} / 100.0)")
      
      '// 3. Define the multi-line transaction script
      Dim script = "
DEPOSIT 1000.00
WITHDRAW 50.75
INTEREST 0.5
WITHDRAW 200.00
"
      
      Console.WriteLine($"Initial Balance: {uc.Eval("balance")}")
      Console.WriteLine("Processing script...")
      
      '// 4. Evaluate the entire script.
      '// Note: EvalStr returns the result of the LAST line.
      '// The intermediate lines modify the 'balance' variable.
      uc.EvalStr(script)
      
      '// 5. Get the final balance
      Console.WriteLine($"Final Balance: {uc.EvalStr("balance")}")
   End Sub
End Module
				
			
Initial Balance: 0
Processing script...
Final Balance: 753.99625

Dive deeper by clicking one of the following step-by-step guides to building a real-world project.

Project: Building a Markdown to HTML Converter

Build a simple Markdown-to-HTML converter using the declarative rules of the uCalc Transformer.

Project: Building a JSON Formatter and Minifier

Build a simple parser for INI-style configuration files using the uCalc Transformer's hierarchical parsing capabilities.

Project: Creating a Simple DSL for Financial Transactions

Build a simple, readable Domain-Specific Language (DSL) for processing financial transactions using the ExpressionTransformer.

Project: A Unit Conversion DSL

Build a simple, readable Domain-Specific Language (DSL) for unit conversions using the ExpressionTransformer.

Project: Implementing a Custom Syntax Highlighter

Build a static analysis tool (linter) to enforce coding standards on a custom scripting language using the uCalc Transformer.

Project: Extracting and Aggregating Metrics from Server Logs

Build a server log parser that extracts and aggregates key performance metrics using the uCalc Transformer.