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.

Whitespace

Product: 

Class: 

Whitespace behavior

Remarks

In uCalc, whitespace (spaces and tabs) is ignored by default. This means A + B matches A+B or A + B.

Important Distinction: unlike many other languages, uCalc defines Newlines by default as Statement Separators, not generic whitespace.

  • Spaces/Tabs: Ignored/Skipped by default. You can change this behavior using the WhitespaceSensitive property or the $ variable directive.
  • Newlines: Treated as a "stop" or "separator" (like a semicolon ; in C#). To treat them as spaces, you must redefine the token type.

Key Concepts

ConceptBehaviorExample
Default (Insensitive)Spaces in the pattern match any amount of horizontal whitespace (including none).Key : Value matches Key:Value and Key : Value
Newline BehaviorNewlines separate statements. By default they are not consumed by standard space characters in a pattern.A B matches A B but not A \n B (unless configured).
{@Whitespace}Explicitly captures a block of whitespace into a variable.{@Whitespace} captures whitespace characters such as spaces and tabs.
WhitespaceSensitiveIf set to True, block of whitespace in your pattern matches exactly one token in the source.A B matches A B but fails on A B.

Why uCalc? (Comparative Analysis)

  • vs. Regular Expressions:
    • Readability: In Regex, handling variable spacing requires cluttering your pattern with \s*. uCalc handles the "flexibility" automatically.
    • Structure: uCalc distinguishes between "formatting" (spaces) and "structure" (newlines), making it easier to parse line-based data formats (like CSV or Config files) without accidental matches across lines.
    • Configurability: It's easy to reconfigure newlines to behave as whitespace with t.Tokens["_token_newline"].TypeOfToken = TokenType::Whitespace;, for dealing with XML or HTML.

Examples

Whitespace
				
					using uCalcSoftware;

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

t.FromTo("Hello World", "<{@Self}>");
Console.WriteLine(t.Transform("Hello World. HelloWorld. Hello     World. Hello, World."));
				
			
<Hello World>. HelloWorld. <Hello     World>. Hello, World.
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

   t.FromTo("Hello World", "<{@Self}>");
   cout << t.Transform("Hello World. HelloWorld. Hello     World. Hello, World.") << endl;
}
				
			
<Hello World>. HelloWorld. <Hello     World>. Hello, World.
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      
      t.FromTo("Hello World", "<{@Self}>")
      Console.WriteLine(t.Transform("Hello World. HelloWorld. Hello     World. Hello, World."))
   End Sub
End Module
				
			
<Hello World>. HelloWorld. <Hello     World>. Hello, World.
WhitespaceSensitive()
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
var Text = "This is a test.";
var p = t.FromTo("This {words:3}", "[{words}]");

Console.WriteLine($"Input: {Text}");
Console.WriteLine($"Pattern: {p.Pattern}");
Console.WriteLine("");

Console.WriteLine("3 captured tokens are in brackets");
Console.WriteLine("");

Console.WriteLine($"WhitespaceSensitive = {t.DefaultRuleSet.WhitespaceSensitive}");
Console.WriteLine(t.Transform(Text));
Console.WriteLine("");

t.DefaultRuleSet.WhitespaceSensitive = true;
Console.WriteLine($"WhitespaceSensitive = {t.DefaultRuleSet.WhitespaceSensitive}");
Console.WriteLine(t.Transform(Text));

				
			
Input: This is a test.
Pattern: This {words:3}

3 captured tokens are in brackets

WhitespaceSensitive = False
[is a test].

WhitespaceSensitive = True
[ is ]a test.
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   auto Text = "This is a test.";
   auto p = t.FromTo("This {words:3}", "[{words}]");

   cout << "Input: " << Text << endl;
   cout << "Pattern: " << p.Pattern() << endl;
   cout << "" << endl;

   cout << "3 captured tokens are in brackets" << endl;
   cout << "" << endl;

   cout << "WhitespaceSensitive = " << tf(t.DefaultRuleSet().WhitespaceSensitive()) << endl;
   cout << t.Transform(Text) << endl;
   cout << "" << endl;

   t.DefaultRuleSet().WhitespaceSensitive(true);
   cout << "WhitespaceSensitive = " << tf(t.DefaultRuleSet().WhitespaceSensitive()) << endl;
   cout << t.Transform(Text) << endl;

}
				
			
Input: This is a test.
Pattern: This {words:3}

3 captured tokens are in brackets

WhitespaceSensitive = False
[is a test].

