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.

Precedence = [int]

Property

Product: 

Fast Math Parser

Class: 

Item

Gets the precedence level of a symbol, which determines its binding strength in the order of operations.

Remarks

The Precedence() method returns the numeric precedence level of an operator or rule. This value determines the order of operations in an expression, dictating which operations are performed first when multiple operators are present.

For example, in standard mathematics, multiplication has a higher precedence than addition, which is why the expression 2 + 3 * 4 evaluates to 14 (2 + 12) rather than 20 (5 * 4).

# ⚙️ How Precedence Works in uCalc

In uCalc, precedence is represented by a numeric value. A higher number means higher precedence (it binds more tightly and is evaluated sooner).

This method is essential for two main tasks:

  1. Inspecting Existing Operators: You can query the precedence of built-in operators like +, *, or And to understand the default evaluation order.
  2. Defining New Operators: When creating a custom operator with DefineOperator, you must assign it a precedence level. The best practice is to base this level on an existing operator's precedence.

# 💡 Best Practices

Avoid hardcoding 'magic numbers' for precedence levels. The exact numeric values of built-in operators can change between versions. Instead, always define precedence relative to an existing, well-understood operator.

Good Practice (Relative):

// Give the new operator a higher precedence than multiplication.var mul_prec = uc.ItemOf("*", ItemIs.Infix).Precedence();uc.DefineOperator("{a} ** {b} = Pow(a, b)", mul_prec + 10);

Bad Practice (Hardcoded):

// Avoid this. '60' is an internal detail.uc.DefineOperator("{a} ** {b} = Pow(a, b)", 70);

# 🆚 Comparative Analysis: Why uCalc?

In most compiled languages like C# or C++, operator precedence is fixed at compile-time. You cannot change the fact that * is evaluated before +, nor can you invent new operators with custom precedence levels.

This is where uCalc offers a significant advantage. Its precedence system is fully configurable at runtime. This allows you to:

  • Create Domain-Specific Languages (DSLs): Invent new operators (e.g., contains, matches, within) with intuitive precedence rules that make sense for your specific domain.
  • Adapt Syntax: Modify the parsing behavior on the fly, perhaps based on a user's dialect preference or a specific compatibility mode.
  • Experiment Safely: Dynamically add or change operators without needing to recompile your application.

Setter

This method sets the precedence level of an Item, which is a crucial property for operators and some transformer rules. Precedence determines the order of operations in an expression—which operators are evaluated first. For example, in standard arithmetic, multiplication has a higher precedence than addition.

Dynamic Control at Runtime

While precedence is typically set when an operator is first created with DefineOperator(), this method allows you to change it dynamically at runtime. This provides powerful control for creating adaptive syntaxes or reconfiguring a parser without a full restart.

⚠️ Important Note on ParsingA change in precedence only affects expressions that are parsed after the change is made. It does not alter expressions that have already been compiled with Parse(). Those expressions would need to be re-parsed to reflect the new precedence rules.

The actual numeric value of the precedence level is arbitrary; its meaning comes from its relationship to the precedence levels of other operators. A higher number means higher precedence (tighter binding).

💡 Comparative Analysis: Why uCalc?

In compiled languages like C# or C++, operator precedence is fixed by the language specification and cannot be changed. For example, * will always have higher precedence than +. This is a rigid, compile-time rule.

uCalc's model is fundamentally more flexible. By allowing precedence to be modified at runtime, you can:

  • Create Domain-Specific Languages (DSLs): Invent a custom order of operations that is intuitive for a specific domain (e.g., financial modeling, scientific notation).
  • Emulate Other Languages: Adjust precedence to match the behavior of another language's operators for easier transpilation.
  • User-Configurable Syntax: Allow end-users to customize how their formulas are interpreted.

This runtime configurability is a significant advantage over static, compiled-language approaches.

Examples

Retrieving the precedence levels of built-in arithmetic operators to compare their binding strength.
				
					using uCalcSoftware;

var uc = new uCalc();
var plus_op = uc.ItemOf("+", uCalc.Properties(ItemIs.Infix));
var mul_op = uc.ItemOf("*", uCalc.Properties( ItemIs.Infix));

