uCalc API Version: 2.1.3-preview.2 Released: 6/17/2026

Warning

uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.

ExpressionTransformer = [Transformer]

Property

Product: 

Fast Math Parser

Class: 

uCalcBase

Returns the singleton transformer instance used to pre-process expressions before they are parsed.

Remarks

Returns the singleton Transformer instance dedicated to pre-processing expressions before they are parsed by functions like Eval, EvalStr, and Parse.

This powerful feature allows you to define structural, token-aware rewrite rules to create custom syntax, simplify complex expressions, or transpile constructs from other languages.


⚙️ How It Works

When you define a rule on the ExpressionTransformer, any expression string passed to the parser is first processed by these rules. This happens before the expression is evaluated.

For example, you can create a rule to automatically convert x^y into pow(x,y), effectively adding a new operator to the language without using DefineOperator.


💡 Common Use Cases

  • Creating syntactic sugar: Avg(1,2,3) -> (1+2+3)/3
  • Transpiling operators: a ? b : c -> iif(a, b, c)
  • Adding domain-specific keywords: CalculateYield(rate, time) -> rate * (1 + time)^2
  • Enforcing coding standards: Rewriting deprecated function names to their modern equivalents.

Comparative Analysis

ExpressionTransformer vs. Alias

FeatureExpressionTransformerAlias
MechanismTextual transformation (slower)Internal symbol table pointer (faster)
FlexibilityCan change structure, add/remove argumentsSimple 1-to-1 name replacement only
Use CaseUse for changing syntax or structure.Use for creating simple synonyms (Log -> Ln).

Choose Alias for simple renaming; it's significantly more performant as it avoids the entire transformation step.

ExpressionTransformer vs. NewTransformer

  • ExpressionTransformer(): Modifies the built-in parsing pipeline. Rules defined here affect all subsequent calls to Eval, Parse, etc., within that uCalc instance.
  • NewTransformer(): Creates a standalone, independent Transformer object. It does not affect the built-in parser and is used for general-purpose text transformation tasks.

ExpressionTransformer vs. Standard Regex

A Transformer is superior to regular expressions for language constructs because it operates on tokens, not just characters. It inherently understands concepts like nested parentheses, quoted strings, and numbers, which are notoriously difficult to handle correctly with regex.


⚠️ Performance Considerations

A Transformer object is not created for a uCalc instance until ExpressionTransformer() is called for the first time. Once created, it introduces a small overhead to every parse operation, even if no rules are defined. For performance-critical applications where transformations are not needed, avoid calling this method.

For more targeted, token-level transformations (like defining hex 0xFF notation or string interpolation), consider using TokenTransformer, which is only triggered when a specific token type is matched.


The returned Transformer object should not be released manually. It is owned by the parent uCalc instance.

Examples

Demonstrates using `RewindOnChange(true)` to perform recursive-style transformations, such as creating a variadic `AddUp` function.
				
					using uCalcSoftware;

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

// Base case: a single argument
t.FromTo("AddUp({x})", "{x}");

// Recursive case: multiple arguments
// RewindOnChange(true) causes the transformer to re-scan the string after a replacement.
// This allows AddUp(1,2,3) -> (1 + AddUp(2,3)) -> (1 + (2 + AddUp(3))) -> (1 + (2 + 3))
t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))").RewindOnChange = true;

Console.WriteLine("Input: AddUp(1, 2, 3, 4)");
Console.WriteLine($"Result: {uc.Eval("AddUp(1, 2, 3, 4)")}");
				
			
Input: AddUp(1, 2, 3, 4)
Result: 10
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

   // Base case: a single argument
   t.FromTo("AddUp({x})", "{x}");

   // Recursive case: multiple arguments
   // RewindOnChange(true) causes the transformer to re-scan the string after a replacement.
   // This allows AddUp(1,2,3) -> (1 + AddUp(2,3)) -> (1 + (2 + AddUp(3))) -> (1 + (2 + 3))
   t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))").RewindOnChange(true);

   cout << "Input: AddUp(1, 2, 3, 4)" << endl;
   cout << "Result: " << uc.Eval("AddUp(1, 2, 3, 4)") << endl;
}
				
			
Input: AddUp(1, 2, 3, 4)
Result: 10
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.ExpressionTransformer
      
      '// Base case: a single argument
      t.FromTo("AddUp({x})", "{x}")
      
      '// Recursive case: multiple arguments
      '// RewindOnChange(true) causes the transformer to re-scan the string after a replacement.
      '// This allows AddUp(1,2,3) -> (1 + AddUp(2,3)) -> (1 + (2 + AddUp(3))) -> (1 + (2 + 3))
      t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))").RewindOnChange = true
      
      Console.WriteLine("Input: AddUp(1, 2, 3, 4)")
      Console.WriteLine($"Result: {uc.Eval("AddUp(1, 2, 3, 4)")}")
   End Sub
