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.
Multi-Pattern Search
Product:Â
Class:Â
Simultaneously evaluating multiple distinct search patterns within a single input stream
Remarks
Standard string searching typically looks for one specific sequence of characters at a time. uCalc's Concurrent Patterns allow you to define multiple distinct patterns and search for all of them simultaneously in a single pass through the text.
Precedence & Order Rules:
- Text Position Priority: Matches are returned in the order they appear in the source string.
- Definition Priority (LIFO): If multiple patterns match starting at the same position (e.g., overlapping anchors), the most recently defined pattern takes precedence.
- Fallback Mechanism: If the highest-priority pattern fails to match the subsequent tokens, uCalc automatically backtracks and attempts the next most recently defined pattern that shares the same start anchor.
This architecture makes Concurrent Patterns ideal for tokenizers, lexers, or keyword highlighters where different definitions (like keywords vs. identifiers) might compete for the same text.
Comparative Analysis: Why uCalc?
- vs. Regex:
- Parallelism: To search for multiple distinct Regex patterns simultaneously (e.g., a date OR an email OR a specific keyword), you typically have to join them with
|into a massive, hard-to-read "super-pattern" or run multiple passes. uCalc lets you add them as separate, clean lines of code that run in one efficient pass. - Prioritization: Managing precedence in a giant Regex alternation
(PatternA|PatternB)relies strictly on left-to-right ordering and can be tricky to adjust dynamically. uCalc handles precedence via definition order, allowing runtime re-prioritization.
- Parallelism: To search for multiple distinct Regex patterns simultaneously (e.g., a date OR an email OR a specific keyword), you typically have to join them with
- vs. Native Code (String.IndexOf):
- Single Pass: Native searches like
IndexOfgenerally find one string. Finding multiple different strings requires a loop and complex index management to ensure you don't count the same text twice or process overlaps incorrectly. uCalc handles the cursor advancement automatically.
- Single Pass: Native searches like
Examples
Searching for two different words in parallel.
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
// Define concurrent patterns
t.FromTo("Mango", "[Fruit]");
t.FromTo("Car", "[Vehicle]");
Console.WriteLine(t.Transform("I have a Mango and a Car."));
I have a [Fruit] and a [Vehicle]. using uCalcSoftware; var uc = new uCalc(); var t = uc.NewTransformer(); // Define concurrent patterns t.FromTo("Mango", "[Fruit]"); t.FromTo("Car", "[Vehicle]"); Console.WriteLine(t.Transform("I have a Mango and a Car."));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
// Define concurrent patterns
t.FromTo("Mango", "[Fruit]");
t.FromTo("Car", "[Vehicle]");
cout << t.Transform("I have a Mango and a Car.") << endl;
}
I have a [Fruit] and a [Vehicle]. #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.NewTransformer(); // Define concurrent patterns t.FromTo("Mango", "[Fruit]"); t.FromTo("Car", "[Vehicle]"); cout << t.Transform("I have a Mango and a Car.") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
'// Define concurrent patterns
t.FromTo("Mango", "[Fruit]")
t.FromTo("Car", "[Vehicle]")
Console.WriteLine(t.Transform("I have a Mango and a Car."))
End Sub
End Module
I have a [Fruit] and a [Vehicle]. Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.NewTransformer() '// Define concurrent patterns t.FromTo("Mango", "[Fruit]") t.FromTo("Car", "[Vehicle]") Console.WriteLine(t.Transform("I have a Mango and a Car.")) End Sub End Module
A simple Lexer/Tokenizer that categorizes content into numbers, operators, or keywords.
using uCalcSoftware;
var uc = new uCalc();
// Note how the definition order matters if patterns overlap (though here they are distinct).
var t = uc.NewTransformer();
// Define patterns for a simple math language
t.FromTo("{d: {@Number}}", "[NUM:{d}]");
t.FromTo("{op: + | - | * | / }", "[OP:{op}]");
t.FromTo("print", "[CMD:PRINT]"); // Specific keyword
var code = "print 10 + 20";
Console.WriteLine(t.Transform(code));
[CMD:PRINT] [NUM:10] [OP:+] [NUM:20] using uCalcSoftware; var uc = new uCalc(); // Note how the definition order matters if patterns overlap (though here they are distinct). var t = uc.NewTransformer(); // Define patterns for a simple math language t.FromTo("{d: {@Number}}", "[NUM:{d}]"); t.FromTo("{op: + | - | * | / }", "[OP:{op}]"); t.FromTo("print", "[CMD:PRINT]"); // Specific keyword var code = "print 10 + 20"; Console.WriteLine(t.Transform(code));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// Note how the definition order matters if patterns overlap (though here they are distinct).
auto t = uc.NewTransformer();
// Define patterns for a simple math language
t.FromTo("{d: {@Number}}", "[NUM:{d}]");
t.FromTo("{op: + | - | * | / }", "[OP:{op}]");
t.FromTo("print", "[CMD:PRINT]"); // Specific keyword
auto code = "print 10 + 20";
cout << t.Transform(code) << endl;
}
[CMD:PRINT] [NUM:10] [OP:+] [NUM:20] #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // Note how the definition order matters if patterns overlap (though here they are distinct). auto t = uc.NewTransformer(); // Define patterns for a simple math language t.FromTo("{d: {@Number}}", "[NUM:{d}]"); t.FromTo("{op: + | - | * | / }", "[OP:{op}]"); t.FromTo("print", "[CMD:PRINT]"); // Specific keyword auto code = "print 10 + 20"; cout << t.Transform(code) << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// Note how the definition order matters if patterns overlap (though here they are distinct).
Dim t = uc.NewTransformer()
'// Define patterns for a simple math language
t.FromTo("{d: {@Number}}", "[NUM:{d}]")
t.FromTo("{op: + | - | * | / }", "[OP:{op}]")
t.FromTo("print", "[CMD:PRINT]") '// Specific keyword
Dim code = "print 10 + 20"
Console.WriteLine(t.Transform(code))
End Sub
End Module
[CMD:PRINT] [NUM:10] [OP:+] [NUM:20] Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// Note how the definition order matters if patterns overlap (though here they are distinct). Dim t = uc.NewTransformer() '// Define patterns for a simple math language t.FromTo("{d: {@Number}}", "[NUM:{d}]") t.FromTo("{op: + | - | * | / }", "[OP:{op}]") t.FromTo("print", "[CMD:PRINT]") '// Specific keyword Dim code = "print 10 + 20" Console.WriteLine(t.Transform(code)) End Sub End Module
Testing the "Last In, First Out" precedence rule with overlapping anchors.
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
// Priority Test: All start with "An"
// 1. Defined first (lowest priority for same start)
t.FromTo("An {item}", "Match1: {item}");
// 2. Defined second
t.FromTo("An {item}.", "Match2: {item}");
// 3. Defined last (Highest priority for same start)
t.FromTo("An orange.", "Match3: orange");
// Input text
var txt = "An orange. An apple. An elephant.";
// "An orange." matches Rule 3 (Specific, defined last)
// "An apple." fails Rule 3, matches Rule 2 (Ending in dot)
// If input is "An elephant" (no dot), it falls back to Rule 1.
Console.WriteLine(t.Transform("An orange.")); // Match3: Orange
Console.WriteLine(t.Transform("An apple.")); // Match2: apple
Console.WriteLine(t.Transform("An elephant")); // Match1: elephant
Match3: orange
Match2: apple
Match1: elephant using uCalcSoftware; var uc = new uCalc(); var t = uc.NewTransformer(); // Priority Test: All start with "An" // 1. Defined first (lowest priority for same start) t.FromTo("An {item}", "Match1: {item}"); // 2. Defined second t.FromTo("An {item}.", "Match2: {item}"); // 3. Defined last (Highest priority for same start) t.FromTo("An orange.", "Match3: orange"); // Input text var txt = "An orange. An apple. An elephant."; // "An orange." matches Rule 3 (Specific, defined last) // "An apple." fails Rule 3, matches Rule 2 (Ending in dot) // If input is "An elephant" (no dot), it falls back to Rule 1. Console.WriteLine(t.Transform("An orange.")); // Match3: Orange Console.WriteLine(t.Transform("An apple.")); // Match2: apple Console.WriteLine(t.Transform("An elephant")); // Match1: elephant
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
// Priority Test: All start with "An"
// 1. Defined first (lowest priority for same start)
t.FromTo("An {item}", "Match1: {item}");
// 2. Defined second
t.FromTo("An {item}.", "Match2: {item}");
// 3. Defined last (Highest priority for same start)
t.FromTo("An orange.", "Match3: orange");
// Input text
auto txt = "An orange. An apple. An elephant.";
// "An orange." matches Rule 3 (Specific, defined last)
// "An apple." fails Rule 3, matches Rule 2 (Ending in dot)
// If input is "An elephant" (no dot), it falls back to Rule 1.
cout << t.Transform("An orange.") << endl; // Match3: Orange
cout << t.Transform("An apple.") << endl; // Match2: apple
cout << t.Transform("An elephant") << endl; // Match1: elephant
}
Match3: orange
Match2: apple
Match1: elephant #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.NewTransformer(); // Priority Test: All start with "An" // 1. Defined first (lowest priority for same start) t.FromTo("An {item}", "Match1: {item}"); // 2. Defined second t.FromTo("An {item}.", "Match2: {item}"); // 3. Defined last (Highest priority for same start) t.FromTo("An orange.", "Match3: orange"); // Input text auto txt = "An orange. An apple. An elephant."; // "An orange." matches Rule 3 (Specific, defined last) // "An apple." fails Rule 3, matches Rule 2 (Ending in dot) // If input is "An elephant" (no dot), it falls back to Rule 1. cout << t.Transform("An orange.") << endl; // Match3: Orange cout << t.Transform("An apple.") << endl; // Match2: apple cout << t.Transform("An elephant") << endl; // Match1: elephant }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
'// Priority Test: All start with "An"
'// 1. Defined first (lowest priority for same start)
t.FromTo("An {item}", "Match1: {item}")
'// 2. Defined second
t.FromTo("An {item}.", "Match2: {item}")
'// 3. Defined last (Highest priority for same start)
t.FromTo("An orange.", "Match3: orange")
'// Input text
Dim txt = "An orange. An apple. An elephant."
'// "An orange." matches Rule 3 (Specific, defined last)
'// "An apple." fails Rule 3, matches Rule 2 (Ending in dot)
'// If input is "An elephant" (no dot), it falls back to Rule 1.
Console.WriteLine(t.Transform("An orange.")) '// Match3: Orange
Console.WriteLine(t.Transform("An apple.")) '// Match2: apple
Console.WriteLine(t.Transform("An elephant")) '// Match1: elephant
End Sub
End Module
Match3: orange
Match2: apple
Match1: elephant Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.NewTransformer() '// Priority Test: All start with "An" '// 1. Defined first (lowest priority for same start) t.FromTo("An {item}", "Match1: {item}") '// 2. Defined second t.FromTo("An {item}.", "Match2: {item}") '// 3. Defined last (Highest priority for same start) t.FromTo("An orange.", "Match3: orange") '// Input text Dim txt = "An orange. An apple. An elephant." '// "An orange." matches Rule 3 (Specific, defined last) '// "An apple." fails Rule 3, matches Rule 2 (Ending in dot) '// If input is "An elephant" (no dot), it falls back to Rule 1. Console.WriteLine(t.Transform("An orange.")) '// Match3: Orange Console.WriteLine(t.Transform("An apple.")) '// Match2: apple Console.WriteLine(t.Transform("An elephant")) '// Match1: elephant End Sub End Module