Passed
Push — master ( 4344d4...81d6c9 )
by Martijn
02:43
created

Implementation   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 128
ccs 46
cts 46
cp 1
rs 10
c 0
b 0
f 0
wmc 19

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A build() 0 11 4
A __toString() 0 9 2
B parse() 0 35 9
A __get() 0 13 3
1
<?php
2
3
namespace Vanderlee\Comprehend\Builder;
4
5
use Exception;
6
use InvalidArgumentException;
7
use Vanderlee\Comprehend\Core\Context;
8
use Vanderlee\Comprehend\Match\Failure;
9
use Vanderlee\Comprehend\Match\Success;
10
use Vanderlee\Comprehend\Parser\Parser;
11
12
/**
13
 * Description of Factory
14
 *
15
 * @author Martijn
16
 */
17
class Implementation extends Parser
18
{
19
20
    /**
21
     * @var Parser|callable|null
22
     */
23
    private $parser = null;
24
25
    /**
26
     * @var callable|null
27
     */
28
    public $validator = null;
29
30
    /**
31
     * @var callable|null
32
     */
33
    public $processor    = null;
34
    public $processorKey = null;
35
36
    /**
37
     * @var Definition
38
     */
39
    private $definition = null;
40
    private $arguments  = null;
41
42
    /**
43
     * @param Definition $definition
44
     * @param array $arguments
45
     */
46 38
    public function __construct(Definition &$definition, array $arguments = [])
47
    {
48 38
        $this->definition = $definition;
49 38
        $this->arguments  = $arguments;
50 38
    }
51
52
    /**
53
     * @param $name
54
     * @return callable|null|Parser
55
     */
56 5
    public function __get($name)
57
    {
58 5
        if ($name === 'parser') {
59
            try {
60 4
                $this->build();
61 2
            } catch (Exception $exception) {
62 2
                $this->parser = null;
63
            }
64
65 4
            return $this->parser;
66
        }
67
68 1
        throw new InvalidArgumentException("Property `{$name}` does not exist");
69
    }
70
71
    /**
72
     * @throws \Exception
73
     */
74 167
    private function build()
75
    {
76 167
        if ($this->parser === null) {
77 163
            $this->parser = $this->definition->generator;
78 163
            if (!$this->parser instanceof Parser) {
79 18
                if (!is_callable($this->parser)) {
80 5
                    throw new Exception('Parser not defined');
81
                }
82
83 13
                $parser       = ($this->parser);
84 13
                $this->parser = $parser(...$this->arguments);
85
            }
86
        }
87 162
    }
88
89
    /**
90
     * @param string $input
91
     * @param int $offset
92
     * @param Context $context
93
     * @return Failure|Success
94
     * @throws Exception
95
     */
96 162
    protected function parse(&$input, $offset, Context $context)
97
    {
98 162
        $this->build();
99
100 160
        $match = $this->parser->parse($input, $offset, $context);
101
102 160
        $localResults = []; // this is redundant, but suppresses PHP scanner warnings
103 160
        if ($match instanceof Success) {
104 125
            $localResults = $match->results;
105 125
            foreach ($this->definition->validators as $validator) {
106 4
                if (!($validator(substr($input, $offset, $match->length), $localResults))) {
107 4
                    return $this->failure($input, $offset, $match->length);
108
                }
109
            }
110
        }
111
112
        // Copy match into new match, only pass original callbacks if processor not set
113 160
        $successes = empty($this->definition->processors)
114 159
            ? $match
115 160
            : [];
116 160
        $match     = ($match instanceof Success)
117 125
            ? $this->success($input, $offset, $match->length, $successes)
118 160
            : $this->failure($input, $offset, $match->length);
119
120 160
        if ($match instanceof Success
121 160
            && !empty($this->definition->processors)) {
122
123 1
            foreach ($this->definition->processors as $key => $processor) {
124 1
                $match->addResultCallback(function (&$results) use ($key, $processor, $localResults) {
125 1
                    $results[$key] = $processor($localResults, $results);
126 1
                });
127
            }
128
        }
129
130 160
        return $match;
131
    }
132
133
    /**
134
     * @return string
135
     */
136 132
    public function __toString()
137
    {
138
        try {
139 132
            $this->build();
140 1
        } catch (Exception $e) {
141
            // ignore
142
        }
143
144 132
        return (string)$this->parser;
145
    }
146
147
}
148