Skip to content

Commit f68e1a4

Browse files
TomasVotrubanikic
andauthored
[PHP 8.1] Add support for enums (nikic#758)
RFC: https://wiki.php.net/rfc/enumerations Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
1 parent f767b9f commit f68e1a4

File tree

16 files changed

+1585
-1162
lines changed

16 files changed

+1585
-1162
lines changed

.editorconfig

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*.y]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
indent_style = space
9+
indent_size = 4

grammar/php7.y

+15-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ reserved_non_modifiers:
2828
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
2929
| T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
3030
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN
31-
| T_MATCH
31+
| T_MATCH | T_ENUM
3232
;
3333

3434
semi_reserved:
@@ -356,6 +356,18 @@ class_declaration_statement:
356356
$this->checkInterface($$, #3); }
357357
| optional_attributes T_TRAIT identifier '{' class_statement_list '}'
358358
{ $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; }
359+
| optional_attributes T_ENUM identifier enum_scalar_type implements_list '{' class_statement_list '}'
360+
{ $$ = Stmt\Enum_[$3, ['scalarType' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]];
361+
$this->checkEnum($$, #3); }
362+
;
363+
364+
enum_scalar_type:
365+
/* empty */ { $$ = null; }
366+
| ':' type { $$ = $2; }
367+
368+
enum_case_expr:
369+
/* empty */ { $$ = null; }
370+
| '=' expr { $$ = $2; }
359371
;
360372

361373
class_entry_type:
@@ -637,6 +649,8 @@ class_statement:
637649
{ $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]];
638650
$this->checkClassMethod($$, #2); }
639651
| T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
652+
| optional_attributes T_CASE identifier enum_case_expr semi
653+
{ $$ = Stmt\EnumCase[$3, $4, $1]; }
640654
| error { $$ = null; /* will be skipped */ }
641655
;
642656

grammar/tokens.y

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
%token T_CLASS
8484
%token T_TRAIT
8585
%token T_INTERFACE
86+
%token T_ENUM
8687
%token T_EXTENDS
8788
%token T_IMPLEMENTS
8889
%token T_OBJECT_OPERATOR

lib/PhpParser/Node/Stmt/Class_.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class Class_ extends ClassLike
3232
* 'extends' => null : Name of extended class
3333
* 'implements' => array(): Names of implemented interfaces
3434
* 'stmts' => array(): Statements
35-
* '$attrGroups' => array(): PHP attribute groups
35+
* 'attrGroups' => array(): PHP attribute groups
3636
* @param array $attributes Additional attributes
3737
*/
3838
public function __construct($name, array $subNodes = [], array $attributes = []) {

lib/PhpParser/Node/Stmt/EnumCase.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PhpParser\Node\Stmt;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\AttributeGroup;
7+
8+
class EnumCase extends Node\Stmt
9+
{
10+
/** @var Node\Identifier Enum case name */
11+
public $name;
12+
/** @var Node\Expr|null Enum case expression */
13+
public $expr;
14+
/** @var Node\AttributeGroup[] PHP attribute groups */
15+
public $attrGroups;
16+
17+
/**
18+
* @param string|Node\Identifier $name Enum case name
19+
* @param Node\Expr|null $expr Enum case expression
20+
* @param AttributeGroup[] $attrGroups PHP attribute groups
21+
* @param array $attributes Additional attributes
22+
*/
23+
public function __construct($name, Node\Expr $expr = null, array $attrGroups = [], array $attributes = []) {
24+
parent::__construct($attributes);
25+
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
26+
$this->expr = $expr;
27+
$this->attrGroups = $attrGroups;
28+
}
29+
30+
public function getSubNodeNames() : array {
31+
return ['attrGroups', 'name', 'expr'];
32+
}
33+
34+
public function getType() : string {
35+
return 'Stmt_EnumCase';
36+
}
37+
}

lib/PhpParser/Node/Stmt/Enum_.php

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PhpParser\Node\Stmt;
4+
5+
use PhpParser\Node;
6+
7+
class Enum_ extends ClassLike
8+
{
9+
/** @var null|Node\Identifier Scalar Type */
10+
public $scalarType;
11+
/** @var Node\Name[] Names of implemented interfaces */
12+
public $implements;
13+
14+
/**
15+
* @param string|Node\Identifier|null $name Name
16+
* @param array $subNodes Array of the following optional subnodes:
17+
* 'scalarType' => null : Scalar type
18+
* 'implements' => array() : Names of implemented interfaces
19+
* 'stmts' => array() : Statements
20+
* 'attrGroups' => array() : PHP attribute groups
21+
* @param array $attributes Additional attributes
22+
*/
23+
public function __construct($name, array $subNodes = [], array $attributes = []) {
24+
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
25+
$this->scalarType = $subNodes['scalarType'] ?? null;
26+
$this->implements = $subNodes['implements'] ?? [];
27+
$this->stmts = $subNodes['stmts'] ?? [];
28+
$this->attrGroups = $subNodes['attrGroups'] ?? [];
29+
30+
parent::__construct($attributes);
31+
}
32+
33+
public function getSubNodeNames() : array {
34+
return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts'];
35+
}
36+
37+
public function getType() : string {
38+
return 'Stmt_Enum';
39+
}
40+
}

lib/PhpParser/Parser/Php5.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ class Php5 extends \PhpParser\ParserAbstract
193193
"'`'",
194194
"']'",
195195
"'\"'",
196+
"T_ENUM",
196197
"T_NULLSAFE_OBJECT_OPERATOR",
197-
"T_ATTRIBUTE",
198-
"T_ENUM"
198+
"T_ATTRIBUTE"
199199
);
200200

201201
protected $tokenToSymbol = array(
@@ -235,10 +235,10 @@ class Php5 extends \PhpParser\ParserAbstract
235235
94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
236236
104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
237237
114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
238-
124, 125, 126, 127, 128, 129, 130, 131, 163, 132,
239-
133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
240-
143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
241-
153, 164, 165
238+
124, 125, 126, 127, 128, 163, 129, 130, 131, 164,
239+
132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
240+
142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
241+
152, 153, 165
242242
);
243243

244244
protected $action = array(

0 commit comments

Comments
 (0)