php 加入 unless 语法
1. php 的版本 :PHP 7.3.0-dev (cli) (built: Mar 18 2018 00:28:55) ( NTS )
2. unless
语法结构:
unless($cond){
statement;
}
语法作用:
当 $cond 为假的时候,执行 statement 语句。
3. 代码修改
词法分析文件 : Zend/zend_language_scanner.l , 大约 1195 的地方,添加 5 -7 行、 13 - 15 行内容 :
1 <ST_IN_SCRIPTING>"while" { 2 RETURN_TOKEN(T_WHILE); 3 } 4 5 <ST_IN_SCRIPTING>"unless" { 6 RETURN_TOKEN(T_UNLESS); 7 } 8 9 <ST_IN_SCRIPTING>"endwhile" { 10 RETURN_TOKEN(T_ENDWHILE); 11 } 12 13 <ST_IN_SCRIPTING>"endunless" { 14 RETURN_TOKEN(T_ENDUNLESS); 15 }
语法分析文件 : Zend/zend_language_parser.y , 添加内容:
文件大约 271 行处, 添加 T_UNLESS 和 T_ENDUNLESS 内容:
1 reserved_non_modifiers: 2 T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND 3 | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE 4 | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY 5 | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO 6 | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK 7 | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS 8 | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_UNLESS | T_ENDUNLESS 9 ;
文件大约 152 行处, 添加 2 和 4 行 的内容:
1 %token T_WHILE "while (T_WHILE)" 2 %token T_UNLESS "unless (T_UNLESS)" 3 %token T_ENDWHILE "endwhile (T_ENDWHILE)" 4 %token T_ENDUNLESS "endunless (T_ENDUNLESS)"
大约 235 行处 , 增加 unless_statement :
%type <ast> expr optional_expr while_statement unless_statement for_statement foreach_variable
大约 428 行处, 增加 3 和 4 行的内容 :
1 | T_WHILE '(' expr ')' while_statement 2 { $$ = zend_ast_create(ZEND_AST_WHILE, $3, $5); } 3 | T_UNLESS '(' expr ')' unless_statement 4 { $$ = zend_ast_create(ZEND_AST_UNLESS, $3, $5); }
大约 598 行处 ,增加 6 - 9 行的内容 :
1 while_statement: 2 statement { $$ = $1; } 3 | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } 4 ; 5 6 unless_statement: 7 statement { $$ = $1; } 8 | ':' inner_statement_list T_ENDUNLESS ';' { $$ = $2; } 9 ;
Zend/zend_ast.h 的头文件中 ,大约 134 行处 , 增加 2 行的内容:
1 ZEND_AST_GROUP_USE, 2 ZEND_AST_UNLESS, 3 4 /* 3 child nodes */
Zend/zend_ast.c 的文件中, 函数 zend_ast_export_stmt 内,大约 915 行处, 添加 7 行的内容:
1 zend_ast_export_indent(str, indent); 2 zend_ast_export_indent(str, indent); 3 zend_ast_export_ex(str, ast, 0, indent); 4 switch (ast->kind) { 5 case ZEND_AST_LABEL: 6 case ZEND_AST_IF: 7 case ZEND_AST_UNLESS: 8 case ZEND_AST_SWITCH: 9 case ZEND_AST_WHILE: 10 case ZEND_AST_TRY: 11 case ZEND_AST_FOR: 12 case ZEND_AST_FOREACH: 13 case ZEND_AST_FUNC_DECL: 14 case ZEND_AST_METHOD: 15 case ZEND_AST_CLASS: 16 case ZEND_AST_USE_TRAIT: 17 case ZEND_AST_NAMESPACE: 18 case ZEND_AST_DECLARE: 19 break; 20 default: 21 smart_str_appendc(str, ';'); 22 break; 23 } 24 smart_str_appendc(str, '\n');
Zend/zend_compile.c 的文件中 ,
大约 4667 行, 添加 zend_compile_ unless 函数 :
1 void zend_compile_unless(zend_ast *ast) 2 { 3 zend_ast *cond_ast = ast->child[0]; 4 zend_ast *stmt_ast = ast->child[1]; 5 znode cond_node; 6 7 uint32_t opnum_cond; 8 9 zend_compile_expr(&cond_node,cond_ast); 10 11 opnum_cond = zend_emit_cond_jump(ZEND_JMPNZ,&cond_node,0); 12 13 zend_compile_stmt(stmt_ast); 14 15 zend_update_jump_target_to_next(opnum_cond); 16 }
zend_compile_stmt 函数中, 大约 8200 行处 :
1 case ZEND_AST_IF: 2 zend_compile_if(ast); 3 break; 4 case ZEND_AST_UNLESS: 5 zend_compile_unless(ast); 6 break;
4. 删除 Zend 目录下的 zend_language_parser.c 和 zend_language_scanner.c 文件,重新编译,安装 php .
5. 测试代码:
1 <?php 2 unless(0) 3 { 4 echo "Hello the world!\n"; 5 } 6 7 unless(0): 8 echo "Hello the world!\n"; 9 endunless;
输出:
1 root@ubuntu:~/tmp# php a.php 2 Hello the world! 3 Hello the world!
参考: