Почему синтаксический анализатор PHP понимает «$ x ++ — ++ $ x», но не работает на «$ x +++++ $ x»?

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

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

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

  2. Есть ли где-нибудь список операторов, которые являются чувствительными
    о пространствах?

27

Решение

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

35

Другие решения

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

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

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

11

Еще немного дополнительной информации. Когда скрипт PHP «лексирован», то есть когда он сканируется, проверяются токены, составляющие скрипт. Пара символов, таких как «++», обозначает токен приращения следующим образом:

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

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

Обратите внимание, что написание кода, подобного следующему, не рекомендуется:

  <?php

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

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

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

Кроме того, отличное чтение Вот.

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

10
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector