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 to detect, handle, and recover from parsing and evaluation errors using uCalc's state-based and callback-driven systems.
No parser is complete without robust error handling. uCalc offers a powerful and flexible system that differs from the traditional try/catch exception model. It provides two primary methods for dealing with errors: reactive state checking and proactive callback handling.
This tutorial covers the two main types of errors and how to manage them.
Errors in uCalc fall into two categories:
The simplest way to handle errors is to check the engine's state after an operation. Every uCalc instance has an Error property that holds information about the last error.
After calling a method like EvalStr, you can check if an error occurred:csharpThis approach is simple and effective for many use cases, but it's reactive—you only know about the error after it has already happened and aborted the operation.
var result = uc.EvalStr("5 * (10 +"); // Invalid syntax
// Check if an error was flagged
if (uc.Error.Code() != ErrorCode.None) {
{
Console.WriteLine($"An error occurred: {uc.Error.Message()}");
}
For more advanced control, you can register an error handler using AddHandler. This callback function is automatically invoked the moment an error occurs, giving you the power to intercept, inspect, and even recover from it.
Your callback receives a uCalc instance (implicitly via uc in examples), giving you access to the full suite of error-reporting methods:
Error.ResponseThe most powerful feature of an error handler is the ability to control what happens next by setting the Error.Response:
ErrorHandlerResponse::Abort (Default): Halts execution immediately.ErrorHandlerResponse::ReRaise: Passes the error to the next handler in the chain.ErrorHandlerResponse::Resume: Instructs the engine to continue execution as if the error never happened.ResumeThe Resume response is what makes uCalc's error handling truly unique. It allows you to fix a problem on the fly and continue.
A common use case is to automatically define variables that a user forgot to declare. The practical example below demonstrates this perfectly.
⚠️ Important: When you Resume, you must resolve the underlying cause of the error. If you don't, the engine will re-encounter the same error, leading to an infinite loop. uCalc has a built-in safety limit to prevent a true infinite loop, which will raise a ReParseOverflow error.
vs. try/catch Exceptions: Traditional exception handling interrupts the program flow and unwinds the call stack, which can be computationally expensive. uCalc's callback system is lightweight and does not unwind the stack. This makes it highly suitable for parsing user input where errors are common and expected, not "exceptional."
vs. C-Style Error Codes: Simply returning an error code after a function call requires the developer to write boilerplate if (error) { ... } checks everywhere. uCalc centralizes this logic into a single, clean handler.
The ability to recover from an error with Resume is the most significant advantage. It elevates error handling from a simple failure-reporting mechanism to a dynamic, interactive recovery system, which is difficult to achieve with standard try/catch blocks.
ID: 1189
using uCalcSoftware;
var uc = new uCalc();
// Trigger a syntax error
uc.EvalStr("1 +");
// Check the error state after the fact
if (uc.Error.Code != ErrorCode.None) {
Console.WriteLine($"Error detected: {uc.Error.Message}");
} else {
Console.WriteLine("Success!");
}
// Perform a successful operation, which clears the error state
uc.EvalStr("1 + 1");
if (uc.Error.Code == ErrorCode.None) {
Console.WriteLine("Previous error was cleared by successful operation.");
}
Error detected: Syntax error
Previous error was cleared by successful operation. using uCalcSoftware; var uc = new uCalc(); // Trigger a syntax error uc.EvalStr("1 +"); // Check the error state after the fact if (uc.Error.Code != ErrorCode.None) { Console.WriteLine($"Error detected: {uc.Error.Message}"); } else { Console.WriteLine("Success!"); } // Perform a successful operation, which clears the error state uc.EvalStr("1 + 1"); if (uc.Error.Code == ErrorCode.None) { Console.WriteLine("Previous error was cleared by successful operation."); }
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// Trigger a syntax error
uc.EvalStr("1 +");
// Check the error state after the fact
if (uc.Error().Code() != ErrorCode::None) {
cout << "Error detected: " << uc.Error().Message() << endl;
} else {
cout << "Success!" << endl;
}
// Perform a successful operation, which clears the error state
uc.EvalStr("1 + 1");
if (uc.Error().Code() == ErrorCode::None) {
cout << "Previous error was cleared by successful operation." << endl;
}
}
Error detected: Syntax error
Previous error was cleared by successful operation. #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // Trigger a syntax error uc.EvalStr("1 +"); // Check the error state after the fact if (uc.Error().Code() != ErrorCode::None) { cout << "Error detected: " << uc.Error().Message() << endl; } else { cout << "Success!" << endl; } // Perform a successful operation, which clears the error state uc.EvalStr("1 + 1"); if (uc.Error().Code() == ErrorCode::None) { cout << "Previous error was cleared by successful operation." << endl; } }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// Trigger a syntax error
uc.EvalStr("1 +")
'// Check the error state after the fact
If uc.Error.Code <> ErrorCode.None Then
Console.WriteLine($"Error detected: {uc.Error.Message}")
Else
Console.WriteLine("Success!")
End If
'// Perform a successful operation, which clears the error state
uc.EvalStr("1 + 1")
If uc.Error.Code = ErrorCode.None Then
Console.WriteLine("Previous error was cleared by successful operation.")
End If
End Sub
End Module
Error detected: Syntax error
Previous error was cleared by successful operation. Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// Trigger a syntax error uc.EvalStr("1 +") '// Check the error state after the fact If uc.Error.Code <> ErrorCode.None Then Console.WriteLine($"Error detected: {uc.Error.Message}") Else Console.WriteLine("Success!") End If '// Perform a successful operation, which clears the error state uc.EvalStr("1 + 1") If uc.Error.Code = ErrorCode.None Then Console.WriteLine("Previous error was cleared by successful operation.") End If End Sub End Module
ID: 1190
using uCalcSoftware;
var uc = new uCalc();
// This handler automatically defines variables when they are first used.
static void AutoDefineHandler(Handle_uCalc h) {
var uc = new uCalc(h);
// Check if the error is specifically an undefined identifier
if (uc.Error.Code == ErrorCode.Undefined_Identifier) {
Console.WriteLine($"Handler: '{uc.Error.Symbol}' is undefined. Defining it now.");
uc.DefineVariable(uc.Error.Symbol);
// Tell the engine to resume the operation
uc.Error.Response = ErrorHandlerResponse.Resume;
}
}
uc.Error.AddHandler(AutoDefineHandler);
// 'my_var' doesn't exist yet, but the handler will create it.
var result = uc.EvalStr("my_var = 100; my_var = my_var * 2");
Console.WriteLine($"Final result: {result}");
Handler: 'my_var' is undefined. Defining it now.
Final result: 200 using uCalcSoftware; var uc = new uCalc(); // This handler automatically defines variables when they are first used. static void AutoDefineHandler(Handle_uCalc h) { var uc = new uCalc(h); // Check if the error is specifically an undefined identifier if (uc.Error.Code == ErrorCode.Undefined_Identifier) { Console.WriteLine($"Handler: '{uc.Error.Symbol}' is undefined. Defining it now."); uc.DefineVariable(uc.Error.Symbol); // Tell the engine to resume the operation uc.Error.Response = ErrorHandlerResponse.Resume; } } uc.Error.AddHandler(AutoDefineHandler); // 'my_var' doesn't exist yet, but the handler will create it. var result = uc.EvalStr("my_var = 100; my_var = my_var * 2"); Console.WriteLine($"Final result: {result}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
// This handler automatically defines variables when they are first used.
void ucalc_call AutoDefineHandler(Handle_uCalc h) {
auto uc = uCalc(h);
// Check if the error is specifically an undefined identifier
if (uc.Error().Code() == ErrorCode::Undefined_Identifier) {
cout << "Handler: '" << uc.Error().Symbol() << "' is undefined. Defining it now." << endl;
uc.DefineVariable(uc.Error().Symbol());
// Tell the engine to resume the operation
uc.Error().Response(ErrorHandlerResponse::Resume);
}
}
int main() {
uCalc uc;
uc.Error().AddHandler(AutoDefineHandler);
// 'my_var' doesn't exist yet, but the handler will create it.
auto result = uc.EvalStr("my_var = 100; my_var = my_var * 2");
cout << "Final result: " << result << endl;
}
Handler: 'my_var' is undefined. Defining it now.
Final result: 200 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; // This handler automatically defines variables when they are first used. void ucalc_call AutoDefineHandler(Handle_uCalc h) { auto uc = uCalc(h); // Check if the error is specifically an undefined identifier if (uc.Error().Code() == ErrorCode::Undefined_Identifier) { cout << "Handler: '" << uc.Error().Symbol() << "' is undefined. Defining it now." << endl; uc.DefineVariable(uc.Error().Symbol()); // Tell the engine to resume the operation uc.Error().Response(ErrorHandlerResponse::Resume); } } int main() { uCalc uc; uc.Error().AddHandler(AutoDefineHandler); // 'my_var' doesn't exist yet, but the handler will create it. auto result = uc.EvalStr("my_var = 100; my_var = my_var * 2"); cout << "Final result: " << result << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
'// This handler automatically defines variables when they are first used.
Public Sub AutoDefineHandler(ByVal h As Handle_uCalc)
Dim uc As New uCalc(h)
'// Check if the error is specifically an undefined identifier
If uc.Error.Code = ErrorCode.Undefined_Identifier Then
Console.WriteLine($"Handler: '{uc.Error.Symbol}' is undefined. Defining it now.")
uc.DefineVariable(uc.Error.Symbol)
'// Tell the engine to resume the operation
uc.Error.Response = ErrorHandlerResponse.Resume
End If
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.Error.AddHandler(AddressOf AutoDefineHandler)
'// 'my_var' doesn't exist yet, but the handler will create it.
Dim result = uc.EvalStr("my_var = 100; my_var = my_var * 2")
Console.WriteLine($"Final result: {result}")
End Sub
End Module
Handler: 'my_var' is undefined. Defining it now.
Final result: 200 Imports System Imports uCalcSoftware Public Module Program '// This handler automatically defines variables when they are first used. Public Sub AutoDefineHandler(ByVal h As Handle_uCalc) Dim uc As New uCalc(h) '// Check if the error is specifically an undefined identifier If uc.Error.Code = ErrorCode.Undefined_Identifier Then Console.WriteLine($"Handler: '{uc.Error.Symbol}' is undefined. Defining it now.") uc.DefineVariable(uc.Error.Symbol) '// Tell the engine to resume the operation uc.Error.Response = ErrorHandlerResponse.Resume End If End Sub Public Sub Main() Dim uc As New uCalc() uc.Error.AddHandler(AddressOf AutoDefineHandler) '// 'my_var' doesn't exist yet, but the handler will create it. Dim result = uc.EvalStr("my_var = 100; my_var = my_var * 2") Console.WriteLine($"Final result: {result}") End Sub End Module