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

I have a perl program that will parse a file that contains many options (far too many to pass as command line options). The options are in a format like this:
# comment
# comment
global {
   option_one => some value,
   option_two => some value
}
table {
   name => blah,
   some_opt => blah,
   columns => {
      col1 {
        col_option => stuff,
        col_option2 => stuff
      }
      col2 {
        col_option => stuff
      }
   }
}
I'm not wedded to this syntax - I'm working on specifying it from the user side - but in general there's several blocks, each of which have directives (not all of which always appear), and some directives have sub-directives. My question...is this a job for Parse::RecDescent? I've never worked with BNF grammar before.

Replies are listed 'Best First'.
Re: Is this a job for Parse::RecDescent?
by roboticus (Chancellor) on Nov 29, 2010 at 23:33 UTC

    raindog308:

    If you're not wed to that syntax, perhaps you should investigate one of the Config modules on cpan, such as Config::JSON, Config::General, etc.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      or even Config::Any::XML
      nice sig roboticus. another one i liked recently = just hand over the chocolate and nobody gets hurt.
      the hardest line to type correctly is: stty erase ^H
Re: Is this a job for Parse::RecDescent?
by JavaFan (Canon) on Nov 29, 2010 at 23:22 UTC
    It could be a job for Parse::RecDescent. But Parse::RecDescent is well, a recursive descent parser. Which means, it doesn't take short cuts. It's very general. It will explore and explore and explore, and backtrack and explore and explore and do some more backtracking, and then start all over again before deciding "nope, no way, absolutely no way this is going to match". While powerful, it's not efficient.

    Your syntax looks simple enough that you can parse it with a limited look-ahead parser, which doesn't backtrack more than the number of tokens it looks ahead.

    Usually, much faster. But you may have to do a lot more work to have a parser. So, you have to make a trade off. How much programming time are you willing to spend to speed up the runtime. Of course, if the files you're going to parse are small, or if the grammar is simple, or if the data is such that it never backtracks anyway, Parse::RecDescent maybe fast enough anyway.

    There's no easy answer to this question.

      It's not hard to write a single-token lookahead parser with P::RD. There's no reason to do any backtracking with that grammar. That doesn't mean P::RD isn't slow.

Re: Is this a job for Parse::RecDescent?
by kcott (Archbishop) on Nov 30, 2010 at 07:03 UTC

    This is somewhat speculative and is based on "I'm not wedded to this syntax" and without knowing exactly what's in some value, stuff and so on.

    Adding a few commas in strategic places (e.g. changing global { to global => {) will result in a Perl hash structure. You could read this and access your options like this:

    $opt_hash->{table}{columns}{col1}{col_option2}

    -- Ken

      Thanks everyone for the great suggestions. I will look at perhaps using JSON or XML instead - not sure why that never occurred to me! Ken, simply making it as a hash is another interesting idea - I'll have to ultimately see what's easiest for users. Thanks so much all!
Re: Is this a job for Parse::RecDescent?
by locked_user sundialsvc4 (Abbot) on Nov 30, 2010 at 17:37 UTC

    I have grown very fond of YAML as a storage-format.   It is well-supported, and a definite “plus” is that it is easily human-readable.   But it might not be suitable for a file that you intend to be human-edited.   (XML would probably be the best choice for that.)