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