Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Friday August 26, 2005
06:50 PM

Extending the Higher Order Perl Parser.pm module

[ #26476 ]

A few days ago I wrote my first BNF grammar after already having a parser which implemented it. One section specifies how one can search between two values:

  between_value  ::= 'BETWEEN' '[' value ','  value ']'
                   | 'BETWEEN' '[' value '=>' value ']'
                   |           '[' value ','  value ']'
                   |           '[' value '=>' value ']'

That's more or less equivalent to the following regex:

/(?:BETWEEN)?\s*\[\s*$value\s*(?:,|=>)\s*$value\s*\]/

The HOP parser, of course, can handle this, but it doesn't handle it as gracefully as I would like, so I extended it.

concatenate(
    absorb( optional( match( KEYWORD => 'BETWEEN' ) ) ),
    absorb($lbracket),
    $Value,
    absorb($either_comma),
    $Value,
    absorb($rbracket),
),

match() is the new name of the old &_ function. absorb() means "match this but throw away the value." optional() means "0 or 1 of the following value."

All things told, this makes things much easier to read and allows us to skip many of the annoying transformations that were required to get rid of of unwanted values.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Couldn't you make another description for the operator, e.g.

    op ::= ','|'=>'

    and rewrite that as

    between_value ::= 'BETWEEN' '[' value op value ']'
                    |           '[' value op value ']'

    ?

    Or if you were using EBNF,

    between_value ::= ['BETWEEN'] '[' value op value ']'