Console.WriteLine($"Precedence of '+': {plus_op.Precedence}");
Console.WriteLine($"Precedence of '*': {mul_op.Precedence}");
Console.WriteLine($"Does '*' bind tighter than '+'? {mul_op.Precedence > plus_op.Precedence}");
				
			
Precedence of '+': 50
Precedence of '*': 60
Does '*' bind tighter than '+'? True
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

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

int main() {
   uCalc uc;
   auto plus_op = uc.ItemOf("+", uCalc::Properties(ItemIs::Infix));
   auto mul_op = uc.ItemOf("*", uCalc::Properties( ItemIs::Infix));

   cout << "Precedence of '+': " << plus_op.Precedence() << endl;
   cout << "Precedence of '*': " << mul_op.Precedence() << endl;
   cout << "Does '*' bind tighter than '+'? " << tf(mul_op.Precedence() > plus_op.Precedence()) << endl;
}
				
			
Precedence of '+': 50
Precedence of '*': 60
Does '*' bind tighter than '+'? True
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim plus_op = uc.ItemOf("+", uCalc.Properties(ItemIs.Infix))
      Dim mul_op = uc.ItemOf("*", uCalc.Properties( ItemIs.Infix))
      
      Console.WriteLine($"Precedence of '+': {plus_op.Precedence}")
      Console.WriteLine($"Precedence of '*': {mul_op.Precedence}")
      Console.WriteLine($"Does '*' bind tighter than '+'? {mul_op.Precedence > plus_op.Precedence}")
   End Sub
End Module
				
			
Precedence of '+': 50
Precedence of '*': 60
Does '*' bind tighter than '+'? True
Defining a new custom operator with a precedence level set relative to an existing operator.
				
					using uCalcSoftware;

var uc = new uCalc();
// Goal: Define a new power operator '**' with higher precedence than multiplication '*'.
var mul_precedence = uc.ItemOf("*", uCalc.Properties(ItemIs.Infix)).Precedence;

// Set the new operator's precedence to be higher than multiplication.
uc.DefineOperator("{base} ** {exp} = Pow(base, exp)", mul_precedence + 10);

// The new operator should be evaluated before multiplication and addition.
// The expression is equivalent to: 2 + (3 * (2 ** 3)) -> 2 + (3 * 8) -> 2 + 24 -> 26
Console.WriteLine(uc.Eval("2 + 3 * 2 ** 3"));
				
			
26
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Goal: Define a new power operator '**' with higher precedence than multiplication '*'.
   auto mul_precedence = uc.ItemOf("*", uCalc::Properties(ItemIs::Infix)).Precedence();

   // Set the new operator's precedence to be higher than multiplication.
   uc.DefineOperator("{base} ** {exp} = Pow(base, exp)", mul_precedence + 10);

   // The new operator should be evaluated before multiplication and addition.
   // The expression is equivalent to: 2 + (3 * (2 ** 3)) -> 2 + (3 * 8) -> 2 + 24 -> 26
   cout << uc.Eval("2 + 3 * 2 ** 3") << endl;
}
				
			
26
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Goal: Define a new power operator '**' with higher precedence than multiplication '*'.
      Dim mul_precedence = uc.ItemOf("*", uCalc.Properties(ItemIs.Infix)).Precedence
      
      '// Set the new operator's precedence to be higher than multiplication.
      uc.DefineOperator("{base} ** {exp} = Pow(base, exp)", mul_precedence + 10)
      
      '// The new operator should be evaluated before multiplication and addition.
      '// The expression is equivalent to: 2 + (3 * (2 ** 3)) -> 2 + (3 * 8) -> 2 + 24 -> 26
      Console.WriteLine(uc.Eval("2 + 3 * 2 ** 3"))
   End Sub
End Module
				
			
26
Internal Test: Demonstrates how changing an operator's precedence at runtime affects the parsing of subsequent expressions.
				
					using uCalcSoftware;

var uc = new uCalc();
// Define '##' with the same precedence as 'And'. 'And' binds tighter than 'Or'.
var and_prec = uc.ItemOf("And", uCalc.Properties(ItemIs.Infix)).Precedence;
var op_handle = uc.DefineOperator("{a} ## {b} As Boolean = a and b", and_prec);

Console.WriteLine("--- Initial Precedence (like 'And') ---");
// Evaluation is like: true or (false and false) -> true or false -> true
Console.WriteLine(uc.EvalStr("true or false ## 1 == 2"));

