in reply to Re: Regular Expressions and atomic weights
in thread Regular Expressions and atomic weights

Below is a refactoring that avoids using stuff from main. Using stuff from main prevents you from precompiling your grammar into a module. Also, using stuff from main makes the script incompatible with mod_perl. (I also lined up the productions.)

use Parse::RecDescent; my $g = Parse::RecDescent->new(<<'END_GRAMMAR'); { use List::Util 'sum'; use vars '%weights'; %weights = qw( C 12 O 16 Pb 207 ); } weight : compound { $item[1] } compound : group(s) { sum( @{$item[1]} ) } group : element /\d+/ { $item[1] * $item[2] } | element { $item[1] } element : /[A-Z][a-z]*/ { $weights{ $item[1] } } | "(" compound ")" { $item[2] } END_GRAMMAR print $g->weight("Pb(CO3)2"), $/; # prints 327

I was planning on doing P::RD solution for the OP, but I abandonned the idea when others pointed to existing specialized modules. Thanks for filling in the gap.

Update: The common start of both group productions is very innefficient. Fix:

weight : compound { $item[1] } compound : group(s) { sum( @{$item[1]} ) } group : element factor { $item[1] * $item[2] } factor : /\d+/ { $item[1] } | { 1 } element : /[A-Z][a-z]*/ { $weights{ $item[1] } } | "(" compound ")" { $item[2] }

Replies are listed 'Best First'.
Re^3: Regular Expressions and atomic weights
by Your Mother (Archbishop) on Jul 25, 2005 at 19:26 UTC

    That's hot™. Thanks to you and blokhead both for not ceasing to solve the problem. That's one of the more concise and edifying Parse::RecDescent examples I've seen.