Completed
Push — master ( 04e24a...c0588a )
by Martijn
03:54 queued 38s
created

Implementation::__toString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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