Completed
Push — master ( 8418b3...91ec6e )
by
unknown
13s queued 11s
created

Source/Language/PHP/PHPTokenizerInternal.php (1 issue)

Check for PhpDoc comments which do parse

Documentation Minor

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * This file is part of PDepend.
4
 *
5
 * PHP Version 5
6
 *
7
 * Copyright (c) 2008-2017 Manuel Pichler <[email protected]>.
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 *   * Redistributions of source code must retain the above copyright
15
 *     notice, this list of conditions and the following disclaimer.
16
 *
17
 *   * Redistributions in binary form must reproduce the above copyright
18
 *     notice, this list of conditions and the following disclaimer in
19
 *     the documentation and/or other materials provided with the
20
 *     distribution.
21
 *
22
 *   * Neither the name of Manuel Pichler nor the names of his
23
 *     contributors may be used to endorse or promote products derived
24
 *     from this software without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
 * POSSIBILITY OF SUCH DAMAGE.
38
 *
39
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
40
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
41
 */
42
43
namespace PDepend\Source\Language\PHP;
44
45
use PDepend\Source\AST\ASTCompilationUnit;
46
use PDepend\Source\Tokenizer\Token;
47
use PDepend\Source\Tokenizer\Tokenizer;
48
use PDepend\Source\Tokenizer\Tokens;
49
50
/**
51
 * Define PHP 5.4 __TRAIT__ token constant.
52
 */
53
if (!defined('T_TRAIT_C')) {
54
    define('T_TRAIT_C', 42000);
55
}
56
57
/**
58
 * Define PHP 5.4 'trait' token constant.
59
 */
60
if (!defined('T_TRAIT')) {
61
    define('T_TRAIT', 42001);
62
}
63
64
/**
65
 * Define PHP 5.4 'insteadof' token constant.
66
 */
67
if (!defined('T_INSTEADOF')) {
68
    define('T_INSTEADOF', 42002);
69
}
70
71
/**
72
 * Define PHP 5.3 __NAMESPACE__ token constant.
73
 */
74
if (!defined('T_NS_C')) {
75
    define('T_NS_C', 42003);
76
}
77
78
/**
79
 * Define PHP 5.3 'use' token constant
80
 */
81
if (!defined('T_USE')) {
82
    define('T_USE', 42004);
83
}
84
85
/**
86
 * Define PHP 5.3 'namespace' token constant.
87
 */
88
if (!defined('T_NAMESPACE')) {
89
    define('T_NAMESPACE', 42005);
90
}
91
92
/**
93
 * Define PHP 5.6 '...' token constant
94
 */
95
if (!defined('T_ELLIPSIS')) {
96
    define('T_ELLIPSIS', 42006);
97
}
98
99
/**
100
 * Define PHP 5.3's '__DIR__' token constant.
101
 */
102
if (!defined('T_DIR')) {
103
    define('T_DIR', 42006);
104
}
105
106
/**
107
 * Define PHP 5.3's 'T_GOTO' token constant.
108
 */
109
if (!defined('T_GOTO')) {
110
    define('T_GOTO', 42007);
111
}
112
113
/**
114
 * Define PHP 5.4's 'T_CALLABLE' token constant
115
 */
116
if (!defined('T_CALLABLE')) {
117
    define('T_CALLABLE', 42008);
118
}
119
120
/**
121
 * Define PHP 5.5's 'T_YIELD' token constant
122
 */
123
if (!defined('T_YIELD')) {
124
    define('T_YIELD', 42009);
125
}
126
127
/**
128
 * Define PHP 5,5's 'T_FINALLY' token constant
129
 */
130
if (!defined('T_FINALLY')) {
131
    define('T_FINALLY', 42010);
132
}
133
134
/**
135
 * Define character token that was removed in PHP 7
136
 */
137
if (!defined('T_CHARACTER')) {
138
    define('T_CHARACTER', 42011);
139
}
140
141
/**
142
 * Define bad character token that was removed in PHP 7
143
 */
144
if (!defined('T_BAD_CHARACTER')) {
145
    define('T_BAD_CHARACTER', 42012);
146
}
147
148
/**
149
 * Define PHP 7's '<=>' token constant
150
 */
151
if (!defined('T_SPACESHIP')) {
152
    define('T_SPACESHIP', 42013);
153
}
154
155
/**
156
 * Define PHP 7's '??' token constant
157
 */