WhitespaceSensitive = True
[ is ]a test.
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      Dim Text = "This is a test."
      Dim p = t.FromTo("This {words:3}", "[{words}]")
      
      Console.WriteLine($"Input: {Text}")
      Console.WriteLine($"Pattern: {p.Pattern}")
      Console.WriteLine("")
      
      Console.WriteLine("3 captured tokens are in brackets")
      Console.WriteLine("")
      
      Console.WriteLine($"WhitespaceSensitive = {t.DefaultRuleSet.WhitespaceSensitive}")
      Console.WriteLine(t.Transform(Text))
      Console.WriteLine("")
      
      t.DefaultRuleSet.WhitespaceSensitive = true
      Console.WriteLine($"WhitespaceSensitive = {t.DefaultRuleSet.WhitespaceSensitive}")
      Console.WriteLine(t.Transform(Text))
      
   End Sub
End Module
				
			
Input: This is a test.
Pattern: This {words:3}

3 captured tokens are in brackets

WhitespaceSensitive = False
[is a test].

WhitespaceSensitive = True
[ is ]a test.
Transformer: Matching by tokens vs match by character; also whitespace sensitivity
				
					using uCalcSoftware;

var uc = new uCalc();
// This examples shows the default match by
// token mode, as well as how to reconfigure
// it in order to do match by character
// along with a whitespace variation

var t = uc.NewTransformer();
var txt = "This is an island test, I said.";
t.FromTo("is", "<is>");

Console.WriteLine(t.Transform(txt));
Console.WriteLine("");

t.Tokens.Description = "Match by character";
t.Tokens.Add("."); // This overrides existing tokens
t.FromTo("is", "<is>");
Console.WriteLine(t.Tokens.Description);
Console.WriteLine(t.Transform(txt));
Console.WriteLine("");

// Note: whitespace sensitivity is off by default
// Whitespace token is re-introduced
// (after being overridden in the previous Token Add())
t.Tokens.Description = "By char + whitespace ignored";
t.Tokens.Add("[\\t\\v ]+", TokenType.Whitespace);
t.FromTo("is", "<{@Self}>");
Console.WriteLine(t.Tokens.Description);
Console.WriteLine(t.Transform(txt));
				
			
This <is> an island test, I said.

Match by character
Th<is> <is> an <is>land test, I said.

By char + whitespace ignored
Th<is> <is> an <is>land test, <I s>aid.
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // This examples shows the default match by
   // token mode, as well as how to reconfigure
   // it in order to do match by character
   // along with a whitespace variation

   auto t = uc.NewTransformer();
   auto txt = "This is an island test, I said.";
   t.FromTo("is", "<is>");

   cout << t.Transform(txt) << endl;
   cout << "" << endl;

   t.Tokens().Description("Match by character");
   t.Tokens().Add("."); // This overrides existing tokens
   t.FromTo("is", "<is>");
   cout << t.Tokens().Description() << endl;
   cout << t.Transform(txt) << endl;
   cout << "" << endl;

   // Note: whitespace sensitivity is off by default
   // Whitespace token is re-introduced
   // (after being overridden in the previous Token Add())
   t.Tokens().Description("By char + whitespace ignored");
   t.Tokens().Add("[\\t\\v ]+", TokenType::Whitespace);
   t.FromTo("is", "<{@Self}>");
   cout << t.Tokens().Description() << endl;
   cout << t.Transform(txt) << endl;
}
				
			
This <is> an island test, I said.

Match by character
Th<is> <is> an <is>land test, I said.

By char + whitespace ignored
Th<is> <is> an <is>land test, <I s>aid.
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// This examples shows the default match by
      '// token mode, as well as how to reconfigure
      '// it in order to do match by character
      '// along with a whitespace variation
      
      Dim t = uc.NewTransformer()
      Dim txt = "This is an island test, I said."
      t.FromTo("is", "<is>")
      
      Console.WriteLine(t.Transform(txt))
      Console.WriteLine("")
      
      t.Tokens.Description = "Match by character"
      t.Tokens.Add(".") '// This overrides existing tokens
      t.FromTo("is", "<is>")
      Console.WriteLine(t.Tokens.Description)
      Console.WriteLine(t.Transform(txt))
      Console.WriteLine("")
      
      '// Note: whitespace sensitivity is off by default
      '// Whitespace token is re-introduced
      '// (after being overridden in the previous Token Add())
      t.Tokens.Description = "By char + whitespace ignored"
      t.Tokens.Add("[\\t\\v ]+", TokenType.Whitespace)
      t.FromTo("is", "<{@Self}>")
      Console.WriteLine(t.Tokens.Description)
      Console.WriteLine(t.Transform(txt))
   End Sub
End Module
				
			
This <is> an island test, I said.

Match by character
Th<is> <is> an <is>land test, I said.

