Tricky Perl Quine

注意事项 Lane:今天在Twitter上遇到的话题乍一看非常有趣。 然后他仔细看了一下,发现自己不仅很有趣,而且很有趣。 既然是今天星期五,我决定值得与我的同志们分享发现:)

图片

将以下程序保存在/tmp/quine.pl中

Illegal division by zero at /tmp/quine.pl line 1. 

使用命令运行

 perl /tmp/quine.pl 

她将输出自己的代码。

“ Quake-tricks”在许多编程语言中都很容易编写,其中源代码中的语法错误会引起解析器输出与程序源代码一致的错误。 我在Twitter上发布了一些技巧 ,包括以下内容:

  File "quine.py", line 1 File "quine.py", line 1 ^ IndentationError: unexpected indent 

但是本文开头的大麦是一种完全不同的技巧-程序正确理解。 而且它不会持续很长时间,直到偶然发现除零的误差。 此quine对文件命名非常敏感-例如,无法通过./quine.pl运行。

因此,此错误消息实际上是整个程序?

该程序使用了大量的Pearl-bar-what-I-mean解析器。

符号/非常依赖于应用程序上下文,可以将其视为除法符号或正则表达式的开头。 而且,即使对该程序的代码进行很小的更改,也会在解析规则性时导致错误,而不是导致代码执行。 在这种情况下,两个/字符都出现在运算符的上下文中。

该程序的其他非词典部分是1. ,简单解释为数字和. 这是一个串联运算符。

那这些话是什么意思?

Perl中的单词可以是例程,方法,程序包或类的名称。 或者(在懒惰模式下)没有分隔符的行,或者甚至是我忘记的其他东西!

Perl还使用一种不寻常的方法调用语法,称为“ 间接对象​​语法 ”,如下所示:


大多数时候你会看到

 print $filehandle "message"; my $instance = new Class(args); 

尽管对于Perl,以下语法更可取:

 $filehandle->print("message"); my $instance = Class->new(args); 

perlobj文档说:

Perl使用启发式算法来解析此代码,具体取决于它知道哪些包名称,当前包中存在哪些子例程,之前遇到过哪些单词以及分析其他输入数据。 不用说,启发式方法会产生非常出乎意料的结果!
他如何解析此代码?
从右边开始

 pl line 1. 

解析为方法调用

 line->pl(1.) 

其中line是包(类)的名称,pl是方法。

在中间,“ at”,“ tmp”和“ quine”被解析为简单的单词,即 字符串。 表达式解析如下:

 (("at" / "tmp") / "quine") . line->pl(1.) 

左侧是两个折叠的间接方法调用,

 division->Illegal(zero->by( ... )) 

首先执行的内部表达式是:

 "at" / "tmp" 

这立即导致除零异常。

Source: https://habr.com/ru/post/zh-CN446958/


All Articles