内園の日記

2007-03-30 不思議なPerlリテラル

ちょっとパーサの実装の参考にするためにPerlの数値リテラルについて調べていたのですが、手元のPerl5.8.3では「1.1.1」のような式を正しく解析できないようです。

予想では「1.1.1」は数値「1.1」と文字列結合演算子「.」と数値「1」と解釈され、「1.1」と「1」を文字列結合した文字列「1.11」になると思っていたんですが、実際に試してみると、なかなか不思議なことになりました。

	my $i = 1.1.1;
	print sprintf("string:'%s' number:'%d' length:%d\n", $i, $i, (length $i));
	print join(',', unpack("C*", $i));

最新版のPerlでは修正されてるかもしれませんが、上記のコードはsyntax errorにはならず、手元の環境では謎の値を生成してしまいました。

string:'' number:'0' length:3
1:1:1

処理系バグでしょうか?

そうでないなら、単に私の知らないリテラル記法があるんでしょうか。


ちなみにPerlBNFは公開されてないようですが、Perl処理系のtoke.c内にあるscan_num関数のコメントには以下のような記述がありました。

	Read a number in any of the formats that Perl accepts:

	\d(_?\d)*(\.(\d(_?\d)*)?)?[Ee][\+\-]?(\d(_?\d)*)	12 12.34 12.
	\.\d(_?\d)*[Ee][\+\-]?(\d(_?\d)*)			.34
	0b[01](_?[01])*
	0[0-7](_?[0-7])*
	0x[0-9A-Fa-f](_?[0-9A-Fa-f])*

どうやら上2つがPerlの数値リテラルの10進表現の仕様のようです。

(続いて2進、8進、16進表現でしょう)

Connection: close