By char + whitespace ignored
Th<is> <is> an <is>land test, <I s>aid.
Change newline from statement separator to whitespace
				
					using uCalcSoftware;

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

t.Str("""

<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>

""");

t.Pattern("<div>{body}</div>");

Console.WriteLine("Newline as statement separator (default)");
Console.WriteLine("----------------------------------------");
Console.WriteLine(t.Find().Matches.Text);
Console.WriteLine("");

Console.WriteLine("Newline as whitespace");
Console.WriteLine("---------------------");
t.Tokens["_token_newline"].TypeOfToken = TokenType.Whitespace;
Console.WriteLine(t.Find().Matches.Text);
				
			
Newline as statement separator (default)
----------------------------------------
<div>a b c</div>
<div>1 2 3</div>

Newline as whitespace
---------------------
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

   t.Str(R"(
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
)");

   t.Pattern("<div>{body}</div>");

   cout << "Newline as statement separator (default)" << endl;
   cout << "----------------------------------------" << endl;
   cout << t.Find().Matches().Text() << endl;
   cout << "" << endl;

   cout << "Newline as whitespace" << endl;
   cout << "---------------------" << endl;
   t.Tokens()["_token_newline"].TypeOfToken(TokenType::Whitespace);
   cout << t.Find().Matches().Text() << endl;
}
				
			
Newline as statement separator (default)
----------------------------------------
<div>a b c</div>
<div>1 2 3</div>

Newline as whitespace
---------------------
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      
      t.Str("
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
")
      
      t.Pattern("<div>{body}</div>")
      
      Console.WriteLine("Newline as statement separator (default)")
      Console.WriteLine("----------------------------------------")
      Console.WriteLine(t.Find().Matches.Text)
      Console.WriteLine("")
      
      Console.WriteLine("Newline as whitespace")
      Console.WriteLine("---------------------")
      t.Tokens("_token_newline").TypeOfToken = TokenType.Whitespace
      Console.WriteLine(t.Find().Matches.Text)
   End Sub
End Module
				
			
Newline as statement separator (default)
----------------------------------------
<div>a b c</div>
<div>1 2 3</div>

Newline as whitespace
---------------------
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
Change newline from statement separator to whitespace using TypeOfToken
				
					using uCalcSoftware;

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

t.Str("""

<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>

""");

t.Pattern("<div>{body}</div>");
var NewLineToken = t.Tokens["_token_newline"];

Console.WriteLine("Newline as statement separator (default)");
Console.WriteLine("----------------------------------------");
Console.WriteLine(t.Find().Matches.Text);
Console.WriteLine("");

Console.WriteLine("Newline as whitespace");
Console.WriteLine("---------------------");
NewLineToken.TypeOfToken = TokenType.Whitespace;
Console.WriteLine(t.Find().Matches.Text);
				
			
Newline as statement separator (default)
----------------------------------------
<div>a b c</div>
<div>1 2 3</div>

Newline as whitespace
---------------------
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

   t.Str(R"(
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
)");

   t.Pattern("<div>{body}</div>");
   auto NewLineToken = t.Tokens()["_token_newline"];

   cout << "Newline as statement separator (default)" << endl;
   cout << "----------------------------------------" << endl;
   cout << t.Find().Matches().Text() << endl;
   cout << "" << endl;

   cout << "Newline as whitespace" << endl;
   cout << "---------------------" << endl;
   NewLineToken.TypeOfToken(TokenType::Whitespace);
   cout << t.Find().Matches().Text() << endl;
}
				
			
Newline as statement separator (default)
----------------------------------------
<div>a b c</div>
<div>1 2 3</div>

