当前位置: 首页 > 文档资料 > PHP 语言规范 >

09 语法结构

优质
小牛编辑
132浏览
2023-12-01

脚本

[脚本](04-基本概念.html#program-structure)是一个有序的字符序列。通常, 脚本与文件系统中的文件是一一对应关系,但是这种对应不是必需的。

从概念上讲,使用以下步骤翻译脚本:

  1. 转换,转换从特定字符的脚本汇编和编码方案转换为8位字符序列。

  2. 词汇分析,将输入字符流转换成一个令牌流。

  3. 语法分析,将令牌流转换成可执行代码。

一致性实现必须接受使用UTF-8编码的脚本编码形式(由Unicode标准定义),并对它们进行变换 转换为字符序列。实现可以选择接受和变换附加字符编码方案。

语法

本规范显示了使用两个语法的PHP编程语言的语法。词法语法定义源字符如何组合以形成空格,注释和令牌。语法语法定义了所得到的令牌如何组合以形成PHP程序。

使用语法生成来呈现语法,每个语法定义非终端符号和该非终端符号可能扩展成非终端或终端符号的序列。在制作中,非终端符号以这样的倾斜类型示出,并且终端符号以这样的固定宽度字体示出。

语法生产的第一行是定义的非终端符号的名称,后面是用于语法语法生成的一个冒号,以及用于词法语法生成的两个冒号。每个相继的缩进线包含作为非终端或终端符号序列给出的非终端的可能扩展。例如,生产:

single-line-comment-example::
   //   input-charactersopt
   #   input-charactersopt

将词法语法生产单行注释定义为终端//,后跟可选的输入字符。 每个扩展单独列出。

尽管替换方案通常在单独的行上列出,但是当存在大数量时,简写短语“一个”可以在单个行上给出的扩展列表之前。 例如,

hexadecimal-digit-example:: one of
   0   1   2   3   4   5   6   7   8   9
   a   b   c   d   e   f
   A   B   C   D   E   F

词法分析

概述

生产输入文件是脚本的词法结构的根本。 每个脚本必须符合此生产。

语法

input-file::
   input-element
   input-file   input-element

input-element::
   comment
   white-space
   token

语义

脚本的基本元素是注释,空格和符号。

脚本的词法处理涉及减少该脚本 成为成为输入的tokens序列 句法分析。 令牌可以由[空格](#white-space)和 delimited comments

词法处理总是导致创建最长的 可能的词汇元素。 (例如,$a+++++$b必须解析为 $a++ ++ +$b,在语法上无效)。

注释

支持两种形式的注释:分隔注释单行注释

语法

comment::
   single-line-comment
   delimited-comment

single-line-comment::
   //   input-charactersopt
   #   input-charactersopt

input-characters::
   input-character
   input-characters   input-character

input-character::
   Any source character except   new-line

new-line::
   Carriage-return character (U+000D)
   Line-feed character (U+000A)
   Carriage-return character (U+000D) followed by line-feed character (U+000A)

delimited-comment::
   /*   No characters or any source character sequence except */   */

语义

除了在字符串文字或注释中,字符/*开始以分隔符注释,以字符*/结束。 除了在字符串文字或注释中,字符//开始单行注释,以一行结束。 那个新行不是评论的一部分。 但是,如果单行注释是嵌入脚本中的最后一个 源元素,则可以省略结尾的新行。 (注意:这允许使用<?php ... // ...?>)。

分隔的注释可以发生在可能出现空格的脚本中的任何位置。 (例如;/*...*/$c/*...*/=/*...*/567/*...*/;/*...*/ 被解析成 $c=567;, $k = $i+++/*...*/++$j; 被解析成 $k = $i+++ ++$j;).

实现注意事项

在标记化期间,实现可以将分隔的注释看作是空白。

空格

空格由一个或多个的任意组合组成新行,空格和水平制表符。

语法

white-space::
   white-space-character
   white-space   white-space-character

white-space-character::
   new-line
   Space character (U+0020)
   Horizontal-tab character (U+0009)

语义

空格和水平制表符视为水平空格字符

符号

概述

有几种源符号

语法

token::
   variable-name
   name
   keyword
   integer-literal
   floating-literal
   string-literal
   operator-or-punctuator

名称

语法

variable-name::
   $   name

namespace-name::
   name
   namespace-name   \   name

namespace-name-as-a-prefix::
   \
   \opt   namespace-name   \
   namespace   \
   namespace   \   namespace-name   \

qualified-name::
   namespace-name-as-a-prefixopt   name

name::
   name-nondigit
   name   name-nondigit
   name   digit

name-nondigit::
   nondigit
   one of the characters U+0080–U+00ff

nondigit:: one of
   _
   a   b   c   d   e   f   g   h   i   j   k   l   m
   n   o   p   q   r   s   t   u   v   w   x   y   z
   A   B   C   D   E   F   G   H   I   J   K   L   M
   N   O   P   Q   R   S   T   U   V   W   X   Y   Z

语义

名称用于标识以下内容:常量变量标签函数类成员接口traits命名空间heredocnowdoc注释中的名称。

名称以下划线(_),名称无引号或扩展名称字符开头,范围为U+0080–-U+00ff。后续字符也可以包括数字。变量名是带有前导美元($)的名称。

除非另有说明(函数方法接口traits命名空间),名称区分大小写,并且名称中的每个字符都是重要的。

以两个下划线(__)开头的名称由PHP语言保留,不应由用户代码定义。

以下名称不能用作类,接口或traits的名称:boolFALSEfloatintNULLstringTRUEiterablevoid

以下名称保留供将来使用,不应用作类,接口或traits的名称:mixed, numeric, object, and resource

除了class之外,所有关键字都可以用作类,接口或trait的成员的名称。但是,class可以用作属性或方法的名称。

变量名和函数名(当在函数调用上下文中使用时)不需要定义为源令牌; 他们也可以在创建 运行时使用简单变量表达式. (例如, 给出$a = "Total"; $b = 3; $c = $b + 5;, ${$a.$b.$c} = TRUE; 相当于 $Total38 = TRUE;, ${$a.$b.$c}() 相当于 Total38()).

例子

const MAX_VALUE = 100;
function getData() { /*...*/ }
class Point { /*...*/ }
interface ICollection { /*...*/ }

注意事项

不建议使用对名称长度的任意限制。

关键字

关键字是保留的名称类字符序列,并且不能用作名称。

语法

keyword:: one of
   abstract   and   array   as   break   callable   case   catch   class   clone
   const   continue   declare   default   die   do   echo   else   elseif   empty
   enddeclare   endfor   endforeach   endif   endswitch   endwhile   eval   exit
   extends   final   finally   for   foreach   function   global
   goto   if   implements   include   include_once   instanceof
   insteadof   interface   isset   list   namespace   new   or   print   private
   protected   public   require   require_once   return   static   switch
   throw   trait   try   unset   use   var   while   xor   yield   yield from

语义

关键字不区分大小写。

注意,yield from 是一个包含空格的单个符号。 但是,在空格中不允许注释

此外,所有魔术常量也被视为关键字。

语法

代表一个值的源代码被称作文本文本翻译参考

整型文本

语法

integer-literal::
   decimal-literal
   octal-literal
   hexadecimal-literal
   binary-literal

decimal-literal::
   nonzero-digit
   decimal-literal   digit

octal-literal::
   0
   octal-literal   octal-digit

hexadecimal-literal::
   hexadecimal-prefix   hexadecimal-digit
   hexadecimal-literal   hexadecimal-digit

hexadecimal-prefix:: one of
   0x   0X

binary-literal::
   binary-prefix   binary-digit
   binary-literal   binary-digit

binary-prefix:: one of
   0b   0B

digit:: one of
   0   1   2   3   4   5   6   7   8   9

nonzero-digit:: one of
   1   2   3   4   5   6   7   8   9

octal-digit:: one of
   0   1   2   3   4   5   6   7

hexadecimal-digit:: one of
   0   1   2   3   4   5   6   7   8   9
   a   b   c   d   e   f
   A   B   C   D   E   F

binary-digit:: one of
   0   1

语义

使用基数10计算十进制整数文本的值; 那 的八进制整数文本,基数是8; 十六进制整数 文本,基数是16; 二进制整数文本,基数是2。

如果由整数文本表示的值可以适合int类型, 这将是结果值的类型; 否则,类型将是float, 如下所述。

因为负数在PHP中表示为正数的相反数字,最小的负值(32位的-2147483648和64位的-9223372036854775808) 不能表示为十进制整数文本。 如果是非负数 值太大,而不能表示为一个int,它将变成float,然后加上负号。

使用十六进制,八进制或二进制符号写的文本被认为具有非负值。

整数文本通常是常量表达式。

An integer literal is always a constant expression.

例子

$count = 10;      // decimal 10

0b101010 >> 4;    // binary 101010 and decimal 4

0XAF << 023;      // hexadecimal AF and octal 23

一个使用32位整代表的实现

2147483648 -> 2147483648 (too big for int, so is a float)

-2147483648 -> -2147483648 (too big for int, so is a float, negated)

-2147483647 - 1 -> -2147483648 fits in int

0x80000000 -> 2147483648 (too big for int, so is a float)
浮点型文本

语法

floating-literal::
   fractional-literal   exponent-partopt
   digit-sequence   exponent-part

fractional-literal::
   digit-sequenceopt   .   digit-sequence
   digit-sequence   .

exponent-part::
   e   signopt   digit-sequence
   E   signopt   digit-sequence

sign:: one of
   +   -

digit-sequence::
   digit
   digit-sequence   digit

约束

浮点文本的值必须可以通过其类型表示。

语义

浮点文本的类型是float

常量INFNAN分别提供对无穷大和非数字的浮点值的访问。

浮点数文本总是一个常量表达式。

例子

$values = array(1.23, 3e12, 543.678E-23);
字符串文本

语法

string-literal::
   single-quoted-string-literal
   double-quoted-string-literal
   heredoc-string-literal
   nowdoc-string-literal

语义

字符串文本是以某种方式分隔的零个或多个字符的序列。 分隔符不是文字内容的一部分。

字符串文本的类型是string

单引号字符串文本

语法

single-quoted-string-literal::
   b-prefixopt   '   sq-char-sequenceopt   '

sq-char-sequence::
   sq-char
   sq-char-sequence   sq-char

sq-char::
   sq-escape-sequence
   \opt   any member of the source character set except single-quote (') or backslash (\)

sq-escape-sequence:: one of
   \'   \\

b-prefix:: one of
   b   B

语义

A single-quoted string literal is a string literal delimited by single-quotes (', U+0027). The literal can contain any source character except single-quote (') and backslash (\\), which can only be represented by their corresponding escape sequence.

The optional b-prefix is reserved for future use in dealing with so-called binary strings. For now, a single-quoted-string-literal with a b-prefix is equivalent to one without.

单引号字符串文本是由单引号(', U+0027)分隔的字符串文字。 文本可以包含除单引号(')和反斜杠(\)之外的任何源字符,只能由其相应的转义序列表示。

可选的b-prefix保留以供将来在处理所谓的二进制字符串时使用。 现在,带有b-prefix的单引号字符串文本相当于没有。

单引号字符串文本通常是一个常量表达式。

例子

'This text is taken verbatim'

'Can embed a single quote (\') and a backslash (\\) like this'
双引号字符串文本

语法

double-quoted-string-literal::
   b-prefixopt   "   dq-char-sequenceopt   "

dq-char-sequence::
   dq-char
   dq-char-sequence   dq-char

dq-char::
   dq-escape-sequence
   any member of the source character set except double-quote (") or backslash (\)
   \   any member of the source character set except "\$efnrtvxX or   octal-digit

dq-escape-sequence::
   dq-simple-escape-sequence
   dq-octal-escape-sequence
   dq-hexadecimal-escape-sequence
   dq-unicode-escape-sequence

dq-simple-escape-sequence:: one of
   \"   \\   \$   \e   \f   \n   \r   \t   \v

dq-octal-escape-sequence::
   \   octal-digit
   \   octal-digit   octal-digit
   \   octal-digit   octal-digit   octal-digit

dq-hexadecimal-escape-sequence::
   \x   hexadecimal-digit   hexadecimal-digitopt
   \X   hexadecimal-digit   hexadecimal-digitopt

dq-unicode-escape-sequence::
   \u{   codepoint-digits   }

codepoint-digits::
   hexadecimal-digit
   hexadecimal-digit   codepoint-digits

语义

双引号字符串文本是由分隔的字符串文本 双引号(",U+0022)。除了文本可以包含任何源字符 双引号('"')和反斜杠(\\),它们只能用表示 它们相应的转义序列。 某些其他(有时 不可打印)字符也可以表示为转义序列。

可选的b-prefix保留以供将来使用 所谓的二进制字符串。 现在,一个带有b-prefix前缀的 双引号字符串文字相当于没有这个前缀。

如所描述的,转义序列表示单字符编码 在下表中:

Escape sequenceCharacter nameUnicode character
$Dollar signU+0024
\"Double quoteU+0022
\BackslashU+005C
\eEscapeU+001B
\fForm feedU+000C
\nNew lineU+000A
\rCarriage ReturnU+000D
\tHorizontal TabU+0009
\vVertical TabU+000B
\ooo1–3-digit octal digit value ooo
\xhh or \Xhh1–2-digit hexadecimal digit value hh
\u{xxxxxx}UTF-8 encoding of Unicode codepoint U+xxxxxxU+xxxxxx

在双引号字符串文本中,除非被识别为转义序列的开始,否则反斜杠(\)将逐个保留。

在双引号字符串文本中,不使用反斜杠(\)转义的美元($)字符使用下面描述的变量替换规则处理。

\u{xxxxxx}转义序列使用大括号中指定的十六进制数字生成Unicode代码点的UTF-8编码。 实现不允许超出 U+10FFFF 的 Unicode 代码点,因为这超出了UTF-8可以编码的范围(参见RFC 3629)。 如果指定大于 U+10FFFF 的码点,则实现必须出错。实现必须通过\u逐字,如果没有后面跟一个开始{,但是如果是, 实现必须产生一个错误,如果没有终止}或内容不是有效的代码点,不解释它作为一个转义序列。 实现必须支持前导零,但不能支持开头和结尾括号之间的代码点的前导或尾随空格。实现必须 允许不是Unicode标量值的Unicode代码点,例如高和低代理。

无法通过变量替换创建Unicode转义序列。例如,给定$v = "41""\u{$v}"将生成 "\u41", 长度为4的字符串,而"\u{0$v}""\u{{$v}}"包含不合格的Unicode转义序列。

变量替换

变量替换遵循以下语法:

string-variable::
   variable-name   offset-or-propertyopt
   ${   expression   }

offset-or-property::
   offset-in-string
   property-in-string

offset-in-string::
   [   name   ]
   [   variable-name   ]
   [   integer-literal   ]

property-in-string::
   ->   name

表达式的工作方式与简单变量表达式的工作方式相同。

在评估由上述语法定义的变量后,根据字符串转换规则将其值 转换为字符串,并将其值代入变量替换表达式中的字符串。

字符串中的偏移量字符串中的属性定义的下标或属性访问分别根据下标运算符成员访问运算符的规则来解析。例外是, 在字符串内的偏移量被解释为一个字符串文本,即使它没有引号。

如果$后的字符序列不作为名称解析,并且不以{开头,则$字符将逐字地解释,并且不执行变量替换。

变量替代也为表达式的评估提供有限的支持。这是通过在一对匹配 大括号({...})中包含一个表达式来实现的。开头的大括号必须紧跟一个美元($), 没有任何中间的空格,并且美元必须开始一个变量名。如果不是这样,大括号是逐字 处理的。如果大括号({)被转义,它不会被解释为嵌入表达式的开始,而是逐字解释。

表达式的值根据字符串转换规则转换 为字符串,并替换为代替替换表达式的字符串。

双引号字符串文字是一个常量表达式,如果它不包含任何变量替换。

例子

$x = 123;
echo ">\$x.$x"."<"; // → >$x.123<
// -----------------------------------------
$colors = array("red", "white", "blue");
$index = 2;
echo "\$colors[$index] contains >$colors[$index]<\n";
  // → $colors[2] contains >blue<
// -----------------------------------------
class C {
    public $p1 = 2;
}
$myC = new C();
echo "\$myC->p1 = >$myC->p1<\n";  // → $myC->p1 = >2<
Heredoc 字符串文本

语法

heredoc-string-literal::
   b-prefixopt   <<<   hd-start-identifier   new-line   hd-bodyopt   hd-end-identifier   ;opt   new-line

hd-start-identifier::
   name
   "   name   "

hd-end-identifier::
   name

hd-body::
   hd-char-sequenceopt   new-line

hd-char-sequence::
   hd-char
   hd-char-sequence   hd-char

hd-char::
   hd-escape-sequence
   any member of the source character set except backslash (\)
   \ any member of the source character set except \$efnrtvxX or   octal-digit

hd-escape-sequence::
   hd-simple-escape-sequence
   dq-octal-escape-sequence
   dq-hexadecimal-escape-sequence
   dq-unicode-escape-sequence

hd-simple-escape-sequence:: one of
   \\   \$   \e   \f   \n   \r   \t   \v

约束

开始和结束标识符名称必须相同。 在<<<和起始标识符之间只允许水平空格。 在开始标识符和后面的新行之间不允许有空格。 在新行和后面的结束标识符之间 不允许有空格。 除了可选的分号(;)之外,在结束标识符和终止该源行的新行之间 不允许有字符 -- 甚至不包括注释或空格。

语义

heredoc字符串文本是由"<<< name"和"name"分隔的字符串文字。 文字可以包含任何源字符。 某些其他(有时不可打印)字符也可以表示为转义序列。

heredoc字符串文本支持对双引号字符串文本定义的变量替换。

heredoc字符串文本是一个常量表达式,如果它不包含任何变量替换。

可选的b-prefix没有效果。

例子

$v = 123;
$s = <<<    ID
S'o'me "\"t e\txt; \$v = $v"
Some more text
ID;
echo ">$s<";
// → >S'o'me "\"t e  xt; $v = 123"
// Some more text<
Nowdoc 字符串文本

语法

nowdoc-string-literal::
   b-prefixopt   <<<   '   name   '   new-line   hd-bodyopt   name   ;opt   new-line

约束

开始和结束标识符名称必须相同。 在开始标识符名称及其包含的单引号(')之间不允许有空格。 另请参见heredoc字符串文本

语义

一个nowdoc字符串文本看起来像一个heredoc字符串文本,除了在前者 开始标识符名称用单引号(')括起来。 字符串文本的两种形式具有 相同的语义和约束,除了nowdoc字符串文本不受变量替换(如单引号字符串)。

nowdoc字符串文本是一个常量表达式。

可选的b-prefix没有效果。

例子

$v = 123;
$s = <<<    'ID'
S'o'me "\"t e\txt; \$v = $v"
Some more text
ID;
echo ">$s<\n\n";
// → >S'o'me "\"t e\txt; \$v = $v"
// Some more text<

操作符与标点符号

语法

operator-or-punctuator:: one of
   [   ]   (   )   {   }   .   ->   ++   --   **   *   +   -   ~   !
   $   /   %   <<   >>   <   >   <=   >=   ==   ===   !=   !==   ^   |
   &   &&   ||   ?   :   ;   =   **=   *=   /=   %=   +=   -=   .=   <<=
   >>=   &=   ^=   |=   ,   ??   <=>   ...   \

语义

操作符和标点符号是具有独立语法和语义意义的符号。 在表达式中 使用运算符来描述涉及一个或多个操作对象的操作,并产生结果值, 产生副作用或其某种组合。 标点符号用于分组和分离。