concat运算符和浮点标识符'。'的优先级。 (T_CONSTANT_ENCAPSED_STRING,T_DNUMBER)

时间:2016-09-22 06:38:53

标签: php

我最近在SO上创建了一个答案,我开始意识到我认为PHP中的一个奇怪的行为,我从未注意到由于我的(以下)编码风格:

$var = 1;
echo "test string ". $var+1 ." example";

这样可行,但如果删除1.之间的空格:

echo "test string ". $var+1." example";

它会向我提供T_CONSTANT_ENCAPSED_STRING解析错误,在这种情况下,期望','';'非常不正确。

是的..它会像这样工作:

echo "test string ".($var+1)." example";

我遇到的问题是,错误信息是它没有反映其特定需要的基本问题,其中大多数其他消息直接指向并纠正。

虽然我最初并不认为浮点是导致这种情况的原因,但我仍然很难理解浮点运算符在以下场景中优先于concat运算符的原因:

var_dump( .1, 1, 1., 1.0);
var_dump( 1.."a", "a"..1, 1.0."a");
  

float(0.1),int(1),float(1),float(1)
string(2)“1a”,string(4)“a0.1”,string(2)“1a “

现在我明白算术运算符应该在字符串运算之前进行,但这是我不能得到的部分:

".11."应该表明.是一个concat运算符,而1.1应该表明.是一个float的标识符。相反,他们都给出了解析错误。

PHP是一种在变量类型方面不挑剔的语言:

var_dump(1 + 1.); // float(2)
var_dump(1. + 1); // float(2)

您可以简单地使用+ 1添加到浮点数,为什么要将1.解析为浮点数?解析错误发生在下一个令牌上,在该令牌中它需要一个数字,甚至不允许它成为一个连接运算符。

所以我的问题是,为什么PHP词法分析器如此强调浮点识别?如果 echo 1."test"输出1test它会破坏当前现有的代码吗?

  

我已经编辑了这个问题,以便首先澄清我的意思,因为我得到了负面的代表。目前接受的答案仍然非常有效,因为我需要一种方法来验证PHP代码而不使用eval()

2 个答案:

答案 0 :(得分:2)

1.指的是浮点数1.0。所以你写的内容是:

echo "test string " . $var + 1.0 " example";

字符串" example"T_CONSTANT_ENCAPSED_STRING令牌。解析器不会在浮点数之后立即出现。

您可以使用token_get_all()

进行检查
php > var_export(token_get_all('<?php echo "test string ".$var+1." example";'));
array (
  0 => 
  array (
    0 => 379,
    1 => '<?php ',
    2 => 1,
  ),
  1 => 
  array (
    0 => 328,
    1 => 'echo',
    2 => 1,
  ),
  2 => 
  array (
    0 => 382,
    1 => ' ',
    2 => 1,
  ),
  3 => 
  array (
    0 => 323,
    1 => '"test string "',
    2 => 1,
  ),
  4 => '.',
  5 => 
  array (
    0 => 320,
    1 => '$var',
    2 => 1,
  ),
  6 => '+',
  7 => 
  array (
    0 => 318,
    1 => '1.',
    2 => 1,
  ),
  8 => 
  array (
    0 => 323,
    1 => '" example"',
    2 => 1,
  ),
  9 => ';',
)
php > print token_name(318);
T_DNUMBER
php > print token_name(323);
T_CONSTANT_ENCAPSED_STRING

请注意,1.显示为一个令牌318T_DNUMBER,双号)。

答案 1 :(得分:0)

让我告诉你,甚至你的陈述:
echo "test string ". $var+1 ." example";可能无法正常工作。 它可能会打印1 example而不是 test string 2 example

你也可能觉得它很有用

var_dump(1) gives `int 1` and
var_dump(1.) gives `float 1` and as expected
var_dump(1.0) gives `float 1` as answer

意外结果的原因:
  在"test string ". $var+1 ." example";中 首先将“test string”(一个字符串变量)连接到$var并生成结果string 1(一个字符串),然后将其添加(未连接) 1使php将**string 1**(字符串)的类型更改为 int ,因此它将变为0,然后添加到1,结果为1(0 + 1 = 1)。然后将1(从int再次转换为字符串)添加到example(字符串),结果为1 example(字符串)。

使用括号可避免此类更改  如上一个陈述enter code here

echo "test string ".($var+1)." example";