Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types = 1);
2
namespace TheSeer\Tokenizer;
3
 
4
class Tokenizer {
5
 
6
    /**
7
     * Token Map for "non-tokens"
8
     *
9
     * @var array
10
     */
11
    private $map = [
12
        '(' => 'T_OPEN_BRACKET',
13
        ')' => 'T_CLOSE_BRACKET',
14
        '[' => 'T_OPEN_SQUARE',
15
        ']' => 'T_CLOSE_SQUARE',
16
        '{' => 'T_OPEN_CURLY',
17
        '}' => 'T_CLOSE_CURLY',
18
        ';' => 'T_SEMICOLON',
19
        '.' => 'T_DOT',
20
        ',' => 'T_COMMA',
21
        '=' => 'T_EQUAL',
22
        '<' => 'T_LT',
23
        '>' => 'T_GT',
24
        '+' => 'T_PLUS',
25
        '-' => 'T_MINUS',
26
        '*' => 'T_MULT',
27
        '/' => 'T_DIV',
28
        '?' => 'T_QUESTION_MARK',
29
        '!' => 'T_EXCLAMATION_MARK',
30
        ':' => 'T_COLON',
31
        '"' => 'T_DOUBLE_QUOTES',
32
        '@' => 'T_AT',
33
        '&' => 'T_AMPERSAND',
34
        '%' => 'T_PERCENT',
35
        '|' => 'T_PIPE',
36
        '$' => 'T_DOLLAR',
37
        '^' => 'T_CARET',
38
        '~' => 'T_TILDE',
39
        '`' => 'T_BACKTICK'
40
    ];
41
 
42
    public function parse(string $source): TokenCollection {
43
        $result = new TokenCollection();
44
 
45
        if ($source === '') {
46
            return $result;
47
        }
48
 
49
        $tokens = \token_get_all($source);
50
 
51
        $lastToken = new Token(
52
            $tokens[0][2],
53
            'Placeholder',
54
            ''
55
        );
56
 
57
        foreach ($tokens as $pos => $tok) {
58
            if (\is_string($tok)) {
59
                $token = new Token(
60
                    $lastToken->getLine(),
61
                    $this->map[$tok],
62
                    $tok
63
                );
64
                $result->addToken($token);
65
                $lastToken = $token;
66
 
67
                continue;
68
            }
69
 
70
            $line   = $tok[2];
71
            $values = \preg_split('/\R+/Uu', $tok[1]);
72
 
73
            foreach ($values as $v) {
74
                $token = new Token(
75
                    $line,
76
                    \token_name($tok[0]),
77
                    $v
78
                );
79
                $lastToken = $token;
80
                $line++;
81
 
82
                if ($v === '') {
83
                    continue;
84
                }
85
 
86
                $result->addToken($token);
87
            }
88
        }
89
 
90
        return $this->fillBlanks($result, $lastToken->getLine());
91
    }
92
 
93
    private function fillBlanks(TokenCollection $tokens, int $maxLine): TokenCollection {
94
        $prev = new Token(
95
            0,
96
            'Placeholder',
97
            ''
98
        );
99
 
100
        $final = new TokenCollection();
101
 
102
        foreach ($tokens as $token) {
103
            if ($prev === null) {
104
                $final->addToken($token);
105
                $prev = $token;
106
 
107
                continue;
108
            }
109
 
110
            $gap = $token->getLine() - $prev->getLine();
111
 
112
            while ($gap > 1) {
113
                $linebreak = new Token(
114
                    $prev->getLine() + 1,
115
                    'T_WHITESPACE',
116
                    ''
117
                );
118
                $final->addToken($linebreak);
119
                $prev = $linebreak;
120
                $gap--;
121
            }
122
 
123
            $final->addToken($token);
124
            $prev = $token;
125
        }
126
 
127
        $gap = $maxLine - $prev->getLine();
128
 
129
        while ($gap > 0) {
130
            $linebreak = new Token(
131
                $prev->getLine() + 1,
132
                'T_WHITESPACE',
133
                ''
134
            );
135
            $final->addToken($linebreak);
136
            $prev = $linebreak;
137
            $gap--;
138
        }
139
 
140
        return $final;
141
    }
142
}