This article, originally authored by Thomas Punt and reprinted with permission, details the creation of a custom range operator (|>) in PHP. It's a deep dive into PHP internals, assuming familiarity with building PHP from source (refer to the PHP Internals Book for guidance).
The process involves modifying four key areas: the lexer, parser, compilation stage, and Zend VM.
Key Steps:
Lexer Update: The lexer is modified (Zend/zend_language_scanner.l) to recognize "|>" and generate a T_RANGE
token. Re2c is then used to regenerate the lexer. The T_RANGE
token is also declared in Zend/zend_language_parser.y. Finally, the ext/tokenizer/tokenizer_data.c
file needs regeneration using tokenizer_data_gen.sh
to ensure the tokenizer extension recognizes the new token.
Parser Update: The parser (Zend/zend_language_parser.y) is updated to define the usage, precedence (same as the spaceship operator), and associativity (non-associative, preventing chaining) of the T_RANGE
operator. A new AST node (ZEND_AST_RANGE
) is created in Zend/zend_ast.h
.
Compilation Stage Update: The compilation stage (Zend/zend_compile.c) is modified to handle the ZEND_AST_RANGE
AST node. A zend_compile_range
function is added, which emits a ZEND_RANGE
opcode.
Zend VM Update: The Zend VM (Zend/zend_vm_def.h) is updated to handle the ZEND_RANGE
opcode. This involves defining the opcode's behavior, including handling different operand types (integers and floats only), error handling (exceptions for invalid inputs or excessively large ranges), and generating the resulting array. The Zend VM is regenerated using Zend/zend_vm_gen.php
. Finally, the AST pretty printer in Zend/zend_ast.c
is updated to correctly display the new operator.
Range Operator Semantics:
The |>
operator creates an array based on two operands (min and max):
min == max
, returns a single-element array.Error
exception if operands are invalid, min > max
, or the range is too large.Examples:
1 |> 3; // [1, 2, 3] 2.5 |> 5; // [2.5, 3.5, 4.5] $a = $b = 1; $a |> $b; // [1] 2 |> 1; // Error exception 1 |> '1'; // Error exception new StdClass |> 1; // Error exception
This detailed explanation provides a comprehensive overview of the process. The article concludes by noting that this is one implementation and a more efficient version will be explored in a future article. A FAQ section is also included, covering common questions about the range operator's usage and behavior.
The above is the detailed content of Implementing the Range Operator in PHP. For more information, please follow other related articles on the PHP Chinese website!