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.
Learn how uCalc's grammar can be extended at runtime by defining new operators, keywords, and literal formats.
Most programming languages and parsers have a fixed, unchangeable grammar. The meaning of +, if, or 123 is defined by the language specification and cannot be altered. uCalc is different. Its syntax is dynamic, meaning you can teach the engine new tricks—new operators, new keywords, and even new ways to write numbers—at runtime, without recompiling your application.
This capability transforms uCalc from a simple expression evaluator into a lightweight language workbench, allowing you to create expressive, human-readable Domain-Specific Languages (DSLs) tailored to your specific needs.
There are two primary ways to create custom syntax, depending on your needs:
DefineOperatorThe DefineOperator method is for creating new operators that consist of a single alphanumeric word (like and) or a single symbol (like ##).
For example, let's create a percentof operator:
### B. Multi-Word Syntax with the TransformerFor more complex, multi-word syntax like `100 USD to EUR`, the correct tool is the [ExpressionTransformer](/Reference/uCalcBase/uCalc/ExpressionTransformer). It allows you to define flexible, token-aware patterns that are transformed into standard expressions before evaluation.```csharp
// Get the transformer that pre-processes expressions.
var t = uc.ExpressionTransformer;
// Define a rule to handle the multi-word syntax.
t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})");
// The new syntax is now available in any expression.
Console.WriteLine($"100 USD is {uc.EvalStr("100 USD to EUR")} EUR");
```---## 2. Creating Custom Literals (The Advanced Way)Extending the syntax to support new literal formats, like C-style hexadecimal numbers (`0xFF`), is a more advanced process that showcases the power of uCalc's two-stage parsing pipeline. It involves two steps:1. **Lexical Definition**: Teach the tokenizer what the new literal *looks like* using a regular expression via [ExpressionTokens](/Reference/uCalcBase/uCalc/ExpressionTokens).2. **Semantic Transformation**: Tell the engine what the new literal *means* by transforming it into a standard expression via the [TokenTransformer](/Reference/uCalcBase/uCalc/TokenTransformer).#### Example: Adding `0x...` Hexadecimal Support```csharp
// Step 1: Define the lexical rule.
// TokenType::TokenTransform tells the parser that this token needs pre-processing.
uc.ExpressionTokens.Add("0x[0-9a-fA-F]+", TokenType.TokenTransform);
// Step 2: Define the transformation rule.
// This captures the hex digits ('val') and replaces the whole token (e.g., "0xFF")
// with a standard function call that the engine already understands.
uc.TokenTransformer.FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)");
// Step 3: Use the new literal format directly in any expression.
Console.WriteLine(uc.Eval("0xFF + 1")); // Evaluates 255 + 1
```This two-step process allows you to integrate complex, custom syntax seamlessly into the uCalc engine.---## 💡 Why uCalc? (Comparative Analysis)* **vs. Parser Generators (ANTLR, Flex/Bison)**: These are powerful tools, but their grammars are **static**. To add a new operator or literal, you must modify a grammar file, run a code generator, and recompile your entire application. With uCalc, these changes can be made **programmatically at runtime**, allowing your application to adapt its own syntax on the fly.* **vs. Statically-Compiled Languages (C#, C++)**: In these languages, operator sets and precedence rules are fixed by the language specification. You cannot invent a multi-word `USD to EUR` syntax. uCalc gives you complete control over the grammar, allowing you to build languages that are far more expressive and domain-specific.ID: 1225
using uCalcSoftware;
var uc = new uCalc();
// Use the ExpressionTransformer for multi-word syntax.
var t = uc.ExpressionTransformer;
// Note: Captured variables are passed to @Eval as text
// Double() converts the text to Double a precision value
uc.Format("Result = Format('{:.2f}', Double(Result))", uc.DataTypeOf("Double"));
t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})");
t.FromTo("{@Number:amount} EUR to USD", "({@Eval: Double(amount) / 0.92})");
Console.WriteLine($"100 USD is approx. {uc.EvalStr("100 USD to EUR")} EUR");
Console.WriteLine($"120 EUR is approx. {uc.EvalStr("120 EUR to USD")} USD");
100 USD is approx. 92.00 EUR
120 EUR is approx. 130.43 USD using uCalcSoftware; var uc = new uCalc(); // Use the ExpressionTransformer for multi-word syntax. var t = uc.ExpressionTransformer; // Note: Captured variables are passed to @Eval as text // Double() converts the text to Double a precision value uc.Format("Result = Format('{:.2f}', Double(Result))", uc.DataTypeOf("Double")); t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})"); t.FromTo("{@Number:amount} EUR to USD", "({@Eval: Double(amount) / 0.92})"); Console.WriteLine($"100 USD is approx. {uc.EvalStr("100 USD to EUR")} EUR"); Console.WriteLine($"120 EUR is approx. {uc.EvalStr("120 EUR to USD")} USD");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// Use the ExpressionTransformer for multi-word syntax.
auto t = uc.ExpressionTransformer();
// Note: Captured variables are passed to @Eval as text
// Double() converts the text to Double a precision value
uc.Format("Result = Format('{:.2f}', Double(Result))", uc.DataTypeOf("Double"));
t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})");
t.FromTo("{@Number:amount} EUR to USD", "({@Eval: Double(amount) / 0.92})");
cout << "100 USD is approx. " << uc.EvalStr("100 USD to EUR") << " EUR" << endl;
cout << "120 EUR is approx. " << uc.EvalStr("120 EUR to USD") << " USD" << endl;
}
100 USD is approx. 92.00 EUR
120 EUR is approx. 130.43 USD #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // Use the ExpressionTransformer for multi-word syntax. auto t = uc.ExpressionTransformer(); // Note: Captured variables are passed to @Eval as text // Double() converts the text to Double a precision value uc.Format("Result = Format('{:.2f}', Double(Result))", uc.DataTypeOf("Double")); t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})"); t.FromTo("{@Number:amount} EUR to USD", "({@Eval: Double(amount) / 0.92})"); cout << "100 USD is approx. " << uc.EvalStr("100 USD to EUR") << " EUR" << endl; cout << "120 EUR is approx. " << uc.EvalStr("120 EUR to USD") << " USD" << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// Use the ExpressionTransformer for multi-word syntax.
Dim t = uc.ExpressionTransformer
'// Note: Captured variables are passed to @Eval as text
'// Double() converts the text to Double a precision value
uc.Format("Result = Format('{:.2f}', Double(Result))", uc.DataTypeOf("Double"))
t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})")
t.FromTo("{@Number:amount} EUR to USD", "({@Eval: Double(amount) / 0.92})")
Console.WriteLine($"100 USD is approx. {uc.EvalStr("100 USD to EUR")} EUR")
Console.WriteLine($"120 EUR is approx. {uc.EvalStr("120 EUR to USD")} USD")
End Sub
End Module
100 USD is approx. 92.00 EUR
120 EUR is approx. 130.43 USD Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// Use the ExpressionTransformer for multi-word syntax. Dim t = uc.ExpressionTransformer '// Note: Captured variables are passed to @Eval as text '// Double() converts the text to Double a precision value uc.Format("Result = Format('{:.2f}', Double(Result))", uc.DataTypeOf("Double")) t.FromTo("{@Number:amount} USD to EUR", "({@Eval: Double(amount) * 0.92})") t.FromTo("{@Number:amount} EUR to USD", "({@Eval: Double(amount) / 0.92})") Console.WriteLine($"100 USD is approx. {uc.EvalStr("100 USD to EUR")} EUR") Console.WriteLine($"120 EUR is approx. {uc.EvalStr("120 EUR to USD")} USD") End Sub End Module
ID: 1224
using uCalcSoftware;
var uc = new uCalc();
// Define the variables that the operator's expression will use.
uc.DefineVariable("i");
uc.DefineVariable("total");
// Define a new 'sum_to' operator at runtime, with precedence level of 50.
// It uses the built-in ForLoop function to sum numbers into the 'total' variable.
uc.DefineOperator("{start} sum_to {end} = total = 0; ForLoop(i, start, end, 1, total = total + i)", 50);
// Use the new operator. The result is stored in the 'total' variable.
uc.Eval("1 sum_to 5");
Console.WriteLine($"The sum from 1 to 5 is: {uc.Eval("total")}");
The sum from 1 to 5 is: 15 using uCalcSoftware; var uc = new uCalc(); // Define the variables that the operator's expression will use. uc.DefineVariable("i"); uc.DefineVariable("total"); // Define a new 'sum_to' operator at runtime, with precedence level of 50. // It uses the built-in ForLoop function to sum numbers into the 'total' variable. uc.DefineOperator("{start} sum_to {end} = total = 0; ForLoop(i, start, end, 1, total = total + i)", 50); // Use the new operator. The result is stored in the 'total' variable. uc.Eval("1 sum_to 5"); Console.WriteLine($"The sum from 1 to 5 is: {uc.Eval("total")}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// Define the variables that the operator's expression will use.
uc.DefineVariable("i");
uc.DefineVariable("total");
// Define a new 'sum_to' operator at runtime, with precedence level of 50.
// It uses the built-in ForLoop function to sum numbers into the 'total' variable.
uc.DefineOperator("{start} sum_to {end} = total = 0; ForLoop(i, start, end, 1, total = total + i)", 50);
// Use the new operator. The result is stored in the 'total' variable.
uc.Eval("1 sum_to 5");
cout << "The sum from 1 to 5 is: " << uc.Eval("total") << endl;
}
The sum from 1 to 5 is: 15 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // Define the variables that the operator's expression will use. uc.DefineVariable("i"); uc.DefineVariable("total"); // Define a new 'sum_to' operator at runtime, with precedence level of 50. // It uses the built-in ForLoop function to sum numbers into the 'total' variable. uc.DefineOperator("{start} sum_to {end} = total = 0; ForLoop(i, start, end, 1, total = total + i)", 50); // Use the new operator. The result is stored in the 'total' variable. uc.Eval("1 sum_to 5"); cout << "The sum from 1 to 5 is: " << uc.Eval("total") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// Define the variables that the operator's expression will use.
uc.DefineVariable("i")
uc.DefineVariable("total")
'// Define a new 'sum_to' operator at runtime, with precedence level of 50.
'// It uses the built-in ForLoop function to sum numbers into the 'total' variable.
uc.DefineOperator("{start} sum_to {end} = total = 0; ForLoop(i, start, end, 1, total = total + i)", 50)
'// Use the new operator. The result is stored in the 'total' variable.
uc.Eval("1 sum_to 5")
Console.WriteLine($"The sum from 1 to 5 is: {uc.Eval("total")}")
End Sub
End Module
The sum from 1 to 5 is: 15 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// Define the variables that the operator's expression will use. uc.DefineVariable("i") uc.DefineVariable("total") '// Define a new 'sum_to' operator at runtime, with precedence level of 50. '// It uses the built-in ForLoop function to sum numbers into the 'total' variable. uc.DefineOperator("{start} sum_to {end} = total = 0; ForLoop(i, start, end, 1, total = total + i)", 50) '// Use the new operator. The result is stored in the 'total' variable. uc.Eval("1 sum_to 5") Console.WriteLine($"The sum from 1 to 5 is: {uc.Eval("total")}") End Sub End Module
ID: 1223
using uCalcSoftware;
var uc = new uCalc();
// 1. Define the lexical rule.
// The regex matches '0x' followed by hex digits.
// The TokenType::TokenTransform tells the parser to pre-process this token.
uc.ExpressionTokens.Add("0x[0-9a-fA-F]+", TokenType.TokenTransform);
// 2. Define the transformation rule.
// This captures the hex digits and replaces the whole token with a call to BaseConvert.
uc.TokenTransformer.FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)");
// 3. Now, the new literal format can be used in expressions.
Console.WriteLine(uc.Eval("0xFF + 0xA")); // 255 + 10
Console.WriteLine(uc.EvalStr("Hex(0x100)")); // Hex(256)
265
100 using uCalcSoftware; var uc = new uCalc(); // 1. Define the lexical rule. // The regex matches '0x' followed by hex digits. // The TokenType::TokenTransform tells the parser to pre-process this token. uc.ExpressionTokens.Add("0x[0-9a-fA-F]+", TokenType.TokenTransform); // 2. Define the transformation rule. // This captures the hex digits and replaces the whole token with a call to BaseConvert. uc.TokenTransformer.FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)"); // 3. Now, the new literal format can be used in expressions. Console.WriteLine(uc.Eval("0xFF + 0xA")); // 255 + 10 Console.WriteLine(uc.EvalStr("Hex(0x100)")); // Hex(256)
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// 1. Define the lexical rule.
// The regex matches '0x' followed by hex digits.
// The TokenType::TokenTransform tells the parser to pre-process this token.
uc.ExpressionTokens().Add("0x[0-9a-fA-F]+", TokenType::TokenTransform);
// 2. Define the transformation rule.
// This captures the hex digits and replaces the whole token with a call to BaseConvert.
uc.TokenTransformer().FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)");
// 3. Now, the new literal format can be used in expressions.
cout << uc.Eval("0xFF + 0xA") << endl; // 255 + 10
cout << uc.EvalStr("Hex(0x100)") << endl; // Hex(256)
}
265
100 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // 1. Define the lexical rule. // The regex matches '0x' followed by hex digits. // The TokenType::TokenTransform tells the parser to pre-process this token. uc.ExpressionTokens().Add("0x[0-9a-fA-F]+", TokenType::TokenTransform); // 2. Define the transformation rule. // This captures the hex digits and replaces the whole token with a call to BaseConvert. uc.TokenTransformer().FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)"); // 3. Now, the new literal format can be used in expressions. cout << uc.Eval("0xFF + 0xA") << endl; // 255 + 10 cout << uc.EvalStr("Hex(0x100)") << endl; // Hex(256) }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// 1. Define the lexical rule.
'// The regex matches '0x' followed by hex digits.
'// The TokenType::TokenTransform tells the parser to pre-process this token.
uc.ExpressionTokens.Add("0x[0-9a-fA-F]+", TokenType.TokenTransform)
'// 2. Define the transformation rule.
'// This captures the hex digits and replaces the whole token with a call to BaseConvert.
uc.TokenTransformer.FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)")
'// 3. Now, the new literal format can be used in expressions.
Console.WriteLine(uc.Eval("0xFF + 0xA")) '// 255 + 10
Console.WriteLine(uc.EvalStr("Hex(0x100)")) '// Hex(256)
End Sub
End Module
265
100 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// 1. Define the lexical rule. '// The regex matches '0x' followed by hex digits. '// The TokenType::TokenTransform tells the parser to pre-process this token. uc.ExpressionTokens.Add("0x[0-9a-fA-F]+", TokenType.TokenTransform) '// 2. Define the transformation rule. '// This captures the hex digits and replaces the whole token with a call to BaseConvert. uc.TokenTransformer.FromTo("{'0x'}{val:'[0-9a-fA-F]+'}", "BaseConvert('{val}', 16)") '// 3. Now, the new literal format can be used in expressions. Console.WriteLine(uc.Eval("0xFF + 0xA")) '// 255 + 10 Console.WriteLine(uc.EvalStr("Hex(0x100)")) '// Hex(256) End Sub End Module