Completed
Push — master ( 69b695...671bd7 )
by Kirill
06:49
created

PP2   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 8
dl 0
loc 97
ccs 0
cts 46
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A add() 0 9 2
B lex() 0 22 5
A include() 0 15 3
A make() 0 4 1
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\Grammar;
11
12
use Railt\Compiler\Exception\IncludeNotFoundException;
13
use Railt\Compiler\Exception\UnrecognizedTokenException;
14
use Railt\Compiler\Grammar\PP2\Lexer;
15
use Railt\Compiler\Grammar\PP2\Parser;
16
use Railt\Compiler\Reader\GrammarInterface;
17
use Railt\Compiler\Reader\Result;
18
use Railt\Io\File;
19
use Railt\Io\Readable;
20
use Railt\Lexer\LexerInterface;
21
use Railt\Lexer\Result\Eoi;
22
use Railt\Lexer\Result\Unknown;
23
use Railt\Lexer\TokenInterface;
24
25
/**
26
 * Class Grammar
27
 */
28
class PP2 implements GrammarInterface
29
{
30
    /**
31
     * @var LexerInterface
32
     */
33
    private $lexer;
34
35
    /**
36
     * @var PP2
37
     */
38
    private $parser;
39
40
    /**
41
     * Reader constructor.
42
     */
43
    public function __construct()
44
    {
45
        $this->lexer  = new Lexer();
46
        $this->parser = new Parser();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Railt\Compiler\Grammar\PP2\Parser() of type object<Railt\Compiler\Grammar\PP2\Parser> is incompatible with the declared type object<Railt\Compiler\Grammar\PP2> of property $parser.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
47
    }
48
49
    /**
50
     * @param Readable $input
51
     * @return GrammarInterface
52
     * @throws \Railt\Io\Exception\ExternalFileException
53
     * @throws \Railt\Io\Exception\NotReadableException
54
     */
55
    public function add(Readable $input): GrammarInterface
56
    {
57
        /** @var Readable $file */
58
        foreach ($this->lex($input) as $file => $token) {
59
            $this->parser->process($file, $token);
0 ignored issues
show
Bug introduced by
The method process() does not seem to exist on object<Railt\Compiler\Grammar\PP2>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
123
    }
124
}
125