Skip to content

Instantly share code, notes, and snippets.

@brzuchal
Last active February 1, 2018 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brzuchal/41a7e4c771e1551e4226b84ba9fd9bbb to your computer and use it in GitHub Desktop.
Save brzuchal/41a7e4c771e1551e4226b84ba9fd9bbb to your computer and use it in GitHub Desktop.
PHP Annotations Syntax
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 2941546..b0ca01b 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -221,12 +221,14 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_COALESCE "?? (T_COALESCE)"
%token T_POW "** (T_POW)"
%token T_POW_EQUAL "**= (T_POW_EQUAL)"
+%token T_AT "@ (T_AT)"
/* Token used to force a parse error from the lexer */
%token T_ERROR
-%type <ast> top_statement namespace_name name statement function_declaration_statement
-%type <ast> class_declaration_statement trait_declaration_statement
+%type <ast> annotation_list annotation
+%type <ast> top_statement namespace_name name statement annotated_function_declaration_statement function_declaration_statement
+%type <ast> annotated_class_declaration_statement class_declaration_statement trait_declaration_statement
%type <ast> interface_declaration_statement interface_extends_list
%type <ast> group_use_declaration inline_use_declarations inline_use_declaration
%type <ast> mixed_group_use_declaration use_declaration unprefixed_use_declaration
@@ -306,9 +308,21 @@ name:
| T_NS_SEPARATOR namespace_name { $$ = $2; $$->attr = ZEND_NAME_FQ; }
;
+
+annotation:
+ '@' name '(' ')' { $$ = $2; }
+;
+
+annotation_list:
+ annotation { $$ = $1; }
+/* | annotation_list annotation { $$ = $1; }*/
+;
+
top_statement:
statement { $$ = $1; }
+ | annotated_function_declaration_statement { $$ = $1; }
| function_declaration_statement { $$ = $1; }
+ | annotated_class_declaration_statement { $$ = $1; }
| class_declaration_statement { $$ = $1; }
| trait_declaration_statement { $$ = $1; }
| interface_declaration_statement { $$ = $1; }
@@ -483,6 +497,10 @@ unset_variable:
variable { $$ = zend_ast_create(ZEND_AST_UNSET, $1); }
;
+annotated_function_declaration_statement:
+ annotation_list function_declaration_statement { $$ = $2; $$->attr = $1; }
+;
+
function_declaration_statement:
function returns_ref T_STRING backup_doc_comment '(' parameter_list ')' return_type
backup_fn_flags '{' inner_statement_list '}' backup_fn_flags
@@ -500,6 +518,10 @@ is_variadic:
| T_ELLIPSIS { $$ = ZEND_PARAM_VARIADIC; }
;
+annotated_class_declaration_statement:
+ annotation_list class_declaration_statement { $$ = $2; $$->attr = $1; }
+;
+
class_declaration_statement:
class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); }
T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
@@ -716,7 +738,9 @@ class_statement_list:
class_statement:
- variable_modifiers property_list ';'
+ annotation_list variable_modifiers property_list ';'
+ { $$ = $3; $$->attr = $1; $$->attr = $2; }
+ | variable_modifiers property_list ';'
{ $$ = $2; $$->attr = $1; }
| method_modifiers T_CONST class_const_list ';'
{ $$ = $3; $$->attr = $1; }
$ sapi/cli/php test.php
Runtime test without error supression:
foo: 1, 2
Foo::bar: 1, 2
Runtime test with error supression:
foo: 1, 2
Foo::bar: 1, 2
<?php
@Annotation()
function foo($a): void {
echo __FUNCTION__ . ': ' . implode(', ', $a) . PHP_EOL;
}
@Annotation()
class Foo {
@Annotation()
public $baz = 'BAZ';
public function bar($a): void {
echo __METHOD__ . ': ' . implode(', ', $a) . PHP_EOL;
}
}
echo "\e[0;33mRuntime test without error supression:\e[0m\n";
foo([1,2]);
$foo = new Foo();
$foo->bar([1,2]);
echo "\e[0;33mRuntime test with error supression:\e[0m\n";
@foo([1,2]);
@$foo->bar([1,2]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment