Passed
Push — master ( 0651df...f8387b )
by Martijn
02:36
created

Repeat::plus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Vanderlee\Comprehend\Parser\Structure;
4
5
use Vanderlee\Comprehend\Core\Context;
6
use Vanderlee\Comprehend\Match\Success;
7
use Vanderlee\Comprehend\Parser\Parser;
8
9
/**
10
 * Description of RepeatParser
11
 *
12
 * @author Martijn
13
 */
14
class Repeat extends Parser
15
{
16
17
    use SpacingTrait;
18
19
    //use GreedyTrait;
20
21
    private $parser = null;
22
    private $min    = null;
23
    private $max    = null;
24
25 42
    public function __construct($parser, $min = 0, $max = null)
26
    {
27 42
        $this->parser = $this->getArgument($parser);
28 42
        $this->min    = $min;
29 42
        $this->max    = $max;
30
31 42
        if ($this->max !== null && $this->max < $this->min) {
32 1
            throw new \InvalidArgumentException('Invalid repeat range specified');
33
        }
34 41
    }
35
36 9
    public static function plus($parser)
37
    {
38 9
        return new self($parser, 1, null);
39
    }
40
41 9
    public static function star($parser)
42
    {
43 9
        return new self($parser, 0, null);
44
    }
45
46 9
    public static function optional($parser)
47
    {
48 9
        return new self($parser, 0, 1);
49
    }
50
51 1
    public static function exact($parser, $times)
52
    {
53 1
        return new self($parser, $times, $times);
54
    }
55
56 150
    protected function parse(&$input, $offset, Context $context)
57
    {
58
59 150
        $childMatches = [];
60
61 150
        $this->pushSpacer($context);
62
63 150
        $length = 0;
64
        do {
65
            // No skipping at very start
66 150
            $skip = $length > 0
67 104
                ? $context->skipSpacing($input, $offset + $length)
68 150
                : 0;
69
70 150
            if ($skip === false) {
71 1
                break;
72
            }
73
74 150
            $match = $this->parser->parse($input, $offset + $length + $skip, $context);
75 150
            if ($match instanceof Success) {
76 125
                $length         += $skip + $match->length;
77 125
                $childMatches[] = $match;
78
            }
79 150
        } while (($match instanceof Success)
80 125
        && ($this->max === null
81 150
            || count($childMatches) < $this->max));
82
83 150
        $this->popSpacer($context);
84
85 150
        return count($childMatches) >= $this->min
86 133
            ? $this->success($input, $offset, $length, $childMatches)
87 150
            : $this->failure($input, $offset, $length);
88
    }
89
90 90
    public function __toString()
91
    {
92
        // Output ABNF formatting
93
94 90
        $min = $this->min > 0
95 70
            ? $this->min
96 90
            : '';
97 90
        $max = $this->max === null
98 44
            ? ''
99 90
            : $this->max;
100
101 90
        return ($min === $max
102 42
                ? $min
103 90
                : ($min . '*' . $max)) . $this->parser;
104
    }
105
106
}
107