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.
{@Newline}
Product:
Class:
Remarks
Shortcut: {@nl}
Description: A category matcher that identifies any token defined as a vertical line break (e.g., \n or \r\n).
The {@Newline} directive (shorthand {@nl}) is used in a uCalc::Transformer to target vertical structural boundaries. Unlike generic whitespace matchers in other languages, uCalc maintains a strict distinction between horizontal and vertical spacing to preserve document structure during complex transformations.
Vertical vs. Horizontal Space
In uCalc, newlines are treated as a distinct category of tokens. This prevents rules intended for horizontal cleanup from accidentally collapsing multiple lines into a single one.
{@Whitespace}: Targets spaces and tabs.{@Newline}: Targets line-ending characters.
The _newline Variable
The actual string character(s) used by the {@nl} directive is controlled by a special internal string variable named _newline.
- Default Behavior: By default,
_newlineis set to\r\n(CRLF) for versions compiled for Windows, and\n(LF) for all other platforms. - Reconfiguration: You can manually override the newline character used for output by redefining this variable in the evaluator. This is useful for cross-platform document normalization.
- Example:
uc.Eval("_newline = '\n'");sets the newline to Unix-style globally.
- Example:
Common Behaviors
- Statement Boundaries: In many programming languages, a newline signifies the end of a command.
{@nl}allows rules to be anchored specifically to the "End of Line" context. - Cleanup Logic: Consecutive newlines can be matched and reduced (e.g., matching three newlines and replacing with two) to normalize document formatting.
- The Inverse Operator (
!): Using{!nl}allows the engine to match any token that is not a line break, which is useful for processing content while ensuring the match does not spill over into the next line.
Short Alias
Because vertical alignment is a frequent requirement in transformation patterns, the shorter {@nl} alias is provided for cleaner, more readable rule definitions.
Examples
1. Succinct (Quick Start: Consolidating Space)
Replacing triple-newlines with a standard double-newline to normalize document spacing.
New(uCalc::Transformer, t)// Match three consecutive newline tokenst.FromTo("{@nl} {@nl} {@nl}", "{@nl}{@nl}")wl(t.Transform("Line 1\n\n\nLine 2"))[Expected Output]Line 1 Line 2
2. Practical (Real World: Line Counting)
Using {@@Exec} to increment a counter every time a newline is encountered, then displaying the total at the end.
New(uCalc::Transformer, t)// Initialize line counter at the start of the doct.FromTo("{@Beginning}", "{@Exec: Variable: lncnt = 1}")// For every newline, increment the countert.FromTo("{@nl}", "{@@Exec: lncnt = lncnt + 1}{@Self}")// At the end, show the line countt.FromTo("{@End}", " [Total Lines: {@@Eval: lncnt}]")wl(t.Transform("A\nB\nC"))[Expected Output]ABC [Total Lines: 3]
3. Internal Test (Ignoring Horizontal Space)
Verifying that {@nl} ignores horizontal whitespace (tabs and spaces) and only triggers on true vertical breaks.
New(uCalc::Transformer, t)t.FromTo("{@nl}", "[BREAK]")// The spaces between 'A' and 'B' should remain untouchedwl(t.Transform("A B\nC"))[Expected Output]A B[BREAK]C
Strategy & Critique
- Structural Safety: The categorical separation of
{@ws}and{@nl}ensures that developers can perform aggressive horizontal whitespace normalization without worrying about losing the vertical "shape" of the code or document. - Performance: Because newlines are identified during the initial lexing phase, matching
{@nl}is significantly faster than using a regex that has to backtrack through various whitespace combinations. - Critique: One potential pitfall for new users is forgetting that
\r\n(Windows style) is often treated as a single token.{@nl}handles this automatically, but capturing the newline into a variable might yield different raw string values depending on the source document's encoding. - See Also: Refer to Topic 801 (
{@Whitespace}) for horizontal spacing control.
Examples
Matching by token type
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
t.FromTo("{@String:txt}", "<>");
t.FromTo("{@Number:MyNum}", "");
t.FromTo("{@Bracket:MyBrack}", "");
t.FromTo("{@CloseBracket:CloseBr}", "");
t.FromTo("{@StatementSeparator:Sep}", "");
t.FromTo("{@Alphanumeric:alpha}", "");
t.FromTo("{@Whitespace:ws}", "");
t.FromTo("{@Reducible:r}", "");
t.FromTo("{@Newline}", "");
var s = """
This is 55.2*6 "Hello world";
'Single quote'(parenth)
""";
Console.WriteLine(t.Filter(s).Matches.Text);
<Alpha=This>
<whitespace count=1>
<Alpha=is>
<whitespace count=3>
<NumericValue=55.2>
<Reducible=*>
<NumericValue=6>
<whitespace count=1>
<<InnerQuote=Hello world><TxtWithQuotes="Hello world">>
<Separator=;>
<New line
>
<<InnerQuote=Single quote><TxtWithQuotes='Single quote'>>
<Brack=(>
<Alpha=parenth>
<CloseBrack=)> using uCalcSoftware; var uc = new uCalc(); var t = uc.NewTransformer(); t.FromTo("{@String:txt}", "<<InnerQuote={txt}><TxtWithQuotes={txt(0)}>>"); t.FromTo("{@Number:MyNum}", "<NumericValue={MyNum}>"); t.FromTo("{@Bracket:MyBrack}", "<Brack={MyBrack}>"); t.FromTo("{@CloseBracket:CloseBr}", "<CloseBrack={CloseBr}>"); t.FromTo("{@StatementSeparator:Sep}", "<Separator={Sep}>"); t.FromTo("{@Alphanumeric:alpha}", "<Alpha={alpha}>"); t.FromTo("{@Whitespace:ws}", "<whitespace count={@Eval: Length(ws)}>"); t.FromTo("{@Reducible:r}", "<Reducible={r}>"); t.FromTo("{@Newline}", "<New line{@Newline}>"); var s = """ This is 55.2*6 "Hello world"; 'Single quote'(parenth) """; Console.WriteLine(t.Filter(s).Matches.Text);
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
t.FromTo("{@String:txt}", "<>");
t.FromTo("{@Number:MyNum}", "");
t.FromTo("{@Bracket:MyBrack}", "");
t.FromTo("{@CloseBracket:CloseBr}", "");
t.FromTo("{@StatementSeparator:Sep}", "");
t.FromTo("{@Alphanumeric:alpha}", "");
t.FromTo("{@Whitespace:ws}", "");
t.FromTo("{@Reducible:r}", "");
t.FromTo("{@Newline}", "");
auto s = R"(This is 55.2*6 "Hello world";
'Single quote'(parenth))";
cout << t.Filter(s).Matches().Text() << endl;
}
<Alpha=This>
<whitespace count=1>
<Alpha=is>
<whitespace count=3>
<NumericValue=55.2>
<Reducible=*>
<NumericValue=6>
<whitespace count=1>
<<InnerQuote=Hello world><TxtWithQuotes="Hello world">>
<Separator=;>
<New line
>
<<InnerQuote=Single quote><TxtWithQuotes='Single quote'>>
<Brack=(>
<Alpha=parenth>
<CloseBrack=)> #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.NewTransformer(); t.FromTo("{@String:txt}", "<<InnerQuote={txt}><TxtWithQuotes={txt(0)}>>"); t.FromTo("{@Number:MyNum}", "<NumericValue={MyNum}>"); t.FromTo("{@Bracket:MyBrack}", "<Brack={MyBrack}>"); t.FromTo("{@CloseBracket:CloseBr}", "<CloseBrack={CloseBr}>"); t.FromTo("{@StatementSeparator:Sep}", "<Separator={Sep}>"); t.FromTo("{@Alphanumeric:alpha}", "<Alpha={alpha}>"); t.FromTo("{@Whitespace:ws}", "<whitespace count={@Eval: Length(ws)}>"); t.FromTo("{@Reducible:r}", "<Reducible={r}>"); t.FromTo("{@Newline}", "<New line{@Newline}>"); auto s = R"(This is 55.2*6 "Hello world"; 'Single quote'(parenth))"; cout << t.Filter(s).Matches().Text() << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
t.FromTo("{@String:txt}", "<>")
t.FromTo("{@Number:MyNum}", "")
t.FromTo("{@Bracket:MyBrack}", "")
t.FromTo("{@CloseBracket:CloseBr}", "")
t.FromTo("{@StatementSeparator:Sep}", "")
t.FromTo("{@Alphanumeric:alpha}", "")
t.FromTo("{@Whitespace:ws}", "")
t.FromTo("{@Reducible:r}", "")
t.FromTo("{@Newline}", "")
Dim s = "This is 55.2*6 ""Hello world"";
'Single quote'(parenth)"
Console.WriteLine(t.Filter(s).Matches.Text)
End Sub
End Module
<Alpha=This>
<whitespace count=1>
<Alpha=is>
<whitespace count=3>
<NumericValue=55.2>
<Reducible=*>
<NumericValue=6>
<whitespace count=1>
<<InnerQuote=Hello world><TxtWithQuotes="Hello world">>
<Separator=;>
<New line
>
<<InnerQuote=Single quote><TxtWithQuotes='Single quote'>>
<Brack=(>
<Alpha=parenth>
<CloseBrack=)> Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.NewTransformer() t.FromTo("{@String:txt}", "<<InnerQuote={txt}><TxtWithQuotes={txt(0)}>>") t.FromTo("{@Number:MyNum}", "<NumericValue={MyNum}>") t.FromTo("{@Bracket:MyBrack}", "<Brack={MyBrack}>") t.FromTo("{@CloseBracket:CloseBr}", "<CloseBrack={CloseBr}>") t.FromTo("{@StatementSeparator:Sep}", "<Separator={Sep}>") t.FromTo("{@Alphanumeric:alpha}", "<Alpha={alpha}>") t.FromTo("{@Whitespace:ws}", "<whitespace count={@Eval: Length(ws)}>") t.FromTo("{@Reducible:r}", "<Reducible={r}>") t.FromTo("{@Newline}", "<New line{@Newline}>") Dim s = "This is 55.2*6 ""Hello world""; 'Single quote'(parenth)" Console.WriteLine(t.Filter(s).Matches.Text) End Sub End Module