Skip to content

Commit fd38e28

Browse files
authored
Merge pull request #167 from zephir-lang/#166-single-char-class
#166 - Add support for single letter classes
2 parents 1383bd6 + a20afd3 commit fd38e28

File tree

3 files changed

+143
-1
lines changed

3 files changed

+143
-1
lines changed

parser/zephir.lemon

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ xx_interface_def(R) ::= INTERFACE IDENTIFIER(I) EXTENDS xx_implements_list(L) xx
248248
xx_ret_interface(&R, I, &B, &L, status->scanner_state);
249249
}
250250

251+
xx_interface_def(R) ::= INTERFACE CONSTANT(I) xx_interface_body(B) . {
252+
xx_ret_interface(&R, I, &B, NULL, status->scanner_state);
253+
}
254+
255+
xx_interface_def(R) ::= INTERFACE CONSTANT(I) EXTENDS xx_implements_list(L) xx_interface_body(B) . {
256+
xx_ret_interface(&R, I, &B, &L, status->scanner_state);
257+
}
258+
251259
xx_class_def(R) ::= CLASS IDENTIFIER(I) xx_class_body(B) . {
252260
xx_ret_class(&R, I, &B, 0, 0, NULL, NULL, status->scanner_state);
253261
}
@@ -256,6 +264,10 @@ xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) xx_class_body(B) .
256264
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
257265
}
258266

267+
xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
268+
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
269+
}
270+
259271
xx_class_def(R) ::= CLASS IDENTIFIER(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
260272
xx_ret_class(&R, I, &B, 0, 0, NULL, &L, status->scanner_state);
261273
}
@@ -264,6 +276,10 @@ xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_impl
264276
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
265277
}
266278

279+
xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
280+
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
281+
}
282+
267283
xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) xx_class_body(B) . {
268284
xx_ret_class(&R, I, &B, 1, 0, NULL, NULL, status->scanner_state);
269285
}
@@ -272,6 +288,10 @@ xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) xx_class_
272288
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
273289
}
274290

291+
xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
292+
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
293+
}
294+
275295
xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
276296
xx_ret_class(&R, I, &B, 1, 0, NULL, &L, status->scanner_state);
277297
}
@@ -280,6 +300,10 @@ xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENT
280300
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
281301
}
282302

303+
xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
304+
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
305+
}
306+
283307
xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) xx_class_body(B) . {
284308
xx_ret_class(&R, I, &B, 0, 1, NULL, NULL, status->scanner_state);
285309
}
@@ -288,6 +312,10 @@ xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) xx_class_bod
288312
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
289313
}
290314

315+
xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
316+
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
317+
}
318+
291319
xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
292320
xx_ret_class(&R, I, &B, 0, 1, NULL, &L, status->scanner_state);
293321
}
@@ -296,7 +324,81 @@ xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENTS x
296324
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
297325
}
298326

299-
/* TODO: Add internall class */
327+
xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
328+
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
329+
}
330+
331+
xx_class_def(R) ::= CLASS CONSTANT(I) xx_class_body(B) . {
332+
xx_ret_class(&R, I, &B, 0, 0, NULL, NULL, status->scanner_state);
333+
}
334+
335+
xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) xx_class_body(B) . {
336+
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
337+
}
338+
339+
xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
340+
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
341+
}
342+
343+
xx_class_def(R) ::= CLASS CONSTANT(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
344+
xx_ret_class(&R, I, &B, 0, 0, NULL, &L, status->scanner_state);
345+
}
346+
347+
xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
348+
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
349+
}
350+
351+
xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
352+
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
353+
}
354+
355+
xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) xx_class_body(B) . {
356+
xx_ret_class(&R, I, &B, 1, 0, NULL, NULL, status->scanner_state);
357+
}
358+
359+
xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) xx_class_body(B) . {
360+
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
361+
}
362+
363+
xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
364+
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
365+
}
366+
367+
xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
368+
xx_ret_class(&R, I, &B, 1, 0, NULL, &L, status->scanner_state);
369+
}
370+
371+
xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
372+
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
373+
}
374+
375+
xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
376+
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
377+
}
378+
379+
xx_class_def(R) ::= FINAL CLASS CONSTANT(I) xx_class_body(B) . {
380+
xx_ret_class(&R, I, &B, 0, 1, NULL, NULL, status->scanner_state);
381+
}
382+
383+
xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) xx_class_body(B) . {
384+
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
385+
}
386+
387+
xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
388+
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
389+
}
390+
391+
xx_class_def(R) ::= FINAL CLASS CONSTANT(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
392+
xx_ret_class(&R, I, &B, 0, 1, NULL, &L, status->scanner_state);
393+
}
394+
395+
xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
396+
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
397+
}
398+
399+
xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
400+
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
401+
}
300402

301403
xx_class_body(R) ::= BRACKET_OPEN BRACKET_CLOSE . {
302404
ZVAL_UNDEF(&R);
@@ -318,6 +420,10 @@ xx_implements(R) ::= IDENTIFIER(I) . {
318420
xx_ret_literal(&R, XX_T_IDENTIFIER, I, status->scanner_state);
319421
}
320422

423+
xx_implements(R) ::= CONSTANT(I) . {
424+
xx_ret_literal(&R, XX_T_IDENTIFIER, I, status->scanner_state);
425+
}
426+
321427
xx_interface_body(R) ::= BRACKET_OPEN BRACKET_CLOSE . {
322428
ZVAL_UNDEF(&R);
323429
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Single-letter class name should be accepted (regression test)
3+
--SKIPIF--
4+
<?php include(__DIR__ . '/../skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
$code =<<<ZEP
8+
class A {}
9+
ZEP;
10+
$ir = zephir_parse_file($code, '(eval code)');
11+
// Previously this produced a syntax error because 'A' tokenized as CONSTANT
12+
// and grammar allowed only IDENTIFIER after CLASS.
13+
var_dump($ir[0]["name"]);
14+
?>
15+
--EXPECT--
16+
string(1) "A"
17+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Single-letter class name should be parsed
3+
--SKIPIF--
4+
<?php include(__DIR__ . '/../skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
$code =<<<ZEP
8+
class A
9+
{
10+
}
11+
ZEP;
12+
$ir = zephir_parse_file($code, '(eval code)');
13+
var_dump($ir[0]['type']);
14+
var_dump($ir[0]['name']);
15+
?>
16+
--EXPECT--
17+
string(5) "class"
18+
string(1) "A"
19+

0 commit comments

Comments
 (0)