// Now, change the precedence to be lower than 'Or'.
var or_prec = uc.ItemOf("Or", uCalc.Properties(ItemIs.Infix)).Precedence;
op_handle.Precedence = or_prec - 10;

Console.WriteLine("");
Console.WriteLine("--- Changed Precedence (lower than 'Or') ---");
// Evaluation is like: (true or false) and false -> true and false -> false
Console.WriteLine(uc.EvalStr("true or false ## 1 == 2"));
				
			
--- Initial Precedence (like 'And') ---
true

--- Changed Precedence (lower than 'Or') ---
false
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Define '##' with the same precedence as 'And'. 'And' binds tighter than 'Or'.
   auto and_prec = uc.ItemOf("And", uCalc::Properties(ItemIs::Infix)).Precedence();
   auto op_handle = uc.DefineOperator("{a} ## {b} As Boolean = a and b", and_prec);

   cout << "--- Initial Precedence (like 'And') ---" << endl;
   // Evaluation is like: true or (false and false) -> true or false -> true
   cout << uc.EvalStr("true or false ## 1 == 2") << endl;

   // Now, change the precedence to be lower than 'Or'.
   auto or_prec = uc.ItemOf("Or", uCalc::Properties(ItemIs::Infix)).Precedence();
   op_handle.Precedence(or_prec - 10);

   cout << "" << endl;
   cout << "--- Changed Precedence (lower than 'Or') ---" << endl;
   // Evaluation is like: (true or false) and false -> true and false -> false
   cout << uc.EvalStr("true or false ## 1 == 2") << endl;
}
				
			
--- Initial Precedence (like 'And') ---
true

--- Changed Precedence (lower than 'Or') ---
false
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Define '##' with the same precedence as 'And'. 'And' binds tighter than 'Or'.
      Dim and_prec = uc.ItemOf("And", uCalc.Properties(ItemIs.Infix)).Precedence
      Dim op_handle = uc.DefineOperator("{a} ## {b} As Boolean = a and b", and_prec)
      
      Console.WriteLine("--- Initial Precedence (like 'And') ---")
      '// Evaluation is like: true or (false and false) -> true or false -> true
      Console.WriteLine(uc.EvalStr("true or false ## 1 == 2"))
      
      '// Now, change the precedence to be lower than 'Or'.
      Dim or_prec = uc.ItemOf("Or", uCalc.Properties(ItemIs.Infix)).Precedence
      op_handle.Precedence = or_prec - 10
      
      Console.WriteLine("")
      Console.WriteLine("--- Changed Precedence (lower than 'Or') ---")
      '// Evaluation is like: (true or false) and false -> true and false -> false
      Console.WriteLine(uc.EvalStr("true or false ## 1 == 2"))
   End Sub
End Module
				
			
--- Initial Precedence (like 'And') ---
true

--- Changed Precedence (lower than 'Or') ---
false
Finding the precedence level of an operator
				
					using uCalcSoftware;

var uc = new uCalc();
uc.DefineOperator("{a As Bool} ## {b As Bool} As Bool = a And b", uc.ItemOf("And").Precedence);
Console.WriteLine(uc.EvalStr("true Or false ## 2 > 5"));

uc.ItemOf("##").SetPrecedence(uc.ItemOf("Or").Precedence);
Console.WriteLine(uc.EvalStr("true Or false ## 2 > 5"));
				
			
true
false
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uc.DefineOperator("{a As Bool} ## {b As Bool} As Bool = a And b", uc.ItemOf("And").Precedence());
   cout << uc.EvalStr("true Or false ## 2 > 5") << endl;

   uc.ItemOf("##").SetPrecedence(uc.ItemOf("Or").Precedence());
   cout << uc.EvalStr("true Or false ## 2 > 5") << endl;
}
				
			
true
false
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineOperator("{a As Bool} ## {b As Bool} As Bool = a And b", uc.ItemOf("And").Precedence)
      Console.WriteLine(uc.EvalStr("true Or false ## 2 > 5"))
      
      uc.ItemOf("##").SetPrecedence(uc.ItemOf("Or").Precedence)
      Console.WriteLine(uc.EvalStr("true Or false ## 2 > 5"))
   End Sub
End Module
				
			
true
false