Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 107 additions & 1 deletion parser/zephir.lemon
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,14 @@ xx_interface_def(R) ::= INTERFACE IDENTIFIER(I) EXTENDS xx_implements_list(L) xx
xx_ret_interface(&R, I, &B, &L, status->scanner_state);
}

xx_interface_def(R) ::= INTERFACE CONSTANT(I) xx_interface_body(B) . {
xx_ret_interface(&R, I, &B, NULL, status->scanner_state);
}

xx_interface_def(R) ::= INTERFACE CONSTANT(I) EXTENDS xx_implements_list(L) xx_interface_body(B) . {
xx_ret_interface(&R, I, &B, &L, status->scanner_state);
}

xx_class_def(R) ::= CLASS IDENTIFIER(I) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, NULL, NULL, status->scanner_state);
}
Expand All @@ -256,6 +264,10 @@ xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) xx_class_body(B) .
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= CLASS IDENTIFIER(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, NULL, &L, status->scanner_state);
}
Expand All @@ -264,6 +276,10 @@ xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_impl
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, NULL, NULL, status->scanner_state);
}
Expand All @@ -272,6 +288,10 @@ xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) xx_class_
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, NULL, &L, status->scanner_state);
}
Expand All @@ -280,6 +300,10 @@ xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENT
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, NULL, NULL, status->scanner_state);
}
Expand All @@ -288,6 +312,10 @@ xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) xx_class_bod
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, NULL, &L, status->scanner_state);
}
Expand All @@ -296,7 +324,81 @@ xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENTS x
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
}

/* TODO: Add internall class */
xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
}

xx_class_def(R) ::= CLASS CONSTANT(I) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, NULL, NULL, status->scanner_state);
}

xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= CLASS CONSTANT(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, NULL, &L, status->scanner_state);
}

xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= CLASS CONSTANT(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, NULL, NULL, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, NULL, &L, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= ABSTRACT CLASS CONSTANT(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 1, 0, E, &L, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS CONSTANT(I) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, NULL, NULL, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS CONSTANT(E) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, E, NULL, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS CONSTANT(I) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, NULL, &L, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS IDENTIFIER(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
}

xx_class_def(R) ::= FINAL CLASS CONSTANT(I) EXTENDS CONSTANT(E) IMPLEMENTS xx_implements_list(L) xx_class_body(B) . {
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
}

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

xx_implements(R) ::= CONSTANT(I) . {
xx_ret_literal(&R, XX_T_IDENTIFIER, I, status->scanner_state);
}

xx_interface_body(R) ::= BRACKET_OPEN BRACKET_CLOSE . {
ZVAL_UNDEF(&R);
}
Expand Down
17 changes: 17 additions & 0 deletions tests/classes/single-letter-class.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Single-letter class name should be accepted (regression test)
--SKIPIF--
<?php include(__DIR__ . '/../skipif.inc'); ?>
--FILE--
<?php
$code =<<<ZEP
class A {}
ZEP;
$ir = zephir_parse_file($code, '(eval code)');
// Previously this produced a syntax error because 'A' tokenized as CONSTANT
// and grammar allowed only IDENTIFIER after CLASS.
var_dump($ir[0]["name"]);
?>
--EXPECT--
string(1) "A"

19 changes: 19 additions & 0 deletions tests/classes/single_letter_class.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
Single-letter class name should be parsed
--SKIPIF--
<?php include(__DIR__ . '/../skipif.inc'); ?>
--FILE--
<?php
$code =<<<ZEP
class A
{
}
ZEP;
$ir = zephir_parse_file($code, '(eval code)');
var_dump($ir[0]['type']);
var_dump($ir[0]['name']);
?>
--EXPECT--
string(5) "class"
string(1) "A"