PHPackages                             php-rpn/rpn - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. php-rpn/rpn

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

php-rpn/rpn
===========

Reverse Polish Notation implementation in PHP

1.4.1(4mo ago)2227↓50%MITPHPPHP &gt;=8.3CI passing

Since Dec 18Pushed 4mo agoCompare

[ Source](https://github.com/alexandrmazur96/reverse-polish-notation-php)[ Packagist](https://packagist.org/packages/php-rpn/rpn)[ RSS](/packages/php-rpn-rpn/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (7)Dependencies (6)Versions (8)Used By (0)

RPN - Reverse Polish Notation Calculator
========================================

[](#rpn---reverse-polish-notation-calculator)

A flexible and extensible PHP library for parsing and evaluating mathematical expressions using **Reverse Polish Notation (RPN)**. It uses a **Shunting-yard algorithm** implementation that is configurable and easy to use.

What is Reverse Polish Notation?
--------------------------------

[](#what-is-reverse-polish-notation)

Reverse Polish Notation (also called postfix notation) is a mathematical notation in which operators follow their operands. For example:

- **Infix:** `3 + 4 * 2`
- **RPN/Postfix:** `3 4 2 * +`

RPN eliminates the need for parentheses and operator precedence rules during evaluation, making it simpler and faster to compute.

Installation
------------

[](#installation)

```
composer require php-rpn/rpn
```

### Requirements

[](#requirements)

- PHP 8.3 or higher

Features
--------

[](#features)

- ✅ **Fluent Builder Interface** for creating customized parsers.
- ✅ **Parse infix mathematical expressions** to an RPN stream using the Shunting-yard algorithm.
- ✅ **Extensible Operator Registry** to add or override operators.
- ✅ **Evaluate RPN expression streams**.
- ✅ **Support for standard operators:**
    - Binary operators: `+`, `-`, `*` (×), `/` (÷)
    - Unary operators: `-` (negation), `!` (factorial)
- ✅ **Support for mathematical functions:**
    - `sqrt()`|`√` - Square root
    - `pow()`|`^` - Power function
    - `log()` - Natural logarithm
    - `exp()` - Exponential function
    - `min()` - Minimum of two values
    - `max()` - Maximum of two values
    - `∛` (cube root)
    - `∜` (fourth root)
- ✅ **Variable support** for dynamic expressions.
- ✅ **Proper operator associativity** handling.
- ✅ **Type-safe PHP 8.3+** with strict types.

Usage
-----

[](#usage)

The library is designed with a fluent builder to make parsing and evaluation straightforward.

### Basic Usage

[](#basic-usage)

```
use Rpn\Expression;
use Rpn\Parsers\ShuntingYardParserBuilder;

// 1. Get a pre-configured parser for standard math operations.
$parser = ShuntingYardParserBuilder::math()->build();

// 2. Parse an infix expression into an RPN stream.
$rpnStream = $parser->parse('3 + 4 * 2');

// 3. Evaluate the stream.
$evaluator = new Expression();
echo $evaluator->evaluate($rpnStream)->value(); // Output: 11
```

### Using Mathematical Functions

[](#using-mathematical-functions)

```
use Rpn\Expression;
use Rpn\Parsers\ShuntingYardParserBuilder;

$parser = ShuntingYardParserBuilder::math()->build();
$evaluator = new Expression();

// Parse expressions with functions
$rpnStream = $parser->parse('sqrt(16) + pow(2, 3)');
echo $evaluator->evaluate($rpnStream)->value(); // Output: 12 (4 + 8)
```

### Using Variables

[](#using-variables)

```
use Rpn\Expression;
use Rpn\Parsers\ShuntingYardParserBuilder;

$parser = ShuntingYardParserBuilder::math()->build();
$evaluator = new Expression();

// Variables should start with a colon (:)

// Parse an expression with variables
$rpnStream = $parser->parse('(:a * :b + :c) * 2');

$evaluator->evaluate($rpnStream, [':a' => 3, ':b' => 4, ':c' => 5])->value(); // Output: 34
```

### Customization

[](#customization)

You can easily add your own custom operators if you need to. Just implement the `OperatorInterface` and register it with the parser builder:

```
use Rpn\Expression;
use Rpn\Parsers\ShuntingYardParserBuilder;
use Rpn\Operators\OperatorInterface;
use Rpn\Operands\OperandInterface;
use Rpn\Enum\Associativity;
use Rpn\Enum\OperatorType;

// Define a custom "double factorial" operator
class DoubleFactorial implements OperatorInterface {
    public function getPrecedence(): int { return 10; }
    public function getAssociativity(): Associativity { return Associativity::Left; }
    public function getType(): OperatorType { return OperatorType::UnaryPostfix; }
    public function apply(OperandInterface ...$operands): OperandInterface {
        $val = $operands[0]->value();
        $result = 1;
        for ($i = $val; $i >= 1; $i -= 2) {
            $result *= $i;
        }
        return new \Rpn\Operands\Number($result);
    }
}

// Create a parser and add the new operator
$parser = ShuntingYardParserBuilder::math()
    ->addOperator('!!', new DoubleFactorial())
    ->build();

$evaluator = new Expression();

$rpnStream = $parser->parse('5!!'); // 5 * 3 * 1
echo $evaluator->evaluate($rpnStream)->value(); // Output: 15
```

### Supported Syntax

[](#supported-syntax)

The default parser supports both standard ASCII and Unicode mathematical symbols:

OperationASCIIUnicodeExampleAddition`+`-`1 + 7`Subtraction`-`-`5 - 49`Multiply`*``×``3 × 4`Divide`/``÷``10 ÷ 2`Power`^`, `pow`-`2 ^ 3`Factorial`!`-`5!`Square Root`sqrt``√``sqrt(16)` or `√16`Cube Root-`∛``∛27`Fourth Root-`∜``∜81`Exponential function`exp`-`exp(3)`Min`min`-`min(3, :x)`Max`min`-`max(7, :x)`Log`log`-`log(10)`Percent`%`-`5%`Negation`-`-`-3`Development
-----------

[](#development)

Feel free to contribute! Fork the repository and submit a pull request. Just make sure everything satisfies the coding standards and all tests pass.

```
composer checks
```

How It Works
------------

[](#how-it-works)

### 1. Parsing (Infix to RPN)

[](#1-parsing-infix-to-rpn)

The `ShuntingYardParser` converts an infix string like `3 + 4 * 2` into an `ExpressionPartsStream`.

TokenActionOutput Stream (Conceptual)Operator Stack`3`Add to stream`[Number(3)]``+`Push to stack`[Number(3)]``[+]``4`Add to stream`[Number(3), Number(4)]``[+]``*`Higher precedence, push`[Number(3), Number(4)]``[+, *]``2`Add to stream`[Number(3), Number(4), Number(2)]``[+, *]`EndPop all operators`[Number(3), Number(4), Number(2), *, +]`### 2. Evaluation

[](#2-evaluation)

The `Expression::evaluate()` method iterates the `ExpressionPartsStream` and uses a stack to compute the result.

Expression Stream: `[Number(3), Number(4), Number(2), *, +]`

TokenStack AfterExplanation`3``[3]`Push 3`4``[3, 4]`Push 4`2``[3, 4, 2]`Push 2`*``[3, 8]`Pop 4, 2; compute 4\*2=8; push 8`+``[11]`Pop 3, 8; compute 3+8=11; push 11License
-------

[](#license)

This library is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Author
------

[](#author)

Olexandr Mazur

⭐ Star this project on GitHub — it motivates me a lot!

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance74

Regular maintenance activity

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

7

Last Release

147d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1df16a30b0fe8682fcc23838dfe177aaf2bba74527a732a70e5b131b8966b24e?d=identicon)[Alexandr Mazur](/maintainers/Alexandr%20Mazur)

---

Top Contributors

[![alexandrmazur96](https://avatars.githubusercontent.com/u/20535375?v=4)](https://github.com/alexandrmazur96 "alexandrmazur96 (90 commits)")

---

Tags

calculatorRPNReverse Polish Notationexpression evaluation

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/php-rpn-rpn/health.svg)

```
[![Health](https://phpackages.com/badges/php-rpn-rpn/health.svg)](https://phpackages.com/packages/php-rpn-rpn)
```

###  Alternatives

[markrogoyski/ipv4-subnet-calculator

Network calculator for subnet mask and other classless (CIDR) network information.

177813.7k6](/packages/markrogoyski-ipv4-subnet-calculator)[ballen/distical

A distance (Lat/Long) calculation library for PHP

40180.2k2](/packages/ballen-distical)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
