Skip to content

Commit 0002942

Browse files
committed
pass new php7 syntax
1 parent ed12cdc commit 0002942

File tree

5 files changed

+174
-25
lines changed

5 files changed

+174
-25
lines changed

src/parser/expr.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,11 @@ module.exports = function(api, tokens, EOF) {
8888
} else if (this.token === tokens.T_CURLY_OPEN || this.token === '[') {
8989
// @fixme - should avoid a new token (could be resolved)
9090
return ['deference', expr, this.read_encapsed_string_item()];
91+
} else if (this.token === '(') {
92+
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
93+
return ['call', expr, this.read_function_argument_list()];
9194
} else {
92-
return expr;
95+
return expr;
9396
}
9497

9598
case '`':

src/parser/scalar.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,22 @@ module.exports = function(api, tokens, EOF) {
3737
// TEXTS
3838
case tokens.T_CONSTANT_ENCAPSED_STRING:
3939
var value = this.text();
40+
value = value.substring(1, value.length - 1).replace(
41+
/\\[rntvef"'\\\$]/g,
42+
function(seq) {
43+
return specialChar[seq];
44+
}
45+
);
4046
this.next();
41-
return [
42-
'string',
43-
value
44-
.substring(1, value.length - 1)
45-
.replace(/\\[rntvef"'\\\$]/g, function(seq) {
46-
return specialChar[seq];
47-
})
48-
];
47+
if (this.token === tokens.T_DOUBLE_COLON) {
48+
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1151
49+
return this.read_static_getter(
50+
['string', value]
51+
);
52+
} else {
53+
// dirrect string
54+
return ['string', value];
55+
}
4956
case tokens.T_START_HEREDOC:
5057
return this.next().read_encapsed_string(
5158
tokens.T_END_HEREDOC

src/parser/variable.js

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,32 @@ module.exports = function(api, tokens, EOF) {
4242

4343
// static mode
4444
if (this.token === tokens.T_DOUBLE_COLON) {
45-
var getter = null;
46-
if (this.next().is([tokens.T_VARIABLE, '$'])) {
47-
getter = this.read_reference_variable(encapsed);
48-
} else if (
49-
this.token === tokens.T_STRING
50-
|| this.token === tokens.T_CLASS
51-
) {
52-
getter = this.text();
53-
this.next();
54-
} else {
55-
this.error([tokens.T_VARIABLE, tokens.T_STRING]);
56-
}
57-
if (result[0] != 'ns') {
58-
result = ['lookup', 'class', result];
59-
}
60-
result = ['static', 'get', result, getter];
45+
result = this.read_static_getter(result, encapsed);
6146
}
6247

6348
return this.recursive_variable_chain_scan(result, read_only, encapsed);
6449
}
6550

51+
// resolves a static call
52+
,read_static_getter: function(from, encapsed) {
53+
var getter = null;
54+
if (this.next().is([tokens.T_VARIABLE, '$'])) {
55+
getter = this.read_reference_variable(encapsed);
56+
} else if (
57+
this.token === tokens.T_STRING
58+
|| this.token === tokens.T_CLASS
59+
) {
60+
getter = this.text();
61+
this.next();
62+
} else {
63+
this.error([tokens.T_VARIABLE, tokens.T_STRING]);
64+
}
65+
if (from[0] != 'ns') {
66+
from = ['lookup', 'class', from];
67+
}
68+
return ['static', 'get', from, getter];
69+
}
70+
6671
,recursive_variable_chain_scan: function(result, read_only, encapsed) {
6772
recursive_scan_loop:
6873
while(this.token != EOF) {

test/parser/php7.parser

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
Test PHP7 syntax
2+
--PASS:Return type declarations--
3+
function arraysSum(array ...$arrays): array
4+
{
5+
return array_map(function(array $array): int {
6+
return array_sum($array);
7+
}, $arrays);
8+
}
9+
10+
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
11+
--PASS--
12+
// Fetches the value of $_GET['user'] and returns 'nobody'
13+
// if it does not exist.
14+
$username = $_GET['user'] ?? 'nobody';
15+
// This is equivalent to:
16+
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
17+
--PASS:Spaceship operator--
18+
// Integers
19+
echo 1 <=> 1; // 0
20+
echo 1 <=> 2; // -1
21+
echo 2 <=> 1; // 1
22+
23+
// Floats
24+
echo 1.5 <=> 1.5; // 0
25+
echo 1.5 <=> 2.5; // -1
26+
echo 2.5 <=> 1.5; // 1
27+
28+
// Strings
29+
echo "a" <=> "a"; // 0
30+
echo "a" <=> "b"; // -1
31+
echo "b" <=> "a"; // 1
32+
--PASS:Constant arrays using define()--
33+
define('ANIMALS', [
34+
'dog',
35+
'cat',
36+
'bird'
37+
]);
38+
--PASS:Anonymous classes--
39+
interface Logger {
40+
public function log(string $msg);
41+
}
42+
43+
class Application {
44+
private $logger;
45+
46+
public function getLogger(): Logger {
47+
return $this->logger;
48+
}
49+
50+
public function setLogger(Logger $logger) {
51+
$this->logger = $logger;
52+
}
53+
}
54+
55+
$app = new Application;
56+
$app->setLogger(new class implements Logger {
57+
public function log(string $msg) {
58+
echo $msg;
59+
}
60+
});
61+
62+
var_dump($app->getLogger());
63+
--PASS:Unicode codepoint escape syntax--
64+
65+
echo "\u{aa}";
66+
echo "\u{0000aa}";
67+
echo "\u{9999}";
68+
--PASS:Closure::call()--
69+
70+
class A {private $x = 1;}
71+
72+
// Pre PHP 7 code
73+
$getXCB = function() {return $this->x;};
74+
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
75+
echo $getX();
76+
77+
// PHP 7+ code
78+
$getX = function() {return $this->x;};
79+
echo $getX->call(new A);
80+
--PASS:Group use declarations--
81+
// Pre PHP 7 code
82+
use some\ns\ClassA;
83+
use some\ns\ClassB;
84+
use some\ns\ClassC as C;
85+
86+
use function some\ns\fn_a;
87+
use function some\ns\fn_b;
88+
use function some\ns\fn_c;
89+
90+
use const some\ns\ConstA;
91+
use const some\ns\ConstB;
92+
use const some\ns\ConstC;
93+
94+
// PHP 7+ code
95+
use some\ns\{ClassA, ClassB, ClassC as C};
96+
use function some\ns\{fn_a, fn_b, fn_c};
97+
use const some\ns\{ConstA, ConstB, ConstC};
98+
--PASS:Generator Return Expressions--
99+
$gen = (function() {
100+
yield 1;
101+
yield 2;
102+
103+
return 3;
104+
})();
105+
106+
foreach ($gen as $val) {
107+
echo $val, PHP_EOL;
108+
}
109+
110+
echo $gen->getReturn(), PHP_EOL;
111+
--PASS:Generator delegation--
112+
function gen()
113+
{
114+
yield 1;
115+
yield 2;
116+
yield from gen2();
117+
}
118+
119+
function gen2()
120+
{
121+
yield 3;
122+
yield 4;
123+
}
124+
125+
foreach (gen() as $val)
126+
{
127+
echo $val, PHP_EOL;
128+
}
129+
--PASS--
130+
(clone $foo)->bar();
131+
class foo { static $bar = 'baz'; }
132+
var_dump('foo'::$bar);

test/token/edge.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
// edge cases for improving code coverage on lexer

0 commit comments

Comments
 (0)