Phoenix.pm: Parameter parser

Hal Goldfarb codewell at earthlink.net
Mon Dec 2 17:31:42 CST 2002


I highly approve of your coding style and modular breakdown (similar to 
mine).  Consistency is wonderful  : )

-Hal

On Monday 02 December 2002 01:25 pm, Doug Miles wrote:
> 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