トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

技術的雑談-PPIを使ってみる

技術的雑談-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 -- 初版(書きかけ)

技術的雑談へ戻る

 突っ込み

name   comment  
URL (入力するとす ぱ むとみなします!)


技術的雑談へ戻る

TrackBack

TrackBack URL for this entry:
http://www.himajin2001.com/fswiki/tb.cgi/%B5%BB%BD%D1%C5%AA%BB%A8%C3%CC%2DPPI%A4%F2%BB%C8%A4%C3%A4%C6%A4%DF%A4%EB

技術的雑談へ戻る

最終更新日時:最終更新時間:2011年09月11日 11時29分45秒
トップページに戻る