in reply to Dynamic expansion of tokens with Parse::RecDescent

This will produce a spiffy data structure for you. I'm assuming that you can get the array into is_valid_color cleanly.
use Parse::RecDescent; use strict; use Data::Dumper; sub is_valid_color { my $color_to_test = shift(); return $color_to_test if ($color_to_test =~ /red|green|blue/); return undef; } my $grammar = << 'GRAMMAR'; start : order(s) order: quantity color product { $return = { quant => $item{'quantity'}, color => $item{'color'}, item => $item{'product'}, }; } quantity: /\d+/ color: /\w+/ { $return = main::is_valid_color($item[1]); } | <error> product: 'pencil' | 'pen' GRAMMAR my $text; $text = "1 red pencil\n"; $text .= "2 blue pencil\n"; $text .= "4 green pen\n"; my $parser = new Parse::RecDescent($grammar) || die "Bad Grammar"; my $product_list = $parser->start($text) || die "Bad Syntax"; print Dumper($product_list);
output is
$VAR1 = [ { 'color' => 'red', 'item' => 'pencil', 'quant' => '1' }, { 'color' => 'blue', 'item' => 'pencil', 'quant' => '2' }, { 'color' => 'green', 'item' => 'pen', 'quant' => '4' } ];
I changed item to product to avoid confusion with the multiple contexts of item. Also, you must put pencil before pen as Recdescent will find the first match not the longest match. /pen/ will match both pen and pencil so put pencil first.

Replies are listed 'Best First'.
Re^2: Dynamic expansion of tokens with Parse::RecDescent
by ikegami (Patriarch) on Aug 18, 2004 at 22:04 UTC

    Can you try running that $text .= "5 purple pen\n"; added? I don't think you'll get an error (although the colour will be 'undef' in the result). I can't verify this for myself since I don't have this module.

    Update: Nevermind, I see something in the docs I didn't see before, concernign the returning values of actions.. I think the | <error> is unnecessary, btw. That's what confused me.

      It will die with a bad syntax error I believe. There is more error handling that can be done I just didn't do it.

      I think the error tag will give you a little more detail on where the error occured etc. I didn't have a ton of time to play around with it.