Почему эта программа действительна? Я пытался создать синтаксическую ошибку

473

Я запускаю ActiveState 32-разрядный ActivePerl 5.14.2 в Windows 7. Я хотел объединиться с крюком Git pre-commit для обнаружения программ, проверяемых с синтаксическими ошибками. (Как-то мне просто удалось сделать такую плохую фиксацию.) Так что, как тестовая программа, я случайно записал это:

use strict;
use warnings;

Syntax error!

exit 0;

Тем не менее, он компилируется и выполняется без предупреждений, а уровень ошибок равен нулю при выходе. Как этот действительный синтаксис?

  • 113
    Вы только что доказали, что ввод случайных слов в perl создает работающие программы ??!?!?!?!
  • 9
    @PeterM Вряд ли случайные слова. Я доказал, что не знаю достаточно о синтаксисе Perl. Теперь я знаю немного больше.
Показать ещё 3 комментария
Теги:

5 ответов

544
Лучший ответ

Perl имеет синтаксис, называемый "опознавание косвенного метода". Он позволяет

Foo->new($bar)

записывается как

new Foo $bar

Итак, это означает

Syntax error ! exit 0;

совпадает с

error->Syntax(! exit 0);

или

error->Syntax(!exit(0));

Не только это синтаксис, он не приводит к ошибке во время выполнения, потому что первое, что выполнено, exit(0).

  • 0
    Хорошее объяснение! Но не должен ли оператор not ( ! ) Вызывать синтаксическую ошибку?
  • 1
    @ Хасан, почему? За этим следует выражение.
Показать ещё 8 комментариев
107

Я не знаю, почему, но это то, что делает Perl:

perl -MO=Deparse -w yuck
BEGIN { $^W = 1; }
use warnings;
use strict 'refs';
'error'->Syntax(!exit(0));
yuck syntax OK

Кажется, что парсер считает, что вы вызываете метод Syntax в error -объекте... Действительно странно!

  • 3
    Это косвенный синтаксис вызова метода. Это (вроде) работает здесь, потому что сначала выполняется exit(0) , что заставляет программу завершиться до того, как она попытается передать результат в 'error'->Syntax() .
  • 6
    Perl, похоже, предполагает «косвенный (объектный) синтаксис», обычно используемый как new Class вместо Class->new() . Для вызова метода Syntax выполняется функция exit , поэтому ошибка времени выполнения никогда не возникает.
Показать ещё 3 комментария
49

Причина, по которой вы не получаете ошибку, состоит в том, что первый выполненный код

exit(0);

Поскольку у вас не было точки с запятой в первой строке:

Syntax error!

Компилятор угадывает (неправильно), что это вызов подпрограммы с оператором not !. Он будет затем выполнять аргументы этой подпрограммы, которая оказывается exit(0), после чего программа выдает и устанавливает уровень ошибок в 0. Ничто другое не выполняется, поэтому не сообщается больше ошибок времени выполнения.

Вы заметите, что если вы измените exit(0) на нечто вроде print "Hello world!", вы получите сообщение об ошибке:

Can't locate object method "Syntax" via package "error" ...

и ваш уровень ошибки будет установлен:

> echo %errorlevel%
255
  • 7
    >The compiler will guess (incorrectly) . Компилятор не может ничего сделать неправильно.
  • 14
    @LiamLaarity Да, это возможно. Он может неправильно угадать, что имел в виду человек.
Показать ещё 4 комментария
33

Как отмечалось выше, это вызвано опознаванием непрямого метода. Вы можете предупредить об этом:

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;

Выдает:

Indirect call of method "Syntax" on object "error" at - line 5.

Для этого требуется непрямой модуль CPAN.

Вы также можете использовать no indirect "fatal";, чтобы заставить программу умереть (это то, что я делаю)

  • 0
    Это хорошее решение для «проблемы».
7

Попробуйте Perl 6, это, скорее всего, оправдает ваши ожидания:

===SORRY!=== Error while compiling synerror.p6
Negation metaoperator not followed by valid infix
at synerror.p6:1
------> Syntax error!<EOL>
    expecting any of:
        infix
        infix stopper

Ещё вопросы

Сообщество Overcoder
Наверх
Меню