158
if (!defined('T_COALESCE')) {
159
    define('T_COALESCE', 42014);
160
}
161
162
/**
163
 * Define PHP 7's '**' token constant
164
 */
165
if (!defined('T_POW')) {
166
    define('T_POW', 42015);
167
}
168
169
/**
170
 * This tokenizer uses the internal {@link token_get_all()} function as token stream
171
 * generator.
172
 *
173
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
174
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
175
 */
176
class PHPTokenizerInternal implements Tokenizer
177
{
178
    /**
179
     * Mapping between php internal tokens and php depend tokens.
180
     *
181
     * @var array<integer, integer>
182
     */
183
    protected static $tokenMap = array(
184
        T_AS                        =>  Tokens::T_AS,
185
        T_DO                        =>  Tokens::T_DO,
186
        T_IF                        =>  Tokens::T_IF,
187
        T_SL                        =>  Tokens::T_SL,
188
        T_SR                        =>  Tokens::T_SR,
189
        T_DEC                       =>  Tokens::T_DEC,
190
        T_FOR                       =>  Tokens::T_FOR,
191
        T_INC                       =>  Tokens::T_INC,
192
        T_NEW                       =>  Tokens::T_NEW,
193
        T_POW                       =>  Tokens::T_POW,
194
        T_TRY                       =>  Tokens::T_TRY,
195
        T_USE                       =>  Tokens::T_USE,
196
        T_VAR                       =>  Tokens::T_VAR,
197
        T_CASE                      =>  Tokens::T_CASE,
198
        T_ECHO                      =>  Tokens::T_ECHO,
199
        T_ELSE                      =>  Tokens::T_ELSE,
200
        T_EVAL                      =>  Tokens::T_EVAL,
201
        T_EXIT                      =>  Tokens::T_EXIT,
202
        T_FILE                      =>  Tokens::T_FILE,
203
        T_GOTO                      =>  Tokens::T_GOTO,
204
        T_LINE                      =>  Tokens::T_LINE,
205
        T_LIST                      =>  Tokens::T_LIST,
206
        T_NS_C                      =>  Tokens::T_NS_C,
207
        T_ARRAY                     =>  Tokens::T_ARRAY,
208
        T_BREAK                     =>  Tokens::T_BREAK,
209
        T_CLASS                     =>  Tokens::T_CLASS,
210
        T_CATCH                     =>  Tokens::T_CATCH,
211
        T_CLONE                     =>  Tokens::T_CLONE,
212
        T_CONST                     =>  Tokens::T_CONST,
213
        T_EMPTY                     =>  Tokens::T_EMPTY,
214
        T_ENDIF                     =>  Tokens::T_ENDIF,
215
        T_FINAL                     =>  Tokens::T_FINAL,
216
        T_ISSET                     =>  Tokens::T_ISSET,
217
        T_PRINT                     =>  Tokens::T_PRINT,
218
        T_THROW                     =>  Tokens::T_THROW,
219
        T_TRAIT                     =>  Tokens::T_TRAIT,
220
        T_UNSET                     =>  Tokens::T_UNSET,
221
        T_WHILE                     =>  Tokens::T_WHILE,
222
        T_ENDFOR                    =>  Tokens::T_ENDFOR,
223
        T_ELSEIF                    =>  Tokens::T_ELSEIF,
224
        T_FUNC_C                    =>  Tokens::T_FUNC_C,
225
        T_GLOBAL                    =>  Tokens::T_GLOBAL,
226
        T_PUBLIC                    =>  Tokens::T_PUBLIC,
227
        T_RETURN                    =>  Tokens::T_RETURN,
228
        T_STATIC                    =>  Tokens::T_STATIC,
229
        T_STRING                    =>  Tokens::T_STRING,
230
        T_SWITCH                    =>  Tokens::T_SWITCH,
231
        T_CLASS_C                   =>  Tokens::T_CLASS_C,
232
        T_COMMENT                   =>  Tokens::T_COMMENT,
233
        T_DECLARE                   =>  Tokens::T_DECLARE,
234
        T_DEFAULT                   =>  Tokens::T_DEFAULT,
235
        T_DNUMBER                   =>  Tokens::T_DNUMBER,
236
        T_EXTENDS                   =>  Tokens::T_EXTENDS,
237
        T_FOREACH                   =>  Tokens::T_FOREACH,
238
        T_INCLUDE                   =>  Tokens::T_INCLUDE,
239
        T_LNUMBER                   =>  Tokens::T_LNUMBER,
240
        T_PRIVATE                   =>  Tokens::T_PRIVATE,
241
        T_REQUIRE                   =>  Tokens::T_REQUIRE,
242
        T_TRAIT_C                   =>  Tokens::T_TRAIT_C,
243
        T_ABSTRACT                  =>  Tokens::T_ABSTRACT,
244
        T_CALLABLE                  =>  Tokens::T_CALLABLE,
245
        T_ENDWHILE                  =>  Tokens::T_ENDWHILE,
246
        T_FUNCTION                  =>  Tokens::T_FUNCTION,
247
        T_INT_CAST                  =>  Tokens::T_INT_CAST,
248
        T_IS_EQUAL                  =>  Tokens::T_IS_EQUAL,
249
        T_OR_EQUAL                  =>  Tokens::T_OR_EQUAL,
250
        T_CONTINUE                  =>  Tokens::T_CONTINUE,
251
        T_METHOD_C                  =>  Tokens::T_METHOD_C,
252
        T_ELLIPSIS                  =>  Tokens::T_ELLIPSIS,
253
        T_OPEN_TAG                  =>  Tokens::T_OPEN_TAG,
254
        T_SL_EQUAL                  =>  Tokens::T_SL_EQUAL,
255
        T_SR_EQUAL                  =>  Tokens::T_SR_EQUAL,
256
        T_VARIABLE                  =>  Tokens::T_VARIABLE,
257
        T_ENDSWITCH                 =>  Tokens::T_ENDSWITCH,
258
        T_DIV_EQUAL                 =>  Tokens::T_DIV_EQUAL,
259
        T_AND_EQUAL                 =>  Tokens::T_AND_EQUAL,
260
        T_MOD_EQUAL                 =>  Tokens::T_MOD_EQUAL,
261
        T_MUL_EQUAL                 =>  Tokens::T_MUL_EQUAL,
262
        T_NAMESPACE                 =>  Tokens::T_NAMESPACE,
263
        T_XOR_EQUAL                 =>  Tokens::T_XOR_EQUAL,
264
        T_INTERFACE                 =>  Tokens::T_INTERFACE,
265
        T_BOOL_CAST                 =>  Tokens::T_BOOL_CAST,
266
        T_CHARACTER                 =>  Tokens::T_CHARACTER,
267
        T_CLOSE_TAG                 =>  Tokens::T_CLOSE_TAG,
268
        T_INSTEADOF                 =>  Tokens::T_INSTEADOF,
269
        T_PROTECTED                 =>  Tokens::T_PROTECTED,
270
        T_SPACESHIP                 =>  Tokens::T_SPACESHIP,
271
        T_CURLY_OPEN                =>  Tokens::T_CURLY_BRACE_OPEN,
272
        T_ENDFOREACH                =>  Tokens::T_ENDFOREACH,
273
        T_ENDDECLARE                =>  Tokens::T_ENDDECLARE,
274
        T_IMPLEMENTS                =>  Tokens::T_IMPLEMENTS,
275
        T_NUM_STRING                =>  Tokens::T_NUM_STRING,
276
        T_PLUS_EQUAL                =>  Tokens::T_PLUS_EQUAL,
277
        T_ARRAY_CAST                =>  Tokens::T_ARRAY_CAST,
278
        T_BOOLEAN_OR                =>  Tokens::T_BOOLEAN_OR,
279
        T_INSTANCEOF                =>  Tokens::T_INSTANCEOF,
280
        T_LOGICAL_OR                =>  Tokens::T_LOGICAL_OR,
281
        T_UNSET_CAST                =>  Tokens::T_UNSET_CAST,
282
        T_DOC_COMMENT               =>  Tokens::T_DOC_COMMENT,
283
        T_END_HEREDOC               =>  Tokens::T_END_HEREDOC,
284
        T_MINUS_EQUAL               =>  Tokens::T_MINUS_EQUAL,
285
        T_BOOLEAN_AND               =>  Tokens::T_BOOLEAN_AND,
286
        T_DOUBLE_CAST               =>  Tokens::T_DOUBLE_CAST,
287
        T_INLINE_HTML               =>  Tokens::T_INLINE_HTML,
288
        T_LOGICAL_AND               =>  Tokens::T_LOGICAL_AND,
289
        T_LOGICAL_XOR               =>  Tokens::T_LOGICAL_XOR,
290
        T_OBJECT_CAST               =>  Tokens::T_OBJECT_CAST,
291
        T_STRING_CAST               =>  Tokens::T_STRING_CAST,
292
        T_DOUBLE_ARROW              =>  Tokens::T_DOUBLE_ARROW,
293
        T_INCLUDE_ONCE              =>  Tokens::T_INCLUDE_ONCE,
294
        T_IS_IDENTICAL              =>  Tokens::T_IS_IDENTICAL,
295
        T_DOUBLE_COLON              =>  Tokens::T_DOUBLE_COLON,
296
        T_CONCAT_EQUAL              =>  Tokens::T_CONCAT_EQUAL,
297
        T_IS_NOT_EQUAL              =>  Tokens::T_IS_NOT_EQUAL,
298
        T_REQUIRE_ONCE              =>  Tokens::T_REQUIRE_ONCE,
299
        T_BAD_CHARACTER             =>  Tokens::T_BAD_CHARACTER,
300
        T_HALT_COMPILER             =>  Tokens::T_HALT_COMPILER,
301
        T_START_HEREDOC             =>  Tokens::T_START_HEREDOC,
302
        T_STRING_VARNAME            =>  Tokens::T_STRING_VARNAME,
303
        T_OBJECT_OPERATOR           =>  Tokens::T_OBJECT_OPERATOR,
304
        T_IS_NOT_IDENTICAL          =>  Tokens::T_IS_NOT_IDENTICAL,
305
        T_OPEN_TAG_WITH_ECHO        =>  Tokens::T_OPEN_TAG_WITH_ECHO,
306
        T_IS_GREATER_OR_EQUAL       =>  Tokens::T_IS_GREATER_OR_EQUAL,
307
        T_IS_SMALLER_OR_EQUAL       =>  Tokens::T_IS_SMALLER_OR_EQUAL,
308
        //T_PAAMAYIM_NEKUDOTAYIM      =>  Tokens::T_DOUBLE_COLON,
309
        T_ENCAPSED_AND_WHITESPACE   =>  Tokens::T_ENCAPSED_AND_WHITESPACE,
310
        T_CONSTANT_ENCAPSED_STRING  =>  Tokens::T_CONSTANT_ENCAPSED_STRING,
311
        T_YIELD                     =>  Tokens::T_YIELD,
312
        T_FINALLY                   =>  Tokens::T_FINALLY,
313
        T_COALESCE                  =>  Tokens::T_COALESCE,
314
        //T_DOLLAR_OPEN_CURLY_BRACES  =>  Tokens::T_CURLY_BRACE_OPEN,
315
    );
316
317
    /**
318
     * Internally used transition token.
319
     */
320
    const T_ELLIPSIS = 23006;
321
322
    /**
323
     * Mapping between php internal text tokens an php depend numeric tokens.
324
     *
325
     * @var array<string, integer>
326
     */
327
    protected static $literalMap = array(
328
        '@'              =>  Tokens::T_AT,
329
        '/'              =>  Tokens::T_DIV,
330
        '%'              =>  Tokens::T_MOD,
331
        '*'              =>  Tokens::T_MUL,
332
        '+'              =>  Tokens::T_PLUS,
333
        ':'              =>  Tokens::T_COLON,
334
        ','              =>  Tokens::T_COMMA,
335
        '='              =>  Tokens::T_EQUAL,
336
        '-'              =>  Tokens::T_MINUS,
337
        '.'              =>  Tokens::T_CONCAT,
338
        '$'              =>  Tokens::T_DOLLAR,
339
        '`'              =>  Tokens::T_BACKTICK,
340
        '\\'             =>  Tokens::T_BACKSLASH,
341
        ';'              =>  Tokens::T_SEMICOLON,
342
        '|'              =>  Tokens::T_BITWISE_OR,
343
        '&'              =>  Tokens::T_BITWISE_AND,
344
        '~'              =>  Tokens::T_BITWISE_NOT,
345
        '^'              =>  Tokens::T_BITWISE_XOR,
346
        '"'              =>  Tokens::T_DOUBLE_QUOTE,
347
        '?'              =>  Tokens::T_QUESTION_MARK,
348
        '!'              =>  Tokens::T_EXCLAMATION_MARK,
349
        '{'              =>  Tokens::T_CURLY_BRACE_OPEN,
350
        '}'              =>  Tokens::T_CURLY_BRACE_CLOSE,
351
        '('              =>  Tokens::T_PARENTHESIS_OPEN,
352
        ')'              =>  Tokens::T_PARENTHESIS_CLOSE,
353
        '<'              =>  Tokens::T_ANGLE_BRACKET_OPEN,
354
        '>'              =>  Tokens::T_ANGLE_BRACKET_CLOSE,
355
        '['              =>  Tokens::T_SQUARED_BRACKET_OPEN,
356
        ']'              =>  Tokens::T_SQUARED_BRACKET_CLOSE,
357
        'use'            =>  Tokens::T_USE,
358
        'goto'           =>  Tokens::T_GOTO,
359
        'null'           =>  Tokens::T_NULL,
360
        'self'           =>  Tokens::T_SELF,
361
        'true'           =>  Tokens::T_TRUE,
362
        'array'          =>  Tokens::T_ARRAY,
363
        'false'          =>  Tokens::T_FALSE,
364
        'trait'          =>  Tokens::T_TRAIT,
365
        'yield'          =>  Tokens::T_YIELD,
366
        'yield from'     =>  Tokens::T_YIELD,
367
        'parent'         =>  Tokens::T_PARENT,
368
        'finally'        =>  Tokens::T_FINALLY,
369
        'callable'       =>  Tokens::T_CALLABLE,
370
        'insteadof'      =>  Tokens::T_INSTEADOF,
371
        'namespace'      =>  Tokens::T_NAMESPACE,
372
        '__dir__'        =>  Tokens::T_DIR,
373
        '__trait__'      =>  Tokens::T_TRAIT_C,
374
        '__namespace__'  =>  Tokens::T_NS_C,
375
    );
376
377
    /**
378
     *
379
     * @var array<mixed, array>
380
     */
381
    protected static $substituteTokens = array(
382
        T_DOLLAR_OPEN_CURLY_BRACES  =>  array('$', '{'),
383
    );
384
385
    /**
386
     * BuilderContext sensitive alternative mappings.
387
     *
388
     * @var array<integer, array>
389
     */
390
    protected static $alternativeMap = array(
391
        Tokens::T_USE => array(
392
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
393
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
394
            Tokens::T_CONST            =>  Tokens::T_STRING,
395
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
396
        ),
397
398
        Tokens::T_GOTO => array(
399
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
400
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
401
            Tokens::T_CONST            =>  Tokens::T_STRING,
402
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
403
        ),
404
405
        Tokens::T_NULL => array(
406
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
407
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
408
            Tokens::T_CONST            =>  Tokens::T_STRING,
409
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
410
        ),
411
412
        Tokens::T_SELF => array(
413
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
414
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
415
            Tokens::T_CONST            =>  Tokens::T_STRING,
416
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
417
        ),
418
419
        Tokens::T_TRUE => array(
420
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
421
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
422
            Tokens::T_NAMESPACE        =>  Tokens::T_STRING,
423
            Tokens::T_CONST            =>  Tokens::T_STRING,
424
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
425
        ),
426
427
        Tokens::T_ARRAY => array(
428
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
429
        ),
430
431
        Tokens::T_FALSE => array(
432
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
433
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
434
            Tokens::T_NAMESPACE        =>  Tokens::T_STRING,
435
            Tokens::T_CONST            =>  Tokens::T_STRING,
436
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
437
        ),
438
439
        Tokens::T_NAMESPACE => array(
440
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
441
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
442
            Tokens::T_CONST            =>  Tokens::T_STRING,
443
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
444
        ),
445
446
        Tokens::T_DIR => array(
447
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
448
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
449
            Tokens::T_CONST            =>  Tokens::T_STRING,
450
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
451
        ),
452
453
        Tokens::T_NS_C => array(
454
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
455
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
456
            Tokens::T_CONST            =>  Tokens::T_STRING,
457
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
458
        ),
459
460
        Tokens::T_PARENT => array(
461
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
462
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
463
            Tokens::T_CONST            =>  Tokens::T_STRING,
464
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
465
        ),
466
467
        Tokens::T_FINALLY => array(
468
            Tokens::T_OBJECT_OPERATOR  =>  Tokens::T_STRING,
469
            Tokens::T_DOUBLE_COLON     =>  Tokens::T_STRING,
470
            Tokens::T_CONST            =>  Tokens::T_STRING,
471
            Tokens::T_FUNCTION         =>  Tokens::T_STRING,
472
        ),
473
474
        Tokens::T_CALLABLE => array(
475
            Tokens::T_OBJECT_OPERATOR  => Tokens::T_STRING,
476
            Tokens::T_DOUBLE_COLON     => Tokens::T_STRING,
477
        ),
478
479
        Tokens::T_LIST => array(
480
            Tokens::T_OBJECT_OPERATOR  => Tokens::T_STRING,
481
            Tokens::T_DOUBLE_COLON     => Tokens::T_STRING,
482
        ),
483
484
        Tokens::T_EMPTY => array(
485
            Tokens::T_OBJECT_OPERATOR  => Tokens::T_STRING,
486
            Tokens::T_DOUBLE_COLON     => Tokens::T_STRING,
487
        ),
488
489
        Tokens::T_CLASS => array(
490
            Tokens::T_DOUBLE_COLON     => Tokens::T_CLASS_FQN,
491
        ),
492
    );
493
494
    protected static $reductionMap = array(
495
        Tokens::T_CONCAT => array(
496
            Tokens::T_CONCAT => array(
497
                'type'  => self::T_ELLIPSIS,
498
                'image' => '..',
499
            ),
500
            self::T_ELLIPSIS  =>  array(
501
                'type'  => Tokens::T_ELLIPSIS,
502
                'image' => '...',
503
            )
504
        ),
505
506
        Tokens::T_ANGLE_BRACKET_CLOSE => array(
507
            Tokens::T_IS_SMALLER_OR_EQUAL => array(
508
                'type'  => Tokens::T_SPACESHIP,
509
                'image' => '<=>',
510
            )
511
        ),
512
513
        Tokens::T_QUESTION_MARK => array(
514
            Tokens::T_QUESTION_MARK => array(
515
                'type'  => Tokens::T_COALESCE,
516
                'image' => '??',
517
            )
518
        ),
519
520
        Tokens::T_MUL => array(
521
            Tokens::T_MUL => array(
522
                'type'  => Tokens::T_POW,
523
                'image' => '**',
524
            )
525
        ),
526
    );
527
528
    /**
529
     * The source file instance.
530
     *
531
     * @var \PDepend\Source\AST\ASTCompilationUnit
532
     */
533
    protected $sourceFile = '';
534
535
    /**
536
     * Count of all tokens.
537
     *
538
     * @var integer
539
     */
540
    protected $count = 0;
541
542
    /**
543
     * Internal stream pointer index.
544
     *
545
     * @var integer
546
     */
547
    protected $index = 0;
548
549
    /**
550
     * Prepared token list.
551
     *
552
     * @var Token[]|null
553
     */
554
    protected $tokens = null;
555
556
    /**
557
     * The next free identifier for unknown string tokens.
558
     *
559
     * @var integer
560
     */
561
    private $unknownTokenID = 1000;
562
563
    /**
564
     * Returns the name of the source file.
565
     *
566
     * @return \PDepend\Source\AST\ASTCompilationUnit
567
     */
568
    public function getSourceFile()
569
    {
570
        return $this->sourceFile;
571
    }
572
573
    /**
574
     * Sets a new php source file.
575
     *
576
     * @param string $sourceFile A php source file.
577
     *
578
     * @return void
579
     */
580 28
    public function setSourceFile($sourceFile)
581
    {
582 28
        $this->tokens = null;
583 28
        $this->sourceFile = new ASTCompilationUnit($sourceFile);
584 28
    }
585
586
    /**
587
     * Returns the next token or {@link \PDepend\Source\Tokenizer\Tokenizer::T_EOF} if
588
     * there is no next token.
589
     *
590
     * @return Token|integer
591
     */
592 26 View Code Duplication
    public function next()
593
    {
594 26
        $this->tokenize();
595
596 26
        if ($this->index < $this->count) {
597 26
            return $this->tokens[$this->index++];
598
        }
599 26
        return self::T_EOF;
600
    }
601
602
    /**
603
     * Returns the next token type or {@link \PDepend\Source\Tokenizer\Tokenizer::T_EOF} if
604
     * there is no next token.
605
     *
606
     * @return integer
607
     */
608 View Code Duplication
    public function peek()
609
    {
610
        $this->tokenize();
611
612
        if (isset($this->tokens[$this->index])) {
613
            return $this->tokens[$this->index]->type;
614
        }
615
        return self::T_EOF;
616
    }
617
618
    /**
619
     * Returns the type of next token, after the current token. This method
620
     * ignores all comments between the current and the next token.
621
     *
622
     * @return integer
623
     * @since  0.9.12
624
     */
625
    public function peekNext()
626
    {
627
        $this->tokenize();
628
        
629
        $offset = 0;
630
        do {
631
            $type = $this->tokens[$this->index + ++$offset]->type;
632
        } while ($type == Tokens::T_COMMENT || $type == Tokens::T_DOC_COMMENT);
633
        return $type;
634
    }
635
636
    /**
637
     * Returns the previous token type or {@link \PDepend\Source\Tokenizer\Tokenizer::T_BOF}
638
     * if there is no previous token.
639
     *
640
     * @return integer
641
     */
642 2 View Code Duplication
    public function prev()
643
    {
644 2
        $this->tokenize();
645
646 2
        if ($this->index > 1) {
647
            return $this->tokens[$this->index - 2]->type;
648
        }
649 2
        return self::T_BOF;
650
    }
651
652
    /**
653
     * This method takes an array of tokens returned by <b>token_get_all()</b>
654
     * and substitutes some of the tokens with those required by PDepend's
655
     * parser implementation.
656
     *
657
     * @param array<array> $tokens Unprepared array of php tokens.
658
     *
659
     * @return array<array>
660
     */
661 28
    private function substituteTokens(array $tokens)
662
    {
663 28
        $result = array();
664 28
        foreach ($tokens as $token) {
665 28
            $temp = (array) $token;
666 28
            $temp = $temp[0];
667 28
            if (isset(self::$substituteTokens[$temp])) {
668
                foreach (self::$substituteTokens[$temp] as $token) {
669
                    $result[] = $token;
670
                }
671
            } else {
672 28
                $result[] = $token;
673
            }
674 28
        }
675 28
        return $result;
676
    }
677
678
    /**
679
     * Tokenizes the content of the source file with {@link token_get_all()} and
680
     * filters this token stream.
681
     *
682
     * @return void
683
     */
684 28
    private function tokenize()
685
    {
686 28
        if ($this->tokens !== null) {
687 26
            return;
688
        }
689
690 28
        $this->tokens = array();
691 28
        $this->index  = 0;
692 28
        $this->count  = 0;
693
694
        // Replace short open tags, short open tags will produce invalid results
695
        // in all environments with disabled short open tags.
696 28
        $source = $this->sourceFile->getSource();
697 28
        $source = preg_replace(
698 28
            array('(<\?=)', '(<\?(\s))'),
699 28
            array('<?php echo ', '<?php\1'),
700
            $source
701 28
        );
702
703 28
        if (version_compare(phpversion(), '5.3.0alpha3') < 0) {
704
            $tokens = PHPTokenizerHelperVersion52::tokenize($source);
705
        } else {
706 28
            $tokens = token_get_all($source);
707
        }
708
709 28
        $tokens = $this->substituteTokens($tokens);
710
711
        // Is the current token between an opening and a closing php tag?
712 28
        $inTag = false;
713
714
        // The current line number
715 28
        $startLine = 1;
716
717 28
        $startColumn = 1;
718 28
        $endColumn   = 1;
719
720 28
        $literalMap = self::$literalMap;
721 28
        $tokenMap   = self::$tokenMap;
722
723
        // Previous found type
724 28
        $previousType = null;
725 28
        $previousStartColumn = 0;
726
727 28
        while ($token = current($tokens)) {
728 28
            $type  = null;
729 28
            $image = null;
730
731 28
            if (is_string($token)) {
732 28
                $token = array(null, $token);
733 28
            }
734
735 28
            if ($token[0] === T_OPEN_TAG) {
736 28
                $type  = $tokenMap[$token[0]];
737 28
                $image = $token[1];
738 28
                $inTag = true;
739 28
            } elseif ($token[0] === T_CLOSE_TAG) {
740 12
                $type  = $tokenMap[$token[0]];
741 12
                $image = $token[1];
742 12
                $inTag = false;
743 28
            } elseif ($inTag === false) {
744 6
                $type  = Tokens::T_NO_PHP;
745 6
                $image = $this->consumeNonePhpTokens($tokens);
746 28
            } elseif ($token[0] === T_WHITESPACE) {
747
                // Count newlines in token
748 26
                $lines = substr_count($token[1], "\n");
749 26
                if ($lines === 0) {
750 24
                    $startColumn += strlen($token[1]);
751 24
                } else {
752 20
                    $startColumn = strlen(
753 20
                        substr($token[1], strrpos($token[1], "\n") + 1)
754 20
                    ) + 1;
755
                }
756
757 26
                $startLine += $lines;
758 26
            } else {
759 28
                $value = strtolower($token[1]);
760 28
                if (isset($literalMap[$value])) {
761
                    // Fetch literal type
762 28
                    $type = $literalMap[$value];
763 28
                    $image = $token[1];
764
765
                    // Check for a context sensitive alternative
766 28 View Code Duplication
                    if (isset(self::$alternativeMap[$type][$previousType])) {
767
                        $type = self::$alternativeMap[$type][$previousType];
768
                    }
769
770 28
                    if (isset(self::$reductionMap[$type][$previousType])) {
771
                        $image = self::$reductionMap[$type][$previousType]['image'];
772
                        $type = self::$reductionMap[$type][$previousType]['type'];
773
774
                        $startColumn = $previousStartColumn;
775
776
                        array_pop($this->tokens);
777
                    }
778 28
                } elseif (isset($tokenMap[$token[0]])) {
779 28
                    $type = $tokenMap[$token[0]];
780
                    // Check for a context sensitive alternative
781 28 View Code Duplication
                    if (isset(self::$alternativeMap[$type][$previousType])) {
782
                        $type = self::$alternativeMap[$type][$previousType];
783
                    }
784
785 28
                    $image = $token[1];
786 28
                } else {
787
                    // This should never happen
788
                    // @codeCoverageIgnoreStart
789
                    list($type, $image) = $this->generateUnknownToken($token[1]);
790
                    // @codeCoverageIgnoreEnd
791
                }
792
            }
793
794 28
            if ($type) {
795 28
                $rtrim = rtrim($image);
796 28
                $lines = substr_count($rtrim, "\n");
797 28 View Code Duplication
                if ($lines === 0) {
798 28
                    $endColumn = $startColumn + strlen($rtrim) - 1;
799 28
                } else {
800 16
                    $endColumn = strlen(
801 16
                        substr($rtrim, strrpos($rtrim, "\n") + 1)
802 16
                    );
803
                }
804
805 28
                $endLine = $startLine + $lines;
806
807 28
                $token = new Token($type, $rtrim, $startLine, $endLine, $startColumn, $endColumn);
808
809
                // Store token in internal list
810 28
                $this->tokens[] = $token;
811
812
                // Store previous start column
813 28
                $previousStartColumn = $startColumn;
814
815
                // Count newlines in token
816 28
                $lines = substr_count($image, "\n");
817 28 View Code Duplication
                if ($lines === 0) {
818 28
                    $startColumn += strlen($image);
819 28
                } else {
820 24
                    $startColumn = strlen(
821 24
                        substr($image, strrpos($image, "\n") + 1)
822 24
                    ) + 1;
823
                }
824
825 28
                $startLine += $lines;
826
                
827
                // Store current type
828 28
                if ($type !== Tokens::T_COMMENT && $type !== Tokens::T_DOC_COMMENT) {
829 28
                    $previousType = $type;
830 28
                }
831 28
            }
832
833 28
            next($tokens);
834 28
        }
835
836 28
        $this->count = count($this->tokens);
837 28
    }
838
839
    /**
840
     * This method fetches all tokens until an opening php tag was found and it
841
     * returns the collected content. The returned value will be null if there
842
     * was no none php token.
843
     *
844
     * @param array $tokens Reference to the current token stream.
845
     *
846
     * @return string
847
     */
848 6
    private function consumeNonePhpTokens(array &$tokens)
849
    {
850
        // The collected token content
851 6
        $content = null;
852
853
        // Fetch current token
854 6
        $token = (array) current($tokens);
855
856
        // Skipp all non open tags
857 6
        while ($token[0] !== T_OPEN_TAG_WITH_ECHO &&
858 6
               $token[0] !== T_OPEN_TAG &&
859 6
               $token[0] !== false) {
860 6
            $content .= (isset($token[1]) ? $token[1] : $token[0]);
861
862 6
            $token = (array) next($tokens);
863 6
        }
864
865
        // Set internal pointer one back when there was at least one none php token
866 6
        if ($token[0] !== false) {
867 6
            prev($tokens);
868 6
        }
869
870 6
        return $content;
871
    }
872
873
    /**
874
     * Generates a dummy/temp token for unknown string literals.
875
     *
876
     * @param string $token The unknown string token.
877
     *
878
     * @return array<integer, mixed>
0 ignored issues
show
The doc-type array<integer, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
879
     */
880
    private function generateUnknownToken($token)
881
    {
882
        return array($this->unknownTokenID++, $token);
883
    }
884
}
885