Newline as whitespace
---------------------
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      
      t.Str("
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
")
      
      t.Pattern("<div>{body}</div>")
      Dim NewLineToken = t.Tokens("_token_newline")
      
      Console.WriteLine("Newline as statement separator (default)")
      Console.WriteLine("----------------------------------------")
      Console.WriteLine(t.Find().Matches.Text)
      Console.WriteLine("")
      
      Console.WriteLine("Newline as whitespace")
      Console.WriteLine("---------------------")
      NewLineToken.TypeOfToken = TokenType.Whitespace
      Console.WriteLine(t.Find().Matches.Text)
   End Sub
End Module
				
			
Newline as statement separator (default)
----------------------------------------
<div>a b c</div>
<div>1 2 3</div>

Newline as whitespace
---------------------
<div>a b c</div>
<div>
x
y
z
</div>
<div>1 2 3</div>
Turn new line into whitespace with Tokens.Add
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.FromTo("<{tag}>{code}</{tag}>", "[{tag}]{code}[/{tag}]");
var MyStr = """
<div>Single line</div>
<div>Line 1
Line 2
Line 3
Line 4</div>
""";

Console.WriteLine("New line as statement separator (default)");
Console.WriteLine("");
Console.WriteLine(t.Transform(MyStr).Text);
Console.WriteLine("");

Console.WriteLine("New line as whitespace");
Console.WriteLine("");
t.Tokens.Add("[\\r\\n]+", TokenType.Whitespace);
Console.WriteLine(t.Transform(MyStr).Text);



				
			
New line as statement separator (default)

[div]Single line[/div]
<div>Line 1
Line 2
Line 3
Line 4</div>

New line as whitespace

[div]Single line[/div]
[div]Line 1
Line 2
Line 3
Line 4[/div]
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   t.FromTo("<{tag}>{code}</{tag}>", "[{tag}]{code}[/{tag}]");
   auto MyStr = R"(<div>Single line</div>
<div>Line 1
Line 2
Line 3
Line 4</div>)";

   cout << "New line as statement separator (default)" << endl;
   cout << "" << endl;
   cout << t.Transform(MyStr).Text() << endl;
   cout << "" << endl;

   cout << "New line as whitespace" << endl;
   cout << "" << endl;
   t.Tokens().Add("[\\r\\n]+", TokenType::Whitespace);
   cout << t.Transform(MyStr).Text() << endl;



}
				
			
New line as statement separator (default)

[div]Single line[/div]
<div>Line 1
Line 2
Line 3
Line 4</div>

New line as whitespace

[div]Single line[/div]
[div]Line 1
Line 2
Line 3
Line 4[/div]
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      t.FromTo("<{tag}>{code}</{tag}>", "[{tag}]{code}[/{tag}]")
      Dim MyStr = "<div>Single line</div>
<div>Line 1
Line 2
Line 3
Line 4</div>"
      
      Console.WriteLine("New line as statement separator (default)")
      Console.WriteLine("")
      Console.WriteLine(t.Transform(MyStr).Text)
      Console.WriteLine("")
      
      Console.WriteLine("New line as whitespace")
      Console.WriteLine("")
      t.Tokens.Add("[\r\n]+", TokenType.Whitespace)
      Console.WriteLine(t.Transform(MyStr).Text)
      
      
      
   End Sub
End Module
				
			
New line as statement separator (default)

[div]Single line[/div]
<div>Line 1
Line 2
Line 3
Line 4</div>

New line as whitespace

[div]Single line[/div]
[div]Line 1
Line 2
Line 3
Line 4[/div]
Using {@Whitespace} and {@Exec} to Count Indentation (for Python or YAML-like text)
				
					using uCalcSoftware;

var uc = new uCalc();
// Using {@Whitespace} to Count Indentation
// A common use case for parsing structured text (like Python or YAML)
// is capturing the exact whitespace at the start of a line.

uc.DefineVariable("IndentLen");

var t = uc.NewTransformer();
t.Text = "    Item 1"; // Indented by 4 spaces

// Capture the leading whitespace into 'w' and evaluate its length
t.FromTo("{@Whitespace:w} Item {id}", "<{@Self}>{@Exec: IndentLen = Length(w)}");
t.Transform();
// We can now analyze the captured whitespace
Console.WriteLine($"Indentation length: {uc.EvalStr("IndentLen")}");
				
			
Indentation length: 4
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Using {@Whitespace} to Count Indentation
   // A common use case for parsing structured text (like Python or YAML)
   // is capturing the exact whitespace at the start of a line.

   uc.DefineVariable("IndentLen");

   auto t = uc.NewTransformer();
   t.Text("    Item 1"); // Indented by 4 spaces

   // Capture the leading whitespace into 'w' and evaluate its length
   t.FromTo("{@Whitespace:w} Item {id}", "<{@Self}>{@Exec: IndentLen = Length(w)}");
   t.Transform();
   // We can now analyze the captured whitespace
   cout << "Indentation length: " << uc.EvalStr("IndentLen") << endl;
}
				
			
Indentation length: 4
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Using {@Whitespace} to Count Indentation
      '// A common use case for parsing structured text (like Python or YAML)
      '// is capturing the exact whitespace at the start of a line.
      
      uc.DefineVariable("IndentLen")
      
      Dim t = uc.NewTransformer()
      t.Text = "    Item 1" '// Indented by 4 spaces
      
      '// Capture the leading whitespace into 'w' and evaluate its length
      t.FromTo("{@Whitespace:w} Item {id}", "<{@Self}>{@Exec: IndentLen = Length(w)}")
      t.Transform()
      '// We can now analyze the captured whitespace
      Console.WriteLine($"Indentation length: {uc.EvalStr("IndentLen")}")
   End Sub
End Module
				
			
Indentation length: 4