uCalc API Version: 2.1.3-preview.2 Released: 6/16/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.
Introduction
Product:
Class:
An overview of the Rule object, the core component representing a compiled pattern and its behavioral properties in the Transformer.
Remarks
🎯 The Rule Object: A Compiled Pattern
The Rule class is the fundamental building block of the uCalc Transformer. It represents a single, compiled search pattern and its associated action, such as a replacement string or a callback. When you define a pattern with methods like FromTo() or Pattern(), the Transformer creates a Rule object internally.
By obtaining a handle to this Rule object, you gain powerful, granular control over its behavior at runtime.
⚙️ Core Concepts
Stateful, Configurable Objects: Unlike a simple Regex pattern (which is just a string), a
Ruleis a stateful object with a rich set of properties. You can programmatically control its behavior after it has been created, toggling features like case sensitivity, whitespace handling, or its active state.Precedence and Order (LIFO): When a Transformer has multiple rules, their precedence is determined by a Last-In, First-Out (LIFO) order. The most recently defined rule is checked first. This allows you to build a base of general rules and then add more specific, higher-precedence rules on top of them.
Hierarchical Parsing: Rules can be nested using the LocalTransformer property. This allows you to create parent-child relationships where a set of "child" rules only applies to the text captured by a "parent" rule, enabling sophisticated parsing of structured, nested data.
📖 Member List
| Member | Description |
|---|---|
Active | Gets or sets whether the rule is active and will be considered during pattern matching. |
BracketSensitive | Controls whether the rule respects balanced bracket pairs. |
CaseSensitive | Controls whether pattern matching for the rule is case-sensitive. |
Description | Gets or sets a user-defined text description for metadata and debugging. |
Focusable | Flags a rule's matches for inclusion/exclusion from filtered result sets. |
GlobalMaximum | Sets a global match limit; if exceeded, the entire transformation pass is invalidated. |
GlobalMinimum | Sets a global minimum match requirement; if not met, the entire pass is invalidated. |
HasLocalTransformer | Checks if the rule has a nested local transformer without creating one. |
IsChildRule | Determines if the rule belongs to a nested (local) transformer. |
LocalTransformer | Gets a nested Transformer scoped exclusively to the text matched by this rule. |
Matches | Retrieves the collection of matches found exclusively by this rule. |
Maximum | Sets a rule-specific match limit; if exceeded, only this rule's matches are invalidated. |
Minimum | Sets a rule-specific minimum match requirement; if not met, only this rule's matches are invalidated. |
Name | Gets the programmatic name of the rule, derived from its pattern. |
NextOverload | Retrieves the next rule in a sequence of rules that share the same starting anchor. |
ParentTransformer | Retrieves the parent Transformer that owns this rule. |
Pattern | Gets the original pattern string that defines the rule's matching criteria. |
Precedence | Gets or sets the rule's precedence level. |
QuoteSensitive | Controls whether the rule respects quoted strings as atomic units. |
Release | Permanently removes the rule from the transformer. |
Replacement | Gets or sets the replacement string for the rule. |
RewindOnChange | Controls whether the transformer re-scans text after a replacement, enabling recursive transformations. |
StartAfter | Sets the number of matches to skip before including results. |
StatementSensitive | Controls whether the rule respects statement separators (like semicolons or newlines). |
StopAfter | Sets the maximum number of matches this rule will find before stopping. |
Tag | Gets or sets a user-defined integer for fast, programmatic identification. |
uCalc | Retrieves the root uCalc instance that provides the execution context. |
Verbatim | Controls whether variable captures are treated as verbatim blocks, preventing nested matching. |
WhitespaceSensitive | Controls whether whitespace is treated as a significant token. |
⚖️ Comparative Analysis
- vs. Regular Expressions:
- Stateful vs. Static: A Regex pattern is typically a static string, often with global flags (
/i,/g). To change its behavior, you must recompile it. A uCalcRuleis a dynamic object whose properties (CaseSensitive,Active, etc.) can be toggled at runtime without recompiling the pattern. - Context-Awareness: A
Ruleinherits the token-aware nature of the Transformer. It understands language constructs like quotes and brackets, a level of structural awareness that is difficult and fragile to achieve with pure regex.
- Stateful vs. Static: A Regex pattern is typically a static string, often with global flags (
Examples
A succinct example that finds all occurrences of a letter but skips the first one.
using uCalcSoftware;
var uc = new uCalc();
var t = new uCalc.Transformer();
t.Text = "a b c a d e a f g";
var ruleA = t.FromTo("a", "[MATCH]");
// Skip the first 'a' that is found
ruleA.StartAfter = 1;
Console.WriteLine(t.Transform());
a b c [MATCH] d e [MATCH] f g using uCalcSoftware; var uc = new uCalc(); var t = new uCalc.Transformer(); t.Text = "a b c a d e a f g"; var ruleA = t.FromTo("a", "[MATCH]"); // Skip the first 'a' that is found ruleA.StartAfter = 1; Console.WriteLine(t.Transform());
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
uCalc::Transformer t;
t.Text("a b c a d e a f g");
auto ruleA = t.FromTo("a", "[MATCH]");
// Skip the first 'a' that is found
ruleA.StartAfter(1);
cout << t.Transform() << endl;
}
a b c [MATCH] d e [MATCH] f g #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; uCalc::Transformer t; t.Text("a b c a d e a f g"); auto ruleA = t.FromTo("a", "[MATCH]"); // Skip the first 'a' that is found ruleA.StartAfter(1); cout << t.Transform() << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t As New uCalc.Transformer()
t.Text = "a b c a d e a f g"
Dim ruleA = t.FromTo("a", "[MATCH]")
'// Skip the first 'a' that is found
ruleA.StartAfter = 1
Console.WriteLine(t.Transform())
End Sub
End Module
a b c [MATCH] d e [MATCH] f g Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t As New uCalc.Transformer() t.Text = "a b c a d e a f g" Dim ruleA = t.FromTo("a", "[MATCH]") '// Skip the first 'a' that is found ruleA.StartAfter = 1 Console.WriteLine(t.Transform()) End Sub End Module
Applies `RewindOnChange` to a default rule set to enable complex, multi-rule transformations for a custom `Average` function.
using uCalcSoftware;
var uc = new uCalc();
var t = uc.ExpressionTransformer;
// Enable rewind for all subsequent rules in this transformer.
t.DefaultRuleSet.SetRewindOnChange(true);
// Define the recursive rules.
t.FromTo("AddUp({x})", "{x}");
t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))");
t.FromTo("ArgCount({x})", "1");
t.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))");
// The main rule that combines the others.
t.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})");
var expression = "Average(1, 2, 3, 4)";
Console.WriteLine($"Input: {expression}");
Console.WriteLine($"Transform: {t.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 using uCalcSoftware; var uc = new uCalc(); var t = uc.ExpressionTransformer; // Enable rewind for all subsequent rules in this transformer. t.DefaultRuleSet.SetRewindOnChange(true); // Define the recursive rules. t.FromTo("AddUp({x})", "{x}"); t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))"); t.FromTo("ArgCount({x})", "1"); t.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))"); // The main rule that combines the others. t.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})"); var expression = "Average(1, 2, 3, 4)"; Console.WriteLine($"Input: {expression}"); Console.WriteLine($"Transform: {t.Transform(expression)}"); Console.WriteLine($"Eval: {uc.Eval(expression)}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.ExpressionTransformer();
// Enable rewind for all subsequent rules in this transformer.
t.DefaultRuleSet().SetRewindOnChange(true);
// Define the recursive rules.
t.FromTo("AddUp({x})", "{x}");
t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))");
t.FromTo("ArgCount({x})", "1");
t.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))");
// The main rule that combines the others.
t.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})");
auto expression = "Average(1, 2, 3, 4)";
cout << "Input: " << expression << endl;
cout << "Transform: " << t.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 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.ExpressionTransformer(); // Enable rewind for all subsequent rules in this transformer. t.DefaultRuleSet().SetRewindOnChange(true); // Define the recursive rules. t.FromTo("AddUp({x})", "{x}"); t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))"); t.FromTo("ArgCount({x})", "1"); t.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))"); // The main rule that combines the others. t.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})"); auto expression = "Average(1, 2, 3, 4)"; cout << "Input: " << expression << endl; cout << "Transform: " << t.Transform(expression) << endl; cout << "Eval: " << uc.Eval(expression) << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.ExpressionTransformer
'// Enable rewind for all subsequent rules in this transformer.
t.DefaultRuleSet.SetRewindOnChange(true)
'// Define the recursive rules.
t.FromTo("AddUp({x})", "{x}")
t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))")
t.FromTo("ArgCount({x})", "1")
t.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))")
'// The main rule that combines the others.
t.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})")
Dim expression = "Average(1, 2, 3, 4)"
Console.WriteLine($"Input: {expression}")
Console.WriteLine($"Transform: {t.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 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.ExpressionTransformer '// Enable rewind for all subsequent rules in this transformer. t.DefaultRuleSet.SetRewindOnChange(true) '// Define the recursive rules. t.FromTo("AddUp({x})", "{x}") t.FromTo("AddUp({x}, {y})", "({x} + AddUp({y}))") t.FromTo("ArgCount({x})", "1") t.FromTo("ArgCount({x}, {y})", "(1 + ArgCount({y}))") '// The main rule that combines the others. t.FromTo("Average({x}, {y})", "AddUp({x}, {y}) / ArgCount({x}, {y})") Dim expression = "Average(1, 2, 3, 4)" Console.WriteLine($"Input: {expression}") Console.WriteLine($"Transform: {t.Transform(expression)}") Console.WriteLine($"Eval: {uc.Eval(expression)}") End Sub End Module