Passed
Push — master ( e44dc3...5dec7d )
by Kirill
07:30
created

Reader   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 8
dl 0
loc 94
c 0
b 0
f 0
ccs 0
cts 42
cp 0
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A read() 0 11 2
B lex() 0 22 5
A include() 0 15 3
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Compiler;
11
12
use Railt\Compiler\Exception\IncludeNotFoundException;
13
use Railt\Compiler\Exception\UnrecognizedTokenException;
14
use Railt\Compiler\Reader\Parser;
15
use Railt\Io\File;
16
use Railt\Io\Readable;
17
use Railt\Lexer\LexerInterface;
18
use Railt\Lexer\Result\Eoi;
19
use Railt\Lexer\Result\Unknown;
20
use Railt\Lexer\TokenInterface;
21
22
/**
23
 * Class Reader
24
 */
25
class Reader
26
{
27
    /**
28
     * File extensions list
29
     */
30
    private const FILE_EXTENSIONS = [
31
        '',
32
        '.pp',
33
        '.pp2',
34
    ];
35
36
    /**
37
     * @var LexerInterface
38
     */
39
    private $lexer;
40
41
    /**
42
     * Reader constructor.
43
     */
44
    public function __construct()
45
    {
46
        $this->lexer = new Lexer();
47
    }
48
49
    /**
50
     * @param Readable $input
51
     * @return ParsingResult
52
     * @throws \Railt\Io\Exception\NotReadableException
53
     * @throws \Railt\Io\Exception\ExternalFileException
54
     */
55
    public function read(Readable $input): ParsingResult
56
    {
57
        $parser = new Parser();
58
59
        /** @var Readable $file */
60
        foreach ($this->lex($input) as $file => $token) {
61
            $parser->process($file, $token);
0 ignored issues
show
Documentation introduced by
$file is of type integer|string, but the function expects a object<Railt\Io\Readable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
62
        }
63
64
        return $parser->getResult();
65
    }
66
67
    /**
68
     * @param Readable $input
69
     * @return \Traversable
70
     * @throws \Railt\Io\Exception\NotReadableException
71
     * @throws \Railt\Io\Exception\ExternalFileException
72
     */
73
    private function lex(Readable $input): \Traversable
74
    {
75
        $tokens = $this->lexer->lex($input);
76
77
        foreach ($tokens as $token) {
78
            if ($token instanceof Unknown) {
79
                $error = \sprintf('Unrecognized token "%s" (%s)', $token->value(), $token->name());
80
                throw (new UnrecognizedTokenException($error))->throwsIn($input, $token->offset());
81
            }
82
83
            if ($token instanceof Eoi) {
84
                continue;
85
            }
86
87
            if ($token->name() === Lexer::T_INCLUDE) {
88
                yield from $this->lex($this->include($input, $token));
89
                continue;
90
            }
91
92
            yield $input => $token;
93
        }
94
    }
95
96
    /**
97
     * @param Readable $from
98
     * @param TokenInterface $token
99
     * @return Readable
100
     * @throws \Railt\Io\Exception\NotReadableException
101
     * @throws \Railt\Io\Exception\ExternalFileException
102
     */
103
    private function include(Readable $from, TokenInterface $token): Readable
104
    {
105
        $path = \trim($token->value(1), " \t\n\r\0\x0B\"'");
106
107
        foreach (self::FILE_EXTENSIONS as $extension) {
108
            $file = \dirname($from->getPathname()) . '/' . $path . $extension;
109
110
            if (\is_file($file)) {
111
                return File::fromPathname($file);
112
            }
113
        }
114
115
        $error = \sprintf('Could not read external grammar file "%s"', $path);
116
        throw (new IncludeNotFoundException($error))->throwsIn($from, $token->offset());
117
    }
118
}
119