-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCalculations.php
39 lines (30 loc) · 1.27 KB
/
Calculations.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php declare(strict_types=1);
namespace Stratadox\Parser\Test\Examples\Calculator;
use Stratadox\Parser\Containers\Grammar;
use Stratadox\Parser\Containers\Lazy;
use Stratadox\Parser\Parser;
use function Stratadox\Parser\pattern;
use function Stratadox\Parser\text;
final class Calculations
{
public static function parser(): Parser
{
$grammar = Grammar::with($lazy = Lazy::container());
$sign = text('+')->or('-')->maybe();
$digits = pattern('\d+');
$map = fn($op, $l, $r) => [
'op' => $op,
'arg' => [$l, $r],
];
$grammar['prio 0'] = $sign->andThen($digits, '.', $digits)->join()->map(fn($x) => (float) $x)
->or($sign->andThen($digits)->join()->map(fn($x) => (int) $x))
->between(text(' ')->or("\t", "\n", "\r")->repeatable()->optional());
$lazy['prio 1'] = $grammar['prio 0']->andThen('^', $grammar['prio 0'])->map(fn($a) => [
'op' => '^',
'arg' => [$a[0], $a[2]],
])->or($grammar['prio 0']);
$grammar['prio 2'] = $grammar['prio 1']->keepSplit(['*', '/'], $map)->or($grammar['prio 1']);
$grammar['prio 3'] = $grammar['prio 2']->keepSplit(['+', '-'], $map)->or($grammar['prio 2']);
return $grammar['prio 3']->end();
}
}