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.

Tag = [int]

Property

Product: 

Transformer Library

Class: 

Rule

Gets or sets a user-defined integer value, allowing for fast, programmatic identification and categorization of rules at runtime.

Remarks

🏷️ Tagging Rules for Programmatic Identification

The Tag property allows you to associate a custom integer identifier with any Rule. This is a powerful mechanism for categorizing rules and identifying which pattern generated a specific Match at runtime, without relying on slower string comparisons.

⚙️ Getter and Setter Behavior

This property functions as both a getter and a setter, following the standard property syntax:

  • Getter: var myTag = myRule.Tag;Retrieves the integer tag associated with the rule. If no tag has been set, it defaults to 0.

  • Setter: myRule.Tag = 123;Assigns an integer tag to the rule. The setter SetTag() function supports a fluent interface, returning the Rule object itself to allow for method chaining.

🎯 Primary Use Cases

Tag is the preferred method for programmatically identifying rules because comparing integers is significantly faster than comparing strings from Name() or Description().

  • Syntax Highlighting: In a code editor, you can create rules for keywords, strings, and comments, each with a unique tag (e.g., 1 for keyword, 2 for string). When processing matches, you can check the Match.Rule().Tag() to determine which color or style to apply.

  • Building an Abstract Syntax Tree (AST): When building a custom parser, you can use tags to represent token types or node types in your grammar (e.g., TAG_IDENTIFIER, TAG_OPERATOR).

  • State Machines: In a multi-stage transformation, tags can represent different states, allowing you to easily identify which rule corresponds to which state transition.

💡 Why uCalc? (Comparative Analysis)

In a standard Regex-based system, there is no built-in way to attach metadata like a numeric tag to a pattern. A developer would need to manage this association externally, which is cumbersome and less efficient.

Without uCalc:

// Manual, external mappingvar ruleMappings = new Dictionary<Regex, int>{    { new Regex(@"\b(if|else|for)\b"), 1 }, // Tag 1 for keywords    { new Regex(@"""[^\"]*""""), 2 }        // Tag 2 for strings};// ... must then manually find which Regex produced a match ...

With uCalc:

// Integrated, declarative approachvar keywordRule = t.Pattern("{if|else|for}").SetTag(1);var stringRule = t.Pattern("{@String}").SetTag(2);// ... later, simply check match.Rule().Tag() ...

uCalc's integrated Tag property provides a cleaner, more declarative, and higher-performance solution by keeping the identifying metadata tightly coupled with the rule itself.

Examples

A succinct example demonstrating how to set and get tags for different rules.
				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
var ruleA = t.Pattern("A").SetTag(10);
var ruleB = t.Pattern("B").SetTag(20);

Console.WriteLine($"Tag for Rule A: {ruleA.Tag}");
Console.WriteLine($"Tag for Rule B: {ruleB.Tag}");
				
			
Tag for Rule A: 10
Tag for Rule B: 20
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   auto ruleA = t.Pattern("A").SetTag(10);
   auto ruleB = t.Pattern("B").SetTag(20);

   cout << "Tag for Rule A: " << ruleA.Tag() << endl;
   cout << "Tag for Rule B: " << ruleB.Tag() << endl;
}
				
			
Tag for Rule A: 10
Tag for Rule B: 20
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      Dim ruleA = t.Pattern("A").SetTag(10)
      Dim ruleB = t.Pattern("B").SetTag(20)
      
      Console.WriteLine($"Tag for Rule A: {ruleA.Tag}")
      Console.WriteLine($"Tag for Rule B: {ruleB.Tag}")
   End Sub
End Module
				
			
Tag for Rule A: 10
Tag for Rule B: 20
A practical example using tags to build a simple syntax highlighter that categorizes matches.
				
					using uCalcSoftware;

var uc = new uCalc();
// Practical: Basic Syntax Highlighter
var t = new uCalc.Transformer();

// Define categories with integer tags
var TAG_KEYWORD = 1;
var TAG_STRING = 2;
var TAG_COMMENT = 3;

// Define rules and tag them
t.Pattern("{ if | else | for | while }").SetTag(TAG_KEYWORD);
t.Pattern("{@String}").SetTag(TAG_STRING);
t.Pattern("// {text}").SetTag(TAG_COMMENT);

t.Text = """
for (i=0; i<10; i++) { s = "hello"; // comment }
""";
t.Find();

