my @all_keywords = (qw(one two three ));
my @mandatory_keywords = (qw(two three ));
my $source1 =
q{ONE="xyz\t" two=a_34 three = 'name="O\'Hara"' };
my $source2 = <<'END';
two=a_34
three = 'name="O\'Hara"'
ONE="xyz\t"
END
####
my %statement = (
one => 'xyz\t',
two => 'a_34',
three => q{name="O\'Hara"},
);
##
##
#!/usr/bin/perl -w
use strict;
my @all_keywords = (qw(one two three four five));
my @mandatory_keywords = (qw(two three four ));
my $RE_value = qr/
(\w+) # (1) a keyword
\s* = \s* # an equal sign with optional spaces
(?: # quoted keyword ...
( #
[\'\"\`] # (2) a quoting character
)
( # (3) the quoted value:
(?: # either
\\\2 # an escaped quote
| # or
[^\2] # any non-quote character
)
+? # repeat (non-greedily)
)
\2 # until the initial quote shows up again
|
(\S+) # (4) ... bare word value
)
/x;
sub set_value {
my ($stat, $kw, $value) = (@_);
# case insensitive keyword
return 0 unless exists $stat->{lc $kw};
$stat->{lc $kw} = $value;
return 1
}
sub parse_pairs {
my $src = shift;
my %statement = map {$_, undef} @all_keywords;
for ($src) {
while ( ! m/ \G \s* \z /gcx ) {
my $result = 0;
if ( /\G \s* $RE_value \s* /xgc ) {
$result = set_value( \%statement, $1, $4 ? $4 : $3 );
}
else {
die "syntax error >" . substr($_, pos) ."\n";
}
die "invalid keyword $1 \n" unless $result;
}
}
return \%statement;
}
sub check_pairs {
my $statement = shift;
for my $kw (@all_keywords) {
if (defined $statement->{$kw}) {
print "$kw \t -> <$statement->{$kw}>\n"
}
else {
warn "- missing keyword <$kw>!\n"
if grep {$kw eq $_} @mandatory_keywords;
}
}
}
my @sources = (
q{ ONE="xyz\t" two=a_34 three = 'name="O\'Hara"' four=`'one' two` five = ah! },
q{
five = ah!
ONE="xyz\t"
three = 'name="O\'Hara" two=a_34'
four=`'one' two`
});
for (@sources) {
print "\n>>Source: //$_//\n\n";
my $stat = parse_pairs($_);
check_pairs($stat);
}
__END__
output:
>>Source: // ONE="xyz\t" two=a_34 three = 'name="O\'Hara"' four=`'one' two` five = ah! //
one ->
two ->
three ->
four -> <'one' two>
five ->
>>Source: //
five = ah!
ONE="xyz\t"
three = 'name="O\'Hara" two=a_34'
four=`'one' two`
//
one ->
- missing keyword !
three ->
four -> <'one' two>
five ->
##
##
q{one="two=xyz" two=abc}
# ^embedded keyword pattern
q{one="xyz two=abc three= efg"}
# ^missing quotes^