End Module
				
			
Input: AddUp(1, 2, 3, 4)
Result: 10
Internal Test: Verifies that multi-pass transformations work correctly when `RewindOnChange` is enabled for the entire rule set.
				
					using uCalcSoftware;

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

// Enable RewindOnChange for all subsequently added rules
t.DefaultRuleSet.RewindOnChange = true;

// Define a chain of simple transformations
t.FromTo("A", "B");
t.FromTo("B", "C");
t.FromTo("C", "D");

// The transformer should apply all rules in sequence: A -> B -> C -> D
var result = t.Transform("A").Text;
Console.WriteLine($"Transform('A') -> {result}");
Console.WriteLine($"Is correct: {result == "D"}");
				
			
Transform('A') -> D
Is correct: True
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

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

   // Enable RewindOnChange for all subsequently added rules
   t.DefaultRuleSet().RewindOnChange(true);

   // Define a chain of simple transformations
   t.FromTo("A", "B");
   t.FromTo("B", "C");
   t.FromTo("C", "D");

   // The transformer should apply all rules in sequence: A -> B -> C -> D
   auto result = t.Transform("A").Text();
   cout << "Transform('A') -> " << result << endl;
   cout << "Is correct: " << tf(result == "D") << endl;
}
				
			
Transform('A') -> D
Is correct: True
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.ExpressionTransformer
      
      '// Enable RewindOnChange for all subsequently added rules
      t.DefaultRuleSet.RewindOnChange = true
      
      '// Define a chain of simple transformations
      t.FromTo("A", "B")
      t.FromTo("B", "C")
      t.FromTo("C", "D")
      
      '// The transformer should apply all rules in sequence: A -> B -> C -> D
      Dim result = t.Transform("A").Text
      Console.WriteLine($"Transform('A') -> {result}")
      Console.WriteLine($"Is correct: {result = "D"}")
   End Sub
End Module
				
			
Transform('A') -> D
Is correct: True
Using ExpressionTransformer to transform expressions before they are parsed
				
					using uCalcSoftware;

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

var p1 = ExprT.FromTo("AddUp({x})", "{x}"); // RewindOnChange False by default
var p2 = ExprT.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))").SetRewindOnChange(true);

Console.WriteLine($"p1 RewindOnChange: {p1.RewindOnChange}");
Console.WriteLine($"p2 RewindOnChange: {p2.RewindOnChange}");

Console.WriteLine("");

Console.WriteLine($"Input: AddUp(1,2,3,4)");
Console.WriteLine($"Transform: {ExprT.Transform("AddUp(1,2,3,4)")}");
Console.WriteLine($"Eval: {uc.Eval("AddUp(1,2,3,4)")}");
				
			
p1 RewindOnChange: False
p2 RewindOnChange: True

Input: AddUp(1,2,3,4)
Transform: (1 + (2 + (3 + 4)))
Eval: 10
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

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

   auto p1 = ExprT.FromTo("AddUp({x})", "{x}"); // RewindOnChange False by default
   auto p2 = ExprT.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))").SetRewindOnChange(true);

   cout << "p1 RewindOnChange: " << tf(p1.RewindOnChange()) << endl;
   cout << "p2 RewindOnChange: " << tf(p2.RewindOnChange()) << endl;

   cout << "" << endl;

   cout << "Input: " << "AddUp(1,2,3,4)" << endl;
   cout << "Transform: " << ExprT.Transform("AddUp(1,2,3,4)") << endl;
   cout << "Eval: " << uc.Eval("AddUp(1,2,3,4)") << endl;
}
				
			
p1 RewindOnChange: False
p2 RewindOnChange: True

Input: AddUp(1,2,3,4)
Transform: (1 + (2 + (3 + 4)))
Eval: 10
				
					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()
      
      Dim p1 = ExprT.FromTo("AddUp({x})", "{x}") '// RewindOnChange False by default
      Dim p2 = ExprT.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))").SetRewindOnChange(true)
      
      Console.WriteLine($"p1 RewindOnChange: {p1.RewindOnChange}")
      Console.WriteLine($"p2 RewindOnChange: {p2.RewindOnChange}")
      
      Console.WriteLine("")
      
      Console.WriteLine($"Input: AddUp(1,2,3,4)")
      Console.WriteLine($"Transform: {ExprT.Transform("AddUp(1,2,3,4)")}")
      Console.WriteLine($"Eval: {uc.Eval("AddUp(1,2,3,4)")}")
   End Sub
End Module
				
			
p1 RewindOnChange: False
p2 RewindOnChange: True

Input: AddUp(1,2,3,4)
Transform: (1 + (2 + (3 + 4)))
Eval: 10
RewindOnChange
				
					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