foreach(var match in t.Matches) {
   var tag = match.Rule.Tag;
   if (tag == TAG_KEYWORD) {
      Console.WriteLine($"TAG_KEYWORD: {match.Text}");
   } else if (tag == TAG_STRING) {
      Console.WriteLine($"TAG_STRING: {match.Text}");
   } else if (tag == TAG_COMMENT) {
      Console.WriteLine($"TAG_COMMENT: {match.Text}");
   }
}
				
			
TAG_KEYWORD: for
TAG_STRING: "hello"
TAG_COMMENT: // comment 
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Practical: Basic Syntax Highlighter
   uCalc::Transformer t;

   // Define categories with integer tags
   auto TAG_KEYWORD = 1;
   auto TAG_STRING = 2;
   auto TAG_COMMENT = 3;

   // Define rules and tag them
   t.Pattern("{ if | else | for | while }").SetTag(TAG_KEYWORD);
   t.Pattern("{@String}").SetTag(TAG_STRING);
   t.Pattern("// {text}").SetTag(TAG_COMMENT);

   t.Text(R"(for (i=0; i<10; i++) { s = "hello"; // comment })");
   t.Find();

   for(auto match : t.Matches()) {
      auto tag = match.Rule().Tag();
      if (tag == TAG_KEYWORD) {
         cout << "TAG_KEYWORD: " << match.Text() << endl;
      } else if (tag == TAG_STRING) {
         cout << "TAG_STRING: " << match.Text() << endl;
      } else if (tag == TAG_COMMENT) {
         cout << "TAG_COMMENT: " << match.Text() << endl;
      }
   }
}
				
			
TAG_KEYWORD: for
TAG_STRING: "hello"
TAG_COMMENT: // comment 
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Practical: Basic Syntax Highlighter
      Dim t As New uCalc.Transformer()
      
      '// Define categories with integer tags
      Dim TAG_KEYWORD = 1
      Dim TAG_STRING = 2
      Dim TAG_COMMENT = 3
      
      '// Define rules and tag them
      t.Pattern("{ if | else | for | while }").SetTag(TAG_KEYWORD)
      t.Pattern("{@String}").SetTag(TAG_STRING)
      t.Pattern("// {text}").SetTag(TAG_COMMENT)
      
      t.Text = "for (i=0; i<10; i++) { s = ""hello""; // comment }"
      t.Find()
      
      For Each match In t.Matches
         Dim tag = match.Rule.Tag
         If tag = TAG_KEYWORD Then
            Console.WriteLine($"TAG_KEYWORD: {match.Text}")
            ElseIf tag = TAG_STRING Then
            Console.WriteLine($"TAG_STRING: {match.Text}")
            ElseIf tag = TAG_COMMENT Then
            Console.WriteLine($"TAG_COMMENT: {match.Text}")
         End If
      Next
   End Sub
End Module
				
			
TAG_KEYWORD: for
TAG_STRING: "hello"
TAG_COMMENT: // comment 
Internal Test: Verifies rule precedence and tag retrieval by traversing the overload chain with NextOverload.
				
					using uCalcSoftware;

var uc = new uCalc();
// Internal Test: Verifies precedence and tag retrieval via NextOverload
var t = new uCalc.Transformer();
t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3.";

// Rules defined last have higher precedence for the same anchor ("Testing")
var p1 = t.Pattern("Testing {etc}.").SetTag(111);
var p2 = t.Pattern("Testing {etc}!").SetTag(222);
var p3 = t.Pattern("Testing ({etc})").SetTag(333);

// Get the highest precedence rule via Pattern's return value
var highestPriorityRule = p3;
Console.WriteLine($"Highest priority rule tag: {highestPriorityRule.Tag}");

// Walk the overload chain
var midPriorityRule = highestPriorityRule.NextOverload();
Console.WriteLine($"Mid priority rule tag: {midPriorityRule.Tag}");

var lowPriorityRule = midPriorityRule.NextOverload();
Console.WriteLine($"Low priority rule tag: {lowPriorityRule.Tag}");

// The end of the chain should have a tag of 0 (default)
var endOfChain = lowPriorityRule.NextOverload();
Console.WriteLine($"End of chain tag: {endOfChain.Tag}");
				
			
Highest priority rule tag: 333
Mid priority rule tag: 222
Low priority rule tag: 111
End of chain tag: 0
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Internal Test: Verifies precedence and tag retrieval via NextOverload
   uCalc::Transformer t;
   t.Text("Testing (a b c) Testing x y z! Testing 1 2 3.");

   // Rules defined last have higher precedence for the same anchor ("Testing")
   auto p1 = t.Pattern("Testing {etc}.").SetTag(111);
   auto p2 = t.Pattern("Testing {etc}!").SetTag(222);
   auto p3 = t.Pattern("Testing ({etc})").SetTag(333);

   // Get the highest precedence rule via Pattern's return value
   auto highestPriorityRule = p3;
   cout << "Highest priority rule tag: " << highestPriorityRule.Tag() << endl;

   // Walk the overload chain
   auto midPriorityRule = highestPriorityRule.NextOverload();
   cout << "Mid priority rule tag: " << midPriorityRule.Tag() << endl;

   auto lowPriorityRule = midPriorityRule.NextOverload();
   cout << "Low priority rule tag: " << lowPriorityRule.Tag() << endl;

   // The end of the chain should have a tag of 0 (default)
   auto endOfChain = lowPriorityRule.NextOverload();
   cout << "End of chain tag: " << endOfChain.Tag() << endl;
}
				
			
Highest priority rule tag: 333
Mid priority rule tag: 222
Low priority rule tag: 111
End of chain tag: 0
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Internal Test: Verifies precedence and tag retrieval via NextOverload
      Dim t As New uCalc.Transformer()
      t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3."
      
      '// Rules defined last have higher precedence for the same anchor ("Testing")
      Dim p1 = t.Pattern("Testing {etc}.").SetTag(111)
      Dim p2 = t.Pattern("Testing {etc}!").SetTag(222)
      Dim p3 = t.Pattern("Testing ({etc})").SetTag(333)
      
      '// Get the highest precedence rule via Pattern's return value
      Dim highestPriorityRule = p3
      Console.WriteLine($"Highest priority rule tag: {highestPriorityRule.Tag}")
      
      '// Walk the overload chain
      Dim midPriorityRule = highestPriorityRule.NextOverload()
      Console.WriteLine($"Mid priority rule tag: {midPriorityRule.Tag}")
      
      Dim lowPriorityRule = midPriorityRule.NextOverload()
      Console.WriteLine($"Low priority rule tag: {lowPriorityRule.Tag}")
      
      '// The end of the chain should have a tag of 0 (default)
      Dim endOfChain = lowPriorityRule.NextOverload()
      Console.WriteLine($"End of chain tag: {endOfChain.Tag}")
   End Sub
