为什么PHP解析器理解"$ x ++ - ++ $ x",但在"$ x +++++ $ x"上失败?

Axa*_*lix 28 php

我有一个引擎,通过从文件中获取公式,操作数和运算符来执行一些数学和逻辑运算.所有操作都在eval范围内执行,最终结果保存在另一个文件中.

这些文件通常通过网络传输,因此我试图通过剥离操作前后的所有空格来最小化它们.据我所知,对此事没有严格的规定,但我偶然发现了这种行为:

$x = 1;
$result = $x++-++$x; // works
$result = $x+++++$x; // fails
$result = $x++ + ++$x; // works again
Run Code Online (Sandbox Code Playgroud)
  1. 为什么PHP被"+++++"语法混淆,但接受"++ - ++"?"加"比"减"更好吗?

  2. 是否存在对空间敏感的运营商的列表?

Dek*_*kel 35

PHP解析器++在最后一个符号之前搜索+符号,并且语法($x++)++没有意义,因为增量运算符应该应用于变量(而不是整数,这是第一个的结果$x++).

可以在此处找到运算符操作的优先级:http:
//php.net/manual/en/language.operators.precedence.php

$x+++++$x;
^ php parser starts here, find $x++
    ^ here there is a new ++, which has hight precedence to the next + char
      ^ here is the last +, which the php parser will find last.
Run Code Online (Sandbox Code Playgroud)

当两个++,++拆分有减号,代码实际上是$x++ - ++$x,其中一个PHP解析器可以理解.

这也是工作的原因$x++ + ++$x.

  • 顺便说一下,这种行为的名称是"[maximal munch](https://en.wikipedia.org/wiki/Maximal_munch)"规则. (3认同)

Dan*_*Niu 12

答案是解析器在寻找更短的标记之前寻找更长的标记.因此++++++成为++ ++ +,这对解释器来说是不可理解的.

PHP是从C语言中借用其表达式语法的许多语言之一,因此您可能会对此注释感兴趣.在C11草案中,第6.4节第6节举了一个例子:

程序片段x +++++ y被解析为x ++ ++ + y,它违反了增量运算符的约束,即使解析x ++ + ++ y可能产生正确的表达式.

  • [为什么`+ +++++ b`在C中不起作用?](/sf/ask/373884171/) (4认同)

sle*_*vy1 10

更多补充信息.当PHP脚本被"lexed"时,即在扫描时,检查包含脚本的令牌.像"++"这样的一对字符表示增量令牌,如下所示:

<ST_IN_SCRIPTING>"++" {
    RETURN_TOKEN(T_INC);
}
Run Code Online (Sandbox Code Playgroud)

此"规则"位于Zend/language_scanner.l文件中,当您下载并安装它时,它随PHP一起提供.扫描脚本在增量前或增量后变得易于理解的唯一方法是,如果存在某种分界,例如间距,则在上下文中正确评估每个"+".

请注意,编写如下代码是不可取的:

  <?php

  $x=0;
  echo $x++ + ++$x;
Run Code Online (Sandbox Code Playgroud)

即便如此,它也会被正确地理解.反对这种编码风格的原因是因为对于人类大脑而言,对于真正发生的事情来说,它可能不那么明显.评估的顺序不是它看起来的顺序,即变量后递增,然后以其预先递增的值添加到自身.

根据操作码,在添加之前发生前后增量.另请注意,后递增会返回变量的值,然后递增它.因此,最初,$ x被赋值为0.然后,它被后递增,以便临时变量返回值为零.然后,$ x增加以获得值1.接下来,$ x预先递增,因此$ x从值1移动到2,其临时变量的计算结果为2.最后,添加了两个临时变量,以便0 + 2 == 2; 看到这里以及这里.

另外,这里读得很好.

顺便提一下,在这种情况下,PHP符合其隐含的C语言程序设计; 看到这里.