次の入力があります
@Book{press,
author = "Press, W. and Teutolsky, S. and Vetterling, W. and Flannery B.",
title = "Numerical {R}ecipes in {C}: The {A}rt of {S}cientific {C}omputing",
year = 2007,
publisher = "Cambridge University Press"
}
RecDescent パーサー ジェネレーターの文法を書かなければなりません。出力時のデータは、xml 構造に合わせて変更する必要があり、次のようになります。
<book>
<keyword>press</keyword>
<author>Press, W.+Teutolsky, S.+Vetterling, W.+Flannery B.</author>
<title>Numerical {R}ecipes in {C}: The {A}rt of {S}cientific {C}omputing</title>
<year>2007</year>
<publisher>Cambridge University Press</publisher>
</book>
追加の繰り返しフィールドはエラーとして報告する必要があります (行番号を含む適切なメッセージで、それ以上の解析は行われません)。私はこのようなものから始めようとしました:
use Parse::RecDescent;
open(my $in, "<", "parsing.txt") or die "Can't open parsing.txt: $!";
my $text;
while (<$in>) {
$text .= $_;
}
print $text;
my $grammar = q {
beginning: "\@Book\{" keyword fields "\}" { print "<book>\n",$item[2],$item[3],"</book>"; }
keyword: /[a-zA-Z]+/ "," { return " <keyword>".$item[1]."</keyword>\n"; }
fields: one "," two "," tree "," four { return $item[1].$item[3].$item[5].$item[7]; }
one: "author" "=" "\"" /[a-zA-Z\s\.\,\{\}\:]+/ "\"" { $item[4] =~ s/\sand\s/\+/g;
return " <author>",$item[4],"</author>\n"; }
two: "title" "=" "\"" /[a-zA-Z\s\.\,\{\}\:]+/ "\"" { $item[4] =~ s/\sand\s/\+/g;
return " <title>",$item[4],"</title>\n"; }
three: "year" "=" /[0-2][0-9][0-9][0-9]/ { return " <year>",$item[3],"</year>\n"; }
four: "publisher" "=" "\"" /[a-zA-Z\s\.\,\{\}\:]+/ "\""
{ $item[4] =~ s/\sand\s/\+/g;
return " <publisher>",$item[4],"</publisher>\n"; }
};
my $parser = new Parse::RecDescent($grammar) or die ("Bad grammar!");
defined $parser->beginning($text) or die ("Bad text!");
しかし、それが正しい方法であるかどうかさえわかりません。助けてください。
もう 1 つ小さな問題があります。入力時のタグは特定の順序ではない場合がありますが、各タグは一度しか表示できません。(著者、タイトル、年、発行者) のすべての順列に対してサブルールを作成する必要がありますか? 私が思いついたので:
fields: field "," field "," field "," field
field: one | two | three | four
しかし、明らかにタグの繰り返しを妨げません。