End Module
				
			
Highest priority rule tag: 333
Mid priority rule tag: 222
Low priority rule tag: 111
End of chain tag: 0
Rule NextOverload and Tag
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3.";

var Pattern1 = t.Pattern("Testing {etc}.").SetTag(111);
var Pattern2 = t.Pattern("Testing {etc}!").SetTag(222);
var Pattern3 = t.Pattern("Testing ({etc})").SetTag(333);

t.Find();
Console.WriteLine("--- Matches ---");
Console.WriteLine(t.Matches.Text);
Console.WriteLine("--- Patterns ---");
Console.WriteLine(Pattern1.Pattern);
Console.WriteLine(Pattern2.Pattern);
Console.WriteLine(Pattern3.Pattern);
Console.WriteLine("---- Tags ----");
Console.WriteLine(Pattern1.Tag);
Console.WriteLine(Pattern2.Tag);
Console.WriteLine(Pattern3.Tag);
Console.WriteLine("-- Overload Tags --");
// Note that most recently defined patterns come first
Console.WriteLine(Pattern3.NextOverload().Tag);
Console.WriteLine(Pattern2.NextOverload().Tag);
Console.WriteLine(Pattern1.NextOverload().Tag);


				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   t.Text("Testing (a b c) Testing x y z! Testing 1 2 3.");

   auto Pattern1 = t.Pattern("Testing {etc}.").SetTag(111);
   auto Pattern2 = t.Pattern("Testing {etc}!").SetTag(222);
   auto Pattern3 = t.Pattern("Testing ({etc})").SetTag(333);

   t.Find();
   cout << "--- Matches ---" << endl;
   cout << t.Matches().Text() << endl;
   cout << "--- Patterns ---" << endl;
   cout << Pattern1.Pattern() << endl;
   cout << Pattern2.Pattern() << endl;
   cout << Pattern3.Pattern() << endl;
   cout << "---- Tags ----" << endl;
   cout << Pattern1.Tag() << endl;
   cout << Pattern2.Tag() << endl;
   cout << Pattern3.Tag() << endl;
   cout << "-- Overload Tags --" << endl;
   // Note that most recently defined patterns come first
   cout << Pattern3.NextOverload().Tag() << endl;
   cout << Pattern2.NextOverload().Tag() << endl;
   cout << Pattern1.NextOverload().Tag() << endl;


}
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      t.Text = "Testing (a b c) Testing x y z! Testing 1 2 3."
      
      Dim Pattern1 = t.Pattern("Testing {etc}.").SetTag(111)
      Dim Pattern2 = t.Pattern("Testing {etc}!").SetTag(222)
      Dim Pattern3 = t.Pattern("Testing ({etc})").SetTag(333)
      
      t.Find()
      Console.WriteLine("--- Matches ---")
      Console.WriteLine(t.Matches.Text)
      Console.WriteLine("--- Patterns ---")
      Console.WriteLine(Pattern1.Pattern)
      Console.WriteLine(Pattern2.Pattern)
      Console.WriteLine(Pattern3.Pattern)
      Console.WriteLine("---- Tags ----")
      Console.WriteLine(Pattern1.Tag)
      Console.WriteLine(Pattern2.Tag)
      Console.WriteLine(Pattern3.Tag)
      Console.WriteLine("-- Overload Tags --")
      '// Note that most recently defined patterns come first
      Console.WriteLine(Pattern3.NextOverload().Tag)
      Console.WriteLine(Pattern2.NextOverload().Tag)
      Console.WriteLine(Pattern1.NextOverload().Tag)
      
      
   End Sub
End Module
				
			
--- Matches ---
Testing (a b c)
Testing x y z!
Testing 1 2 3.
--- Patterns ---
Testing {etc}.
Testing {etc}!
Testing ({etc})
---- Tags ----
111
222
333
-- Overload Tags --
222
111
0