Phoenix.pm: Parameter parser
Doug Miles
doug.miles at bpxinternet.com
Mon Dec 2 14:25:24 CST 2002
Doug Miles wrote:
> Doug Miles wrote:
>
>> Hey all,
>>
>> I just implemented a parser that takes something like this:
>>
>> command param1 param2="value2" param3="value3 \"foo\""
>>
>> and puts the parameters and values into a hash. The value for param1
>> would be "1". I'm not sure I implemented it the best way, though. I
>> thought I'd get some ideas from you folks to get a different
>> perspective. I'll post what I did after I get some responses. I
>> don't want to contaminate your thinking. :)
>>
>>
>
> I left out a few details that I forgot to mention. There can be
> optional whitespace around the '=' and command may be a command, a
> scalar, an array, or a method call. What the program does from there
> depends on which it is. Right now the program is putting the data in an
> array, but this will change to a hash in the future. Oh, and ignore the
> $tag_parser parameter. :)
>
> I have to pay around with Scott and Eden's examples some more, but here
> is what I did (I'm sure the formatting will be screwed up):
Thanks for the input guys. I did consider using Parse::RecDescent, but
it seemed a little heavyweight for this application. I realized that in
my previous program, I was putting the regexes in array context, which
screwed up the /g \G combination:
if(my ($match, $scalar) = $tag_content =~ /\G^(\$([a-zA-Z0-9_:.]+))/)
{
pos($tag_content) += length($match);
}
This caused me to have to manually update the position pointer. If you
just use the numbered variables instead, everything works out:
if($tag_content =~ /\G^\$([a-zA-Z0-9_:.]+)\s*/gc)
{
$scalar = $1;
}
I learned this the hard way. :)
I worked on this some more, and this is what I have now:
#!/usr/bin/perl
use strict;
use warnings;
use Regexp::Common;
my $tag_content = '$scalar param1 param2="\"test2\""';
my @parameters = process_tags('', $tag_content);
print join('|', @parameters) . "\n\n";
$tag_content = q{@array format="'test3'" default_format="test4"};
@parameters = process_tags('', $tag_content);
print join('|', @parameters) . "\n\n";
$tag_content = q{%hash format="'test5'" default_format="test6"};
@parameters = process_tags('', $tag_content);
print join('|', @parameters) . "\n\n";
$tag_content = <<"EOD";
command
doug =
"test7"
julie =
"test8"
EOD
@parameters = process_tags('', $tag_content);
print join('|', @parameters) . "\n\n";
$tag_content = 'command "doug"="test7" julie="test8"';
@parameters = process_tags('', $tag_content);
print join('|', @parameters) . "\n\n";
# process_tags #########################################################
sub process_tags
{
my $tag_parser = shift;
my $tag_content = shift;
my $scalar;
my $array;
my $hash;
my $command;
my @parameters;
print "\$tag_content: $tag_content\n";
while(pos($tag_content) < length($tag_content))
{
if($tag_content =~ /\G^\$([a-zA-Z0-9_:.]+)\s*/gc)
{
$scalar = $1;
}
elsif($tag_content =~ /\G^\@([a-zA-Z0-9_:.]+)\s*/gc)
{
$array = $1;
}
elsif($tag_content =~ /\G^\%([a-zA-Z0-9_:.]+)\s*/gc)
{
$hash = $1;
}
elsif($tag_content =~ /\G^([a-zA-Z0-9_:.]+)\s*/gc)
{
$command = $1;
}
elsif($tag_content =~
/
\G # Start at last match pos.
(
([a-zA-Z0-9_:.]+) # A parameter.
(?:
\s*?=\s*? # '=' & optional WS.
$RE{delimited}{-delim=>'"'}{-esc=>'\\'}{-keep} # '"'
delimited
# value.
)?\s*
)
/gcx # / Fix VIM syntax highlighting problem.
)
{
my $match = $1;
my $parameter = $2;
my $value = defined($5) ? $5 : 1;
$value =~ s/\\"/"/g;
push(@parameters, ($parameter, $value));
}
else
{
die "$tag_content\n" . ' ' x pos($tag_content) . "^\n";
}
}
return @parameters;
}
# program output #
$tag_content: $scalar param1 param2="\"test2\""
param1|1|param2|"test2"
$tag_content: @array format="'test3'" default_format="test4"
format|'test3'|default_format|test4
$tag_content: %hash format="'test5'" default_format="test6"
format|'test5'|default_format|test6
$tag_content: command
doug =
"test7"
julie =
"test8"
doug|test7|julie|test8
$tag_content: command "doug"="test7" julie="test8"
command "doug"="test7" julie="test8"
^
More information about the Phoenix-pm
mailing list