Подтвердить что ты не робот

Почему парсер PHP понимает "$ x ++ - ++ $x", но не удается "$ x +++++ $x"?

У меня есть движок, который выполняет некоторые математические и логические операции, беря формулы, операнды и операторы из файла. Все операции выполняются в области eval, а окончательный результат сохраняется в другом файле.

Эти файлы часто передаются через сеть, поэтому я пытаюсь свести их к минимуму, разделив все пробелы до и после операций. Насколько я знаю, в этом нет строгих правил, однако я наткнулся на это поведение:

$x = 1;
$result = $x++-++$x; // works
$result = $x+++++$x; // fails
$result = $x++ + ++$x; // works again
  • Почему PHP путают синтаксис "+++++", но принимает "++ - ++"? Как "плюс" лучше, чем "минус"?

  • Есть ли какой-либо список операторов, которые чувствительны о пробелах?

4b9b3361

Ответ 1

Парсер 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.

Когда два ++, ++ разделяются знаком минус, код фактически $x++ - ++$x, тот, который может понять парсер PHP.

Это также причина, по которой работает $x++ + ++$x.

Ответ 2

Ответ заключается в том, что синтаксический анализатор ищет более длинные токены перед поиском более коротких. Поэтому ++++++ становится ++ ++ +, что является непонятным для интерпретатора.

PHP является одним из многих языков, который заимствует грамматику выражения из C, поэтому эта заметка может вас заинтересовать. В проект C11, раздел 6.4, пункт 6 привел пример:

фрагмент программы x +++++ y анализируется как x ++ ++ + y, что нарушает ограничение на операторы приращения, даже если синтаксический анализ x ++ + ++ y может привести к правильному выражению.

Ответ 3

Более подробная информация. Когда PHP script "лексируется", то есть когда он сканируется, проверяются токены, содержащие script. Пара символов типа "++" обозначает токен приращения, как показано ниже:

<ST_IN_SCRIPTING>"++" {
    RETURN_TOKEN(T_INC);
}

Это "правило" находится в файле Zend/language_scanner.l, который сопровождает PHP при загрузке и установке. Единственный способ, которым a script при сканировании становится понятным для лексера в отношении переменных до или после инкремента, - это если есть какая-то демаркация, такая как интервал, чтобы каждый "+" был правильно оценен в контексте.

Обратите внимание, что писать код, подобный приведенному ниже, нецелесообразен:

  <?php

  $x=0;
  echo $x++ + ++$x;

даже он будет правильно лексироваться. Причина возражения против этого стиля кодирования заключается в том, что он может быть менее очевидным для человеческого мозга относительно того, что действительно происходит. Порядок оценки - это не то, что может показаться, то есть переменная, подлежащая поэтапному увеличению, а затем добавленная к ней с ее предварительно увеличенным значением.

В соответствии с opcodes, до и после инкремента происходят до добавления. Также обратите внимание, что post-incrementation возвращает значение переменной, а затем увеличивает его. Таким образом, изначально $x присваивается значение 0. Затем оно увеличивается после того, как временная переменная возвращается с нулевым значением. Затем значение $x увеличивается, чтобы получить значение единицы. Далее, $x предварительно увеличивается, и поэтому $x перемещается со значения от одного до двух, а его временная переменная оценивается как два. Наконец, добавляются две временные переменные, так что 0 + 2 == 2; см. здесь, а также здесь.

Кроме того, отличный читать здесь.

Кстати, в этом случае PHP соответствует своему языку программирования C C; см. здесь.