- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!!!技術的雑談-PPIを使ってみる
!!環境
*OS:CentOS3.5
*perl:5.8.0(OS Installそのまま)
!!PPIとは
Perlを構文解析し、Perl Scriptの中から参照・操作できるようにするための物です。
構文解析されたPerl ScriptはPDOM(Perl Document Object Model)というObject形式になっているようです。
!!PPIのInstall
今回使用したCentOS3.5のperlにはPPI packageが入っていませんでした。
CPANを使えば簡単にInstallできるのかもしれませんが、今回はネットに繋がっていないサーバだったので手動でInstallしました。
!CPANよりPPI-1.199_02.tar.gzを入手
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/PPI-1.199_02.tar.gz
!PPIの展開とInstall
tarで展開し、作成されたPPI-1.199ディレクトリにcdして、
$ perl Makefile.PL
でMakefileの作成を行ないますが、その際に
Checking if your kit is complete...
Looks good
Warning: prerequisite Clone 0.22 not found.
Warning: prerequisite Digest::MD5 2.27 not found. We have 2.20.
Warning: prerequisite File::Spec 0.84 not found. We have 0.83.
Warning: prerequisite IO::String 1.07 not found.
Warning: prerequisite List::MoreUtils 0.13 not found.
Warning: prerequisite List::Util 1.18 not found. We have 1.09.
Warning: prerequisite Params::Util 0.10 not found.
Warning: prerequisite Storable 2.14 not found. We have 2.06.
Warning: prerequisite Task::Weaken 0 not found.
Warning: prerequisite Test::ClassAPI 1.03 not found.
Warning: prerequisite Test::Object 0.07 not found.
Writing Makefile for PPI
と、出るので、必要なモジュールを別途入手しました。
どのModuleも基本的には「展開」「cd」「perl Makefile.PL」「make」「make test」「make install(root権限で)」でInstallされます。
(どうも.pmではなくNative binaryを含むModuleがあるようです。)
!Clone 0.22
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/R/RD/RDF/Clone-0.22.tar.gz
!Digest::MD5
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/G/GA/GAAS/Digest-1.15.tar.gz
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/G/GA/GAAS/Digest-MD5-2.36.tar.gz
但し、Digest::base 1.00が必要とのWarnningが出る。
Warning: prerequisite Digest::base 1.00 not found.
なので、Digest::baseを先にInstallする。
!File::Spec
これはPathTool 3.24に入っている。
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/K/KW/KWILLIAMS/PathTools-3.24.tar.gz
!IO::String
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/G/GA/GAAS/IO-String-1.08.tar.gz
!List::MoreUtils
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/V/VP/VPARSEVAL/List-MoreUtils-0.21.tar.gz
!Params::Util
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/G/GB/GBARR/Scalar-List-Utils-1.19.tar.gz
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/Params-Util-0.23.tar.gz
但し、Params::Utilのperl Makefile.PL時にScalar::Utilが必要といわれるので先にInstallする。
Warning: prerequisite Scalar::Util 1.14 not found. We have 1.09.
!Storable
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AM/AMS/Storable-2.15.tar.gz
!Task::Weaken
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/M/MS/MSCHWERN/ExtUtils-MakeMaker-6.32.tar.gz
(http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/Y/YV/YVES/ExtUtils-Install-1.41.tar.gz)
(http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/R/RK/RKOBES/ExtUtils-Command-1.13.tar.gz)
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/Task-Weaken-0.99.tar.gz
但し、Task::Weakenのmake installの時に原因不明のエラーが出る。
これはExtUtils::MakeMakerのVersionが古いことにより発生しているっぽい。
今回はExtUtils::Install→ExtUtils::Command→ExtUtils::MakeMakerの順でアップデートしたが、ExtUtils::MakeMakerを入れるまでTask::Weakenのエラーメッセージに変化がなかったのでExtUtils::MakeMakerだけでも良いかもしれない。
もしExtUtils::MakeMakerをアップデートする前にTask::Weakenのperl Makefile.PLを行なった場合は、一度make cleanしてperl Makefile.PLから再度やり直す必要があるらしい。
!Test::ClassAPI
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/Config-Tiny-2.10.tar.gz
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/Class-Inspector-1.16.tar.gz
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/Test-ClassAPI-1.04.tar.gz
これも依存性の関係で上記の順番でInstallしないとperl Makefile.PLでWarnningが出る。
!Test::Object
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/M/MS/MSCHWERN/Test-Simple-0.70.tar.gz
http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/authors/id/A/AD/ADAMK/Test-Object-0.07.tar.gz
これも依存性の関係で上記の順番でInstallしないとperl Makefile.PLでWarnningが出る。
このほかにも、使っているperlのバージョン、OSのディストリビューションなどによって必要だったり更新したりするパッケージが変わるかもしれない。
また、PPI自体がまだVersion 1.0未満なので頻繁に更新されるっぽい。
!!PPIを試す
下記のようなテストプログラムを作ってみる。
#!/usr/bin/perl
use strict;
# a comment.
use Dumpvalue;
package ABC;
$ABC::value1 = 100;
@ABC::array1 = ('A', 'B', 'C');
%ABC::hash1 = ( 'X' => '1', 'Y' => '2', 'Z' => '3' );
print "*** start ***\n\n";
print "\$ABC::value1 = $ABC::value1 \n";
foreach my $i (@ABC::array1) {
print "\$ABC::array1[$i] = $ABC::array1[$i] \n";
}
foreach my $i (sort keys(%ABC::hash1)) {
print "\$ABC::hash1{'$i'} = $ABC::hash1{$i} \n";
}
my $ret = function1($ABC::value1);
print "\$ret = $ret\n";
exit 0;
sub function1
{
my $val = shift;
print "Hello $val !!!! \n";
}
0;
これをtest1.plとして保存しておく。
ちなみに実行すると以下のような結果が表示される。
*** start ***
$ABC::value1 = 100
$ABC::array1[A] = A
$ABC::array1[B] = A
$ABC::array1[C] = A
$ABC::hash1{'X'} = 1
$ABC::hash1{'Y'} = 2
$ABC::hash1{'Z'} = 3
Hello 100 !!!!
$ret = 1
さらに、以下のScriptを入力する。
こちらはtest2.plとして保存する。
#!/usr/bin/perl
use strict;
use PPI;
use PPI::Dumper;
my $document = PPI::Document->new($ARGV[0]);
my $dumper = PPI::Dumper->new($document);
$dumper->print;
exit(0);
これらができたところで、
$ perl test2.pl test1.pl
として実行すると、下記のようにtest1.plのPerl scriptが構文解析され、Object化されていることがわかる。
PPI::Document
PPI::Token::Comment '#!/usr/bin/perl\n'
PPI::Token::Whitespace '\n'
PPI::Statement::Include
PPI::Token::Word 'use'
PPI::Token::Whitespace ' '
PPI::Token::Word 'strict'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Token::Comment '# a comment.\n'
PPI::Token::Whitespace '\n'
PPI::Statement::Include
PPI::Token::Word 'use'
PPI::Token::Whitespace ' '
PPI::Token::Word 'Dumpvalue'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement::Package
PPI::Token::Word 'package'
PPI::Token::Whitespace ' '
PPI::Token::Word 'ABC'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Symbol '$ABC::value1'
PPI::Token::Whitespace ' '
PPI::Token::Operator '='
PPI::Token::Whitespace ' '
PPI::Token::Number '100'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Symbol '@ABC::array1'
PPI::Token::Whitespace ' '
PPI::Token::Operator '='
PPI::Token::Whitespace ' '
PPI::Structure::List ( ... )
PPI::Statement::Expression
PPI::Token::Quote::Single ''A''
PPI::Token::Operator ','
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''B''
PPI::Token::Operator ','
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''C''
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Symbol '%ABC::hash1'
PPI::Token::Whitespace ' '
PPI::Token::Operator '='
PPI::Token::Whitespace ' '
PPI::Structure::List ( ... )
PPI::Token::Whitespace ' '
PPI::Statement::Expression
PPI::Token::Quote::Single ''X''
PPI::Token::Whitespace ' '
PPI::Token::Operator '=>'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''1''
PPI::Token::Operator ','
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''Y''
PPI::Token::Whitespace ' '
PPI::Token::Operator '=>'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''2''
PPI::Token::Operator ','
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''Z''
PPI::Token::Whitespace ' '
PPI::Token::Operator '=>'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Single ''3''
PPI::Token::Whitespace ' '
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Word 'print'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Double '"*** start ***\n\n"'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Word 'print'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Double '"\$ABC::value1 = $ABC::value1 \n"'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Statement::Compound
PPI::Token::Word 'foreach'
PPI::Token::Whitespace ' '
PPI::Token::Word 'my'
PPI::Token::Whitespace ' '
PPI::Token::Symbol '$i'
PPI::Token::Whitespace ' '
PPI::Structure::ForLoop ( ... )
PPI::Statement
PPI::Token::Symbol '@ABC::array1'
PPI::Token::Whitespace ' '
PPI::Structure::Block { ... }
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\t'
PPI::Statement
PPI::Token::Word 'print'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Double '"\$ABC::array1[$i] = $ABC::array1[$i] \n"'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement::Compound
PPI::Token::Word 'foreach'
PPI::Token::Whitespace ' '
PPI::Token::Word 'my'
PPI::Token::Whitespace ' '
PPI::Token::Symbol '$i'
PPI::Token::Whitespace ' '
PPI::Structure::ForLoop ( ... )
PPI::Statement
PPI::Token::Word 'sort'
PPI::Token::Whitespace ' '
PPI::Token::Word 'keys'
PPI::Structure::List ( ... )
PPI::Statement::Expression
PPI::Token::Symbol '%ABC::hash1'
PPI::Token::Whitespace ' '
PPI::Structure::Block { ... }
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\t'
PPI::Statement
PPI::Token::Word 'print'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Double '"\$ABC::hash1{'$i'} = $ABC::hash1{$i} \n"'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement::Variable
PPI::Token::Word 'my'
PPI::Token::Whitespace ' '
PPI::Token::Symbol '$ret'
PPI::Token::Whitespace ' '
PPI::Token::Operator '='
PPI::Token::Whitespace ' '
PPI::Token::Word 'function1'
PPI::Structure::List ( ... )
PPI::Statement::Expression
PPI::Token::Symbol '$ABC::value1'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Word 'print'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Double '"\$ret = $ret\n"'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Word 'exit'
PPI::Token::Whitespace ' '
PPI::Token::Number '0'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement::Sub
PPI::Token::Word 'sub'
PPI::Token::Whitespace ' '
PPI::Token::Word 'function1'
PPI::Token::Whitespace '\n'
PPI::Structure::Block { ... }
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\t'
PPI::Statement::Variable
PPI::Token::Word 'my'
PPI::Token::Whitespace ' '
PPI::Token::Symbol '$val'
PPI::Token::Whitespace ' '
PPI::Token::Operator '='
PPI::Token::Whitespace ' '
PPI::Token::Word 'shift'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\t'
PPI::Statement
PPI::Token::Word 'print'
PPI::Token::Whitespace ' '
PPI::Token::Quote::Double '"Hello $val !!!! \n"'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Number '0'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Token::Whitespace '\n'
!!PPI::Documentの使い方
''これから書きます''
!!PPI::Nodesの使い方
''これから書きます''
!!何ができるのか?
''これから書きます''
perldocによると、
*ソースコードからDocumentを起こすツール
*コードチェッカー(ロジックチェック)
*バグ検出ツール
などに使えるっぽいです。
!!参照
*CAPNのPPIのページ
http://search.cpan.org/~adamk/PPI-1.199_02/lib/PPI.pm
PPI::Document、PPI::Node、PPI::Elementなどへのリンクもあります。
!!履歴
2007/03/20 -- 初版(書きかけ)
[[技術的雑談]]へ戻る
!!突っ込み
{{comment}}
[[技術的雑談]]へ戻る
{{trackback}}
[[技術的雑談]]へ戻る