Perlで行うことのできるもう1つのことは、 "(?{...})"を使ってPerlコードを正規表現に直接埋め込むことです。したがって、正規表現のどの部分がマッチしたかを示す変数を設定することができます。警告:あなたの正規表現には、正規表現に補間される(埋め込まれたPerlコード以外の)変数は含まれていないか、エラーが発生します。
my $kind;
my $REGEX = qr/
[A-Za-z][\w]* (?{$kind = 'IDENT';})
| (?: ==? | != | <=? | >=?) (?{$kind = 'OP';})
| -?\d+ (?{$kind = 'INT';})
| \x27 ((?:[^\x27] | \x27{2})*) \x27 (?{$kind = 'STRING';})
| \S (?{$kind = 'OTHER';})
/xs;
my $line = "if (x == 'that') then x = -23 and y = 'say ''hi'' for me';";
my @tokens;
while ($line =~ /($REGEX)/xsg) {
my($match, $str) = ($1,$2);
if ($kind eq 'STRING') {
$str =~ s/\x27\x27/\x27/g;
push(@tokens, ['STRING', $str]);
}
else {
push(@tokens, [$kind, $match]);
}
}
foreach my $lItems (@tokens) {
print("$lItems->[0]: $lItems->[1]\n");
}
次出力します:ここでは、この機能使用するサンプルパーサーです
IDENT: if
OTHER: (
IDENT: x
OP: ==
STRING: that
OTHER:)
IDENT: then
IDENT: x
OP: =
INT: -23
IDENT: and
IDENT: y
OP: =
STRING: say 'hi' for me
OTHER: ;
それは一種の不自然だが、しかし、あなたはわかりますその文字列の前後に引用符(実際には、アポストロフィ) (また、連続した引用符は一重引用符に畳まれています)、一般的に、$ kind変数だけが、パーサが識別子や引用符付きの文字列を見たかどうかを示します。
がすばらしく見えます。 – dividebyzero
モジュールのREADMEの "Tracking"セクションに必要なものが見つかりました。 - 私は特定のパターンマッチで派遣する必要があった。素晴らしいツール。 – dividebyzero