uCalc API Version: 5.7.0-preview.1 Released: 7/30/2026

Warning

uCalc API Preview Release Notice:This preview documentation describes the intended behavior of the API. It is not fully accurate or complete.The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.Use of the preview version in your production code is not recommended.

{@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, _newline is 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.

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

ID: 176

				
					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);
				
			
<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;
}
				
			
<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
				
			
<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=)>