Passed
Push — master ( 3a32ec...04e24a )
by Martijn
02:33
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 45
    public function __construct($parser, $min = 0, $max = null)
26
    {
27 45
        $this->parser = $this->getArgument($parser);
28 45
        $this->min    = $min;
29 45
        $this->max    = $max;
30
31 45
        if ($this->max !== null && $this->max < $this->min) {
32 1
            throw new \InvalidArgumentException('Invalid repeat range specified');
33
        }
34 44
    }
35
36 2
    public static function plus($parser)
37
    {
38 2
        return new self($parser, 1, null);
39
    }
40
41 2
    public static function star($parser)
42
    {
43 2
        return new self($parser, 0, null);
44
    }
45
46 2
    public static function optional($parser)
47
    {
48 2
        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 124
    protected function parse(&$input, $offset, Context $context)
57
    {
58 124
        $this->pushSpacer($context);
59
60 124
        $child_matches = [];
61
62 124
        $match  = null;
63 124
        $length = 0;
64
        do {
65
            // No skipping at very start
66 124
            $skip = $length > 0
67 86
                ? $context->skipSpacing($input, $offset + $length)
68 124
                : 0;
69 124
            if ($skip !== false) {
70 124
                $match = $this->parser->parse($input, $offset + $length + $skip, $context);
71 124
                if ($match instanceof Success) {
72 104
                    $length          += $skip + $match->length;
73 104
                    $child_matches[] = $match;
74
                }
75
            }
76 124
        } while ($skip !== false && $match->match && ($this->max == null || count($child_matches) < $this->max));
77
78 124
        $match = (count($child_matches) >= $this->min) && ($this->max == null || count($child_matches) <= $this->max);
79
80 124
        $this->popSpacer($context);
81
82 124
        return $match
83 110
            ? $this->success($input, $offset, $length, $child_matches)
84 124
            : $this->failure($input, $offset, $length);
85
    }
86
87 60
    public function __toString()
88
    {
89
        // Output ABNF formatting
90
91 60
        $min = $this->min > 0
92 51
            ? $this->min
93 60
            : '';
94 60
        $max = $this->max === null
95 21
            ? ''
96 60
            : $this->max;
97
98 60
        return ($min === $max
99 24
                ? $min
100 60
                : ($min . '*' . $max)) . $this->parser;
101
    }
102
103
}
104