パーザのみを独立したモジュールにすると、なにかと便利ですね。
Parse::RecDescent を使った簡単なパーザを試作してみました。
EUCコードで入出力することを前提していますので、nkf からパイプしてください。今回は動作確認だけなので、chalow とはデータ構造が異なります。いずれは chalow 互換になる予定です。
RecDescentを使うと、ChangeLog の論理構造を記述するだけですむので(作るのはたいへんだったけど結果的には)非常にシンプルになります。
#! perl -w
# Parse ChangeLog
# Copyright: (C) Project PaoPei with zuihu 2004 JAPAN
# $Id: remoteclog.txt,v 1.2 2004/12/06 08:58:45 zuihu Exp $
package ParseChangeLog;
use strict;
use Parse::RecDescent;
use Data::Dumper;
our $VERSION = '0.1';
my $grammar = q(
file: entry(s)
{
my %file;
for (@{$item[1]})
{
(my $date = $_->[1]->[0]->[0]) =~ s/\-//og;
$file{$date} = $_->[1];
}
\%file;
}
entry: entryheader item(s)
{
my @entry;
push @entry, $item[1], $item[2];
[ $item[1], \@entry ];
}
entryheader: date user
{[$item[1], $item[2]]}
| date
{[$item[1]]}
date: /\d{4}-\d\d-\d\d/ /(\s\(.+?\))?/
{$item[1]}
user: /.+/
{$item[1]}
item: itemheader itembody(s)
{ [$item[1], $item[2]] }
| itemheader
{ [$item[1]] }
itemheader: /^\* / /([^\:]+)/ /:\s*/
{$item[2]}
itembody: /^(?!(\* .+?:|\d{4}-\d\d\-\d\d))(.*)/
{$item[1]}
);
my $text;
{
local $/ = undef;
$text = <STDIN>;
}
my $log = Parse::RecDescent->new($grammar)->file($text);
print Dumper($log);