Alien has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks!

I started to learn to use Parse::RecDescent , and I wrote a simple parser that should extract all numbers within a line . However , I only get the first number . Here is the code I am using :
use strict; use warnings; use Parse::RecDescent; my $grammar = q( START: numbers numbers: number(s) number:/\d+/ { print "found a number"; } ); Parse::RecDescent->new($grammar)->START("123 foo 345 bar");


I think the logical thing for my script to do would be to print "found a number" twice . Could you please tell me what I'm doing wrong?

Replies are listed 'Best First'.
Re: My issues with Parse::RecDescent
by JadeNB (Chaplain) on Aug 26, 2008 at 19:53 UTC
    Your parser has no way of knowing how to handle non-numbers, so it stops after the first number because there's nothing more it can parse. You could try something like
    START: ( number | word )(s)
    and add the rule
    word: /\w+/,
    if that's what you want.

    UPDATE: Oops, I forgot that the 'one-or-more' quantifier in Parse::RecDescent is (s), not +. Fixed.

      I tried modifying the script , but now I get an error calling the constructor :
      use strict; use Parse::RecDescent; my $grammar = q( START: ( number | word )+ word: /\w+/ { print "found a word\n"; } number: /\d+/ { print "found a number\n"; } ); Parse::RecDescent->new($grammar)->START("123 geo 456 bam");

      I know I'm a pain in the a** , but please bear with me .
        D:\>perl use strict; use Parse::RecDescent; my $grammar = q( START: ( number | word )+ word: /\w+/ { print "found a word\n"; } number: /\d+/ { print "found a number\n"; } ); Parse::RecDescent->new($grammar)->START("123 geo 456 bam"); __END__ ERROR (line 2): Untranslatable item encountered: "+" (Hint: Set $::RD_HINT (or -RD_HINT if you're using "pe +rl -s") for hints on fixing these problems.) Can't call method "START" on an undefined value at - line 10. D:\>perl $::RD_HINT=1; use strict; use Parse::RecDescent; my $grammar = q( START: ( number | word )+ word: /\w+/ { print "found a word\n"; } number: /\d+/ { print "found a number\n"; } ); Parse::RecDescent->new($grammar)->START("123 geo 456 bam"); __END__ ERROR (line 2): Untranslatable item encountered: "+" (Hint: Did you misspell "+" or forget to comment it ou +t?) Can't call method "START" on an undefined value at - line 11. D:\>perl $::RD_HINT=1; use strict; use Parse::RecDescent; my $grammar = q( START: ( number | word )(s) word: /\w+/ { print "found a word\n"; } number: /\d+/ { print "found a number\n"; } ); Parse::RecDescent->new($grammar)->START("123 geo 456 bam"); __END__ found a number found a word found a number found a word
Re: My issues with Parse::RecDescent
by JavaFan (Canon) on Aug 26, 2008 at 19:57 UTC
    Since you only match numbers (and, by default, whitespace between tokens is skipped), the parser will stop after matching 123.

    There's no rule to "consume" the foo part, so the parser cannot reach 345.

    You will have to decide what you allow between numbers, and write rules accordingly. Perhaps the simplest way is to set the skip to /\D+/. It's been a few years since I last used Parse::RecDescent, so I won't shame myself in showing the wrong syntax, but Parse::RecDescent is pretty well documented, and you should be able to find the skip syntax easily.

    To be clear, the skip is a regular expression (default: /\s*/) that skips "whitespace" between tokens.