Skip to content

Operator

Muqsit Rayyan edited this page Oct 13, 2022 · 17 revisions

arithmexp features two kinds of operators — unary, and binary. Below is a list of all operators featured by the library.

Operator Name
+ Binary Addition
/ Binary Division
** Binary Exponentiation
% Binary Modulo
* Binary Multiplication
- Binary Subtraction
- Unary Negative
+ Unary Positive

Operator Precedence

Operator precedence in arithmexp is at par with PHP's arithmetic operator precedence. Precedence of binary operators is governed by two attributes — a priority value (an integer), and associativity (left-associative or right-associative). If an operator ~ is left-associative, then x ~ y ~ z will be computed as (x ~ y) ~ z. If the operator were right-associative, the expression would be computed as x ~ (y ~ z). While there seems to be no difference in the resulting value due to associativity type in the given expression, this may not always be the case. For example, when multiple operators differing by commutativity are given the same precedence (such as in x - y + z where + and - are given the same precedence and are left-associative), the expression 7 - 6 + 5 would evaluate as (7 - 6) + 5 = 6 instead of 7 - (6 + 5) = -4. You can read more about operator associativity here.

Below is a table of binary operators in ascending order of precedence.

Associativity Operators
Right-associative **
Left-associative * / %
Left-associative + -

Operator Definition

An operator may be registered for a given parser before expressions are parsed by invoking BinaryOperatorRegistry::register() to register a binary operator, or UnaryOperatorRegistry::register() to register a unary operator.

$bop_registry = $parser->getBinaryOperatorRegistry();
$bop_registry->register(new SimpleBinaryOperator(
	"..", // <- symbol
	"Random Value", // <- name
	BinaryOperatorPrecedence::EXPONENTIAL,
	RightBinaryOperatorAssignment::instance(),
	static fn(int $x, int $y) : int => mt_rand($x, $y), // <- computer
	false, // <- is deterministic?
	false // <- is commutative?
));

$uop_registry = $parser->getUnaryOperatorRegistry();
$uop_registry->register(new SimpleUnaryOperator(
	"^", // <- symbol
	"Reciprocal", // <- name
	static fn(int|float $x) : int|float => 1 / $x, // <- computer
	true // <- is determinstic?
));

$parser->parse("3..5")->evaluate(); // may be 3
$parser->parse("3..5")->evaluate(); // may be 4
$parser->parse("3..5")->evaluate(); // may be 5
$parser->parse("^5")->evaluate(); // 0.2

Unary operators use prefix notation (the operator appears before its operand), while binary operators use infix notation (the operator appears between its operands). Commutativity and determinism here hold the same meaning as they do in functions.

Why do I need to define determinism and commutativity for an operator?
These properties are used by various optimization techniques in making informative decisions to reduce computation. For example, the optimizer may resolve (x + y) - (y + x) to a constant expression 0, eliminating variables resolution completely for the given expression.

1. Quick Start

1.1. Installation

2. Documentation Notes

2.1. Constant
2.2. Function
2.3. Macro
2.4. Operator
2.5. Variable
2.6. Expression Optimization
2.7. Implementation Internals

Clone this wiki locally