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.
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.
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 isReadable
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.
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.
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)); };
#include
#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.
#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; }; }
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.
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
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.
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
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));
#include
#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
#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; }
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
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
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.
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));
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));
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
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
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.
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
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);
#include
#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 block.
auto navRule = t.Pattern("{content}");
// 2. Get the local transformer for the nav block.
auto local_t = navRule.LocalTransformer();
// 3. This rule will only find `` tags inside the block.
local_t.Pattern("{text}");
auto html = R"(HomeAbout
)";
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;
}
#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; }
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 block.
Dim navRule = t.Pattern("{content}")
'// 2. Get the local transformer for the nav block.
Dim local_t = navRule.LocalTransformer
'// 3. This rule will only find `` tags inside the block.
local_t.Pattern("{text}")
Dim html = "HomeAbout
"
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
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
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.
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");
}
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));
#include
#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");
}
#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; }
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");
}
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
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.
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
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"));
#include
#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
#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; }
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
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
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.
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)
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));
#include
#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)
#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; }
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)
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
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.
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
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.
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.
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
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")}");
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
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