Hatena::Groupperl

Perl Tech RSSフィード

2015-02-08【ご連絡】はてなブログ始めました

一応のため告知です。実録コンピュータ物語という新しいブログを立ち上げました。もちろんPerlプログラミングの話題も書いていく予定です。このPerl Techも1年に1回更新するかどうかのペースなのでアレですが・・・とにかく、新ブログではPerl 6の話題を積極的に取り上げられたらいいなと考えています。

2014-03-22

bosh20140322

Perl6入門書(Using Perl6)の日本語版を公開しました はてなブックマーク -  Perl6入門書(Using Perl6)の日本語版を公開しました - Perl Tech

また1年ぶりの更新になってしまった。さて、今回はオープンソースのPerl6入門書であるUsing Perl6 <https://github.com/perl6/book>を日本語に翻訳しましたので公開します。Perl6(Rakudo)は開発から10年以上経過しているものの日本語でまとまった情報が少なく、学習のハードルが高すぎると感じていました。この状況を少しでも改善したいと思い、Perl6本を翻訳することにしました。

とは言えこの本自体はほとんど更新が止まっており、Perl6の最新仕様にどこまで通用するのかわかりません。ループなどの制御構造、モジュール、例外処理、テストのような重要っぽい機能の説明もほとんどありません。やはり最終的には仕様(https://github.com/perl6/specs)を見るしかなさそうです。そちらの翻訳にも手を出しているところなので、何らかの形で情報発信していきます。

翻訳版置き場(Dropboxで公開中)

FirefoxChromeなどのブラウザを推奨。IE 11だとシンタックスハイライトできません

Using Perl6日本語版 https://dl.dropboxusercontent.com/u/877032/UsingPerl6_JA.html

2013-01-13

PegexでCSSを解析するcss.pgxを作成しました はてなブックマーク -  PegexでCSSを解析するcss.pgxを作成しました - Perl Tech

用事があって複数のCSS文字列をマージする機能が必要になり、Ingy döt Net氏作のPegexというモジュール用のCSS文法を作ってみました。(CSSをマージするプログラムは探せばあるけれど、自分好みに解析したいし、perlで完結させたかったので。)Pegexを使う参考になるかと思ったので公開します。コピー・改変はご自由に。

注意

この文法はまだ開発中のため、CSSの変な箇所にコメントがあるとエラーになります。たとえば、セレクターの途中でh1, /* */ h2 { }のようにするとエラーで止まります。blank: comment | ~ のような文法を追加して使えば大丈夫かもしれませんが、面倒なのでまだ手を付けていません

css.pgx自体は単なる文法定義なので、これだけでは何の役にも立ちません。レシーバーモジュール(Pegex::Tree::Wrapなど)をカスタマイズすることで初めて真価を発揮します。専用のレシーバーを作れば、以下のような応用が可能になります。

  • マージ
  • 整形
  • プリプロセッサー
  • フォーマット変換

インストール方法

# Grammar for Cascading Style Sheets Level 1-3
# Copyright (c) 2013 Toshiyuki Yamato. <toshiyuki.yamato@gmail.com>

%grammar css
%version 0.1.0

css: -<outline>* eof

outline: -<at_rule> | rule | comment | ~~

eof: / ~ <EOS> /

ident: / ( <ALPHA> [<UNDER><ALNUMS><DASH>]* ) /

namespace: / (: <ident> <PIPE> )? /

element: namespace / <ident> /

class: / <DOT><ident> /

id: / <HASH><ident> /

all: / ( <STAR> ) /

property: / ( [<DASH><ALPHAS>]+ ) /

value: url | format | -<color> | ident | quoted_string | length | percentage | number

value_combination: -<value>+ % ~~

value_group: value_combination+ % / ~ <COMMA> ~ /

declaration: property / ~ <COLON> ~ / value_group ~ important / ~ <SEMI> /

important: / ( <BANG> ~ important )? /

block: / <LCURLY> ~ / ( declaration | comment | ~~ )* / ~ <RCURLY> /

selector: ( all | element | class | id | attribute | pseudo )+

connector: / ( [<WS><RANGLE><PLUS><TILDE>]+ ) (! [<COMMA><LCURLY>] ) /

selector_combination: -<selector>+ % connector

selector_group: selector_combination+ % / ~ <COMMA> ~ /

rule: selector_group ~ block

argument: / (: <LPAREN> ( [^<RPAREN>]* ) <RPAREN> )? /

pseudo: / <COLON><COLON>? <ident> / argument

quoted_string: / [<SINGLE><DOUBLE>] ( [^<SINGLE><DOUBLE>]* ) [<SINGLE><DOUBLE>] /

attribute: / <LSQUARE> ~ / ( match | element ) / ~ <RSQUARE> /

match: / <ident> ~ ( [<TILDE><PIPE><CARET><DOLLAR><STAR>]? <EQUAL> ) ~ <quoted_string> /

comment: /
    <SLASH><STAR> (
    [^<STAR>]* (: (! <STAR><SLASH> ) <STAR> [^<STAR>]* )*
    ) <STAR><SLASH> ~
/

url: / url <argument> /

format: / format <LPAREN> ~ <quoted_string> ~ <RPAREN> /

decimal: / <DASH>? <DIGIT>+ (: <DOT><DIGIT>+ )? /

number: / ( <decimal> ) /

length: / ( <decimal> (: em | ex | ch | rem | vw | vh | vmin | cm | mm | in | px | pt | pc) )  /

color: rrggbb_hex | rgb_hex | rgba | rgb | hsla | hsl

percentage: / ( <decimal> <PERCENT> ) /

rgb_value: percentage | number

rrggbb_hex: / ( <HASH> <HEX>{6} ) /

rgb_hex: / ( <HASH> <HEX>{3} ) /

rgb:  / rgb  <LPAREN> ~ / ( -<rgb_value>3 % / ~ <COMMA> ~ / ) / ~ <RPAREN> /

rgba: / rgba <LPAREN> ~ / ( -<rgb_value>4 % / ~ <COMMA> ~ / ) / ~ <RPAREN> /

hsl:  / hsl  <LPAREN> ~ / ( -<rgb_value>3 % / ~ <COMMA> ~ / ) / ~ <RPAREN> /

hsla: / hsla <LPAREN> ~ / ( -<rgb_value>4 % / ~ <COMMA> ~ / ) / ~ <RPAREN> /

at_rule:
    at_charset | at_font_face | at_import | at_media | at_namespace |
    at_page | at_unknown

at_charset: / <AT>charset ~ <quoted_string> ~ <SEMI> /

at_font_face: / <AT>font-face ~ / block

at_import: / <AT>import ~ / ( url | quoted_string ) / ~ <SEMI> /

at_media:
/ <AT>media ~ / ( -<ident>+ % / ~ <COMMA> ~ / )
/ ~ <LCURLY> ~ /
-<outline>*
/ ~ <RCURLY> /

at_namespace: / <AT>namespace ~ <ident>? ~ <quoted_string> ~ <SEMI> /

at_page: / <AT>page ~ ( <COLON> (: first | right | left ) )? / block

at_unknown: / <AT><ident> ~ <LCURLY> ~ / -<outline>* / ~ <RCURLY> /

使用例

文法ファイルは以下のように使用する。

use strict;
use File::Slurp;
use Data::Dumper qw(Dumper);
$Data::Dumper::Indent = 1;

use Pegex;

my $grammer = read_file "css.pgx";

# CSSをファイルから読み込む
# my $input = Pegex::Input->new(file => "mycss.css");

# 文字列を直接解析したい場合はこっち
my $input = Pegex::Input->new(string => <<'CSS');
@charset "UTF-8";

h1, p {
    font-style: normal;
}

CSS

my $parser = pegex($grammer, receiver => "Pegex::Tree::Wrap");
my $data = $parser->parse($input);
write_file "output.txt", Dumper $data;

すると、出力は以下のようになります。CSS3に対応させるため、要素セレクタにnamespaceなどが付与されるようになっています(この例では名前空間が未指定なのでundefになる)。

$VAR1 = {
  'css' => [
    [
      {
        'at_charset' => 'UTF-8'
      },
      {
        'rule' => [
          {
            'selector_group' => [
              {
                'selector_combination' => [
                  [
                    {
                      'element' => [
                        {
                          'namespace' => undef
                        },
                        'h1'
                      ]
                    }
                  ]
                ]
              },
              {
                'selector_combination' => [
                  [
                    {
                      'element' => [
                        {
                          'namespace' => undef
                        },
                        'p'
                      ]
                    }
                  ]
                ]
              }
            ]
          },
          {
            'block' => [
              [
                {
                  'declaration' => [
                    {
                      'property' => 'font-style'
                    },
                    {
                      'value_group' => [
                        {
                          'value_combination' => [
                            {
                              'ident' => 'normal'
                            }
                          ]
                        }
                      ]
                    },
                    {
                      'important' => undef
                    }
                  ]
                }
              ]
            ]
          }
        ]
      }
    ]
  ]
};

2012-08-29

[]Perlでインラインコメントは書けるのか? はてなブックマーク - Perlでインラインコメントは書けるのか? - Perl Tech

「リーダブルコード」を読んでアイデアが浮かんだので久しぶりに更新。今回はPerlにおけるインラインコメントについて考えたい。インラインコメントとはコードの途中に記述可能なコメントのこと。C言語でお馴染みのコメント方法だ。以下はリーダブルコードより抜粋

// 引数にコメントをつけて関数を呼び出す
Connect(/* timeout_ms = */ 10, /* use_encryption = */ false);

Perlでは#~行末までが全てコメントになる(ラインコメント)。この「行末まで」を途中で止めることができればインラインコメントが可能になるわけだ。しかしPerlの言語仕様上、どう頑張ってもコメントを途中で終わりにすることは出来ない。で、妥協して考えたのが以下のハックである。

sub fullname {
    my ($myouji, $namae) = @_;
    return "$myouji $namae";
}

print fullname( /(?!)# myouji = /x, "tanaka", /(?!)# namae = /x, "taro");

はぁ?もはやリーダブルじゃねーぞ、と思うだろうが説明しよう。/(?!)# myouji = /xというのは正規表現であり、最後のxは「空白とコメントを無視する」というオプションである。

問題は最初の(?!)だろう。なぜこれが必要なのかというと、単なる//xだと「無」にマッチすることになりマッチが成功してしまうため、(?!)をつけることで意味を逆にして意図的にマッチを失敗させているのである。これによって評価が偽になるので、正規表現の評価結果はサブルーチンに渡されなくなる。

しかしこの方法は欠点があり、暗黙の$_評価があるため$_に何らかの値が入っているとマッチ成功になってしまう。従ってこの方法は使えない。他にはもう方法が思いつかなかった。

結論

インラインコメントは無理

tokuhiromtokuhirom2012/08/30 10:15そもそも Perl の場合、パラメータがおおい場合は fullname(timeout_ms => 10, use_encryption => false) のようにハッシュでわたすので必要ありませんね。この方法はC言語の貧弱さをおぎなうためのBKなのでは?

2011-10-16

Windowsでperl6.exe(2011.09版)をビルドする はてなブックマーク -  Windowsでperl6.exe(2011.09版)をビルドする - Perl Tech

Windowsでrakudo 2011.09版のビルドに成功したので、その方法を解説します。perl6を実際に触ってみたい方はぜひどうぞ。(しかし、触る以前に情報が少なすぎるから困る)

用意するもの

perlgccの実行ファイルの場所を環境変数PATHに通しておくこと。

Parrotのビルド

Parrotの圧縮ファイルを展開し、その中のConfigure.plを以下のように実行する。これでC:\parrot\binにparrot.exe等の実行ファイルがインストールされる。

parrot>perl Configure.pl --optimize --prefix="C:/parrot"
parrot>mingw32-make
parrot>mingw32-make install

NQPのビルド

NQPはそのままではエラーが出てビルドできない。まず、NQPの圧縮ファイルを展開したらtools/lib/NQP/Configure.pmのコードを以下のように修正する。

if ($^O eq 'MSWin32') {
    # $text =~ s{/}{\\}g; ここをコメントアウトする

さらにVERSIONというファイルの中身が"2011.05"になっているので、"2011.09-8-ge3d5c8"に変更する。そうしないとrakudoのバージョンチェックに引っかかるので。

そして以下のように実行

nqp>perl Configure.pl --with-parrot="C:/parrot/bin/parrot.exe"

ここでMakefileが出来るが、このMekefileの中身を以下のように修正する。

# PERL          = C:\strawberry\perl\bin\perl.exe
PERL          = C:/strawberry/perl/bin/perl.exe \を/に変更するだけ

そのままビルドするとlibparrot.dllが見つからずエラーになるので、nqpのフォルダにビルドしたlibparrot.dllをコピーしておく。

そしてmake installするとC:\parrot\binにnqp.exeがインストールされる。

nqp>mingw32-make
nqp>mingw32-make install

Rakudoのビルド

rakudoの圧縮ファイルを展開し、libparrot.dllをrakudoのフォルダにコピーしておく。そして以下のように実行すればC:\parrot\binにperl6.exeがインストールされる。あとはC:\parrot\binを環境変数PATHに追加すれば完了。

rakudo>perl Configure.pl --with-nqp="C:/parrot/bin/nqp.exe"
rakudo>mingw32-make
rakudo>mingw32-make install