Как рендеринг комментария вместе с открывающим тегом PHP приводит к «неожиданному T_STRING»? - PullRequest
1 голос
/ 16 февраля 2012

следующий код:

<?php//comment
error_reporting(0);

результаты (по крайней мере, в 5.2.11) в:

Ошибка разбора: синтаксическая ошибка, неожиданная T_STRING

... что я нахожу довольно странным.

Независимо от того, следует ли дословно разрешить <?php//comment, я предлагаю не сомневаться в ошибочности содержимого ошибки разбора.

Это потому, что в поле зрения нет T_STRING (хотя я действительно понимаю, что произведения могут образовывать другие произведения для обеспечения приоритета, например, additive-expression s, инкапсулирующие операции умножения и т.п.).

Может кто-нибудь с пониманием грамматики PHP объяснить, как это произошло?

Ответы [ 4 ]

7 голосов
/ 16 февраля 2012

См. Следующий фрагмент, который ищет открывающий тег <?php.Обратите внимание на требование завершающего пробела, горизонтальной табуляции или новой строки.

<INITIAL>"<?php"([ \t]|{NEWLINE}) {
    <snip>
    return T_OPEN_TAG;
}

(Источник: zend_language_scanner.l из PHP 5.3.10 )

Это означает, что PHP не видит ваш код как обычный (длинный) открытый тег, а скорее имеет короткий открытый тег.

<INITIAL>"<?" {
    if (CG(short_tags)) {
        <snip>
        return T_OPEN_TAG;
    } else {
        goto inline_char_handler;
    }
}

(Источник: zend_language_scanner.l из PHP 5.3.10

Короткий тег не требует конечных пробелов.

Итак, различные части вашего кода, которые видит PHP, <?, php, //comment, error_reporting…. php принимается за константу (которая не существует, см. Ниже). Затем есть комментарий, что хорошо. Однако следующий шагдля вызова функции error_reporting(). Это не то, что разрешено в данный момент, и теперь PHP выручает, жалуясь, что идентификатор (T_STRING) error_reporting не ожидался.

Чтобы продемонстрировать это, давайте попробуем некоторый код, который работает (что означает: код PHP выполнен успешно) с short_open_tag включен, но не будет с short_open_tag отключен.

<?php//comment
;

С error_reporting достаточно высоким, чтобы показывать уведомления, вы сможете увидеть, что идет не так, как вывод, что-то вроде:

Примечание: использование неопределенной константы php - предполагается, что 'php' в example.php в строке 2

При выключенном short_open_tag на выходе будет код вобычный текст, поскольку PHP не пытается его выполнить.

Наконец, небольшое напоминание об описании T_STRING в списке токенов синтаксического анализатора , в котором говорится, что T_STRING предназначено для (не спрашивайте меня, почему это не T_IDENTIFIER, T_BAREWORD или что-то менее запутанное):

идентификаторы, например, строки, объектно-ориентированные ключевые слова, такие как parent и self, функции, классы и многое другое.

4 голосов
/ 16 февраля 2012

Причина проста. token_get_all() возвращает проанализированную версию кода. Возвращает следующий код (при использовании var_dump() в результате).

array(8) {
  [0]=>
  array(3) {
    [0]=>
    int(367)
    [1]=>
    string(2) "<?"
    [2]=>
    int(1)
  }
  [1]=>
  array(3) {
    [0]=>
    int(307)
    [1]=>
    string(3) "php"
    [2]=>
    int(1)
  }
  [2]=>
  array(3) {
    [0]=>
    int(365)
    [1]=>
    string(10) "//comment
"
    [2]=>
    int(1)
  }
  [3]=>
  array(3) {
    [0]=>
    int(307)
    [1]=>
    string(15) "error_reporting"
    [2]=>
    int(2)
  }
  [4]=>
  string(1) "("
  [5]=>
  array(3) {
    [0]=>
    int(305)
    [1]=>
    string(1) "0"
    [2]=>
    int(2)
  }
  [6]=>
  string(1) ")"
  [7]=>
  string(1) ";"
}

Проблема очевидна, когда смотришь на нее. Он видит <? (T_OPEN_TAG) и php (T_STRING). Если вы проанализируете <?php // ok, вы получите следующий результат.

array(2) {
  [0]=>
  array(3) {
    [0]=>
    int(367)
    [1]=>
    string(6) "<?php "
    [2]=>
    int(1)
  }
  [1]=>
  array(3) {
    [0]=>
    int(365)
    [1]=>
    string(5) "// ok"
    [2]=>
    int(1)
  }
}

Можете ли вы заметить, что T_OPEN_TAG это <?php[SPACE]. Кроме того, PHP резервирует версии начального тега с \t, \r и \n после него. Моим рассуждением было бы избежать разрушения БК. В старых версиях PHP в PHP не было <?php, и вы легко могли сделать фрагмент <?phpinfo();?>, чтобы получить информацию о версии PHP. Если команда PHP изменит грамматику, это вызовет активацию функции info();, даже если она ранее работала. Или ... они хотели избежать запутанных букв после php. Видеть <?phprequire было бы несколько странно, поэтому лучше избегать чего-либо подобного. Но это только мое предположение, так как это единственное, что может сломаться.

Кроме того, просто небольшая информация, которую я забыл добавить. Функции (если они не являются переменными функциями или чем-то еще): T_STRING. Они распознаются по значку ( после T_STRING. Это не так уж странно (но тот факт, что они назвали что-то, что явно не является строкой T_STRING, довольно странно ... для меня ... T_BAREWORD или что-то вроде этого было бы лучше ...).

1 голос
/ 16 февраля 2012

Добавьте пробел между <? Php и // комментарием ... Это должно исправить проблему. </p>

0 голосов
/ 16 февраля 2012

За открывающим тегом <?php ДОЛЖНЫ следовать пробелы.

В моем тесте (PHP 5.3.8) <?php// не обрабатывался как открывающий тег, а вместо него печатался источник.

...