Passed
Push — master ( 9cb16b...0651df )
by Martijn
02:32
created

Integer::setMinimum()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 2
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Vanderlee\Comprehend\Parser\Terminal;
4
5
use Exception;
6
use Vanderlee\Comprehend\Core\Context;
7
use Vanderlee\Comprehend\Match\Failure;
8
use Vanderlee\Comprehend\Match\Success;
9
use Vanderlee\Comprehend\Parser\Parser;
10
11
/**
12
 * Matches an integer within the specified range
13
 *
14
 * @author Martijn
15
 */
16
class Integer extends Parser
17
{
18
    use CaseSensitiveTrait;
19
20
    /**
21
     * List of digits to use for the different bases (up to 36)
22
     * @var string
23
     */
24
    private static $set = '0123456789abcdefghijklmnopqrstuvwxyz';
25
26
    /**
27
     * @var int|null
28
     */
29
    private $minimum;
30
31
    /**
32
     * @var int|null
33
     */
34
    private $maximum;
35
36
    /**
37
     * @var int
38
     */
39
    private $base;
40
41
    /**
42
     * @param int|null $minimum
43
     * @param int|null $maximum
44
     * @param int $base
45
     * @throws Exception
46
     */
47 8
    public function __construct($minimum = 0, $maximum = null, $base = 10)
48
    {
49 8
        if ($minimum !== null
50 8
            && $maximum !== null
51 8
            && $minimum > $maximum) {
52
53 1
            throw new \Exception('Maximum must be greater than minimum');
54
        }
55
56 7
        $this->setMinimum($minimum);
57 6
        $this->setMaximum($maximum);
58
59 5
        $this->base = intval($base);
60 5
        if ($base < 2
61 5
            || $base > strlen(self::$set)) {
62
63 2
            throw new \Exception('Unsupported base');
64
        }
65 3
    }
66
67
    /**
68
     * @param int|null $minimum
69
     * @throws Exception
70
     */
71 7
    private function setMinimum($minimum)
72
    {
73 7
        if ($minimum !== null
74 7
            && !is_int($minimum)) {
0 ignored issues
show
introduced by
The condition is_int($minimum) is always true.
Loading history...
75
76 1
            throw new Exception('Minimum must be integer or `null`');
77
        }
78
79 6
        $this->minimum = $minimum;
80 6
    }
81
82
    /**
83
     * @param int|null $maximum
84
     * @throws Exception
85
     */
86 6
    private function setMaximum($maximum)
87
    {
88 6
        if ($maximum !== null
89 6
            && !is_int($maximum)) {
0 ignored issues
show
introduced by
The condition is_int($maximum) is always true.
Loading history...
90
91 1
            throw new Exception('Maximum must be integer or `null`');
92
        }
93
94 5
        $this->maximum = $maximum;
95 5
    }
96
97 51
    private function isInRange($integer)
98
    {
99 51
        return ($this->minimum === null
100 51
                || $integer >= $this->minimum)
101 49
            && ($this->maximum === null
102 51
                || $integer <= $this->maximum);
103
    }
104
105
    /**
106
     * @param string $input
107
     * @param int $offset
108
     * @param Context $context
109
     * @return Failure|Success
110
     */
111 54
    protected function parse(&$input, $offset, Context $context)
112
    {
113 54
        $this->pushCaseSensitivityToContext($context);
114
115
        // Build pattern
116 54
        $set0    = substr(self::$set, 0, $this->base);
117 54
        $set1    = substr(self::$set, 1, $this->base - 1);
118 54
        $pattern = '/(?:0|-?[' . $set1 . '][' . $set0 . ']*)/A' . ($context->isCaseSensitive()
119 51
                ? ''
120 54
                : 'i');
121
122 54
        $this->popCaseSensitivityFromContext($context);
123
124 54
        if (preg_match($pattern, $input, $match, 0, $offset) === 1) {
125
            do {
126 51
                $integer = intval($match[0], $this->base);
127 51
                if ($this->isInRange($integer)
128 51
                    && $match[0] !== '-') {
129
130 40
                    return $this->success($input, $offset, mb_strlen($match[0]));
131
                }
132
133 18
                $match[0] = substr($match[0], 0, -1); // strip off last char
134 18
            } while ($match[0] !== '');
135
        }
136
137 14
        return $this->failure($input, $offset);
138
    }
139
140
    /**
141
     * @return string
142
     */
143 54
    public function __toString()
144
    {
145 54
        return ($this->minimum === null
146 7
                ? '<-INF'
147 54
                : ('[' . $this->minimum)) . ',' . ($this->maximum === null
148 14
                ? 'INF>'
149 54
                : ($this->maximum . ']'));
150
    }
151
152
}
153