in reply to Parse::RecDescent Grammar Questions

make_parser.pl, generates the parser. Run it to create VCSConfigParser.pm.

use strict; use warnings; use Parse::RecDescent qw( ); my $grammar = <<'EOG'; <autotree> { # These affect the entire parser. use strict; use warnings; sub dequote { my $s = $_[0]; $s =~ s/^"//; $s =~ s/"\z//; return $s; } } parse : stmt(s) /\Z/ stmt : clause | def clause : "include" pathname # Pathname may or may not be surrounded by double quotes pathname : STRING | BAREWORD def : IDENT def_[ $item[1] ] { $item[2] } def_ : { $arg[0] eq "cluster" ?1:0 } IDENT "(" attr(s?) ")" | { $arg[0] eq "system" ?1:0 } IDENT "(" attr(s?) ")" attr : ATTRNAME '=' attr_val attr_val : ident | string | number | key_list | assoc_list val : ident | string | number # These aren't inlined because of <autotree> ident : IDENT string : STRING number : NUMBER key_list : '{' <leftop: IDENT /[,;]/ IDENT> '}' assoc_list : '{' <leftop: key_value /[,;]/ key_value> '}' key_value : IDENT '=' val # === Tokens === IDENT : /[a-zA-Z]\w*/ { $item[1] } ATTRNAME : /[a-zA-Z][\w@]*/ { $item[1] } STRING : /"(?:[^"]+)"/ { dequote($item[1]) } NUMBER : /\d+/ { $item[1] } # Need work. BAREWORD : /(?:[^"]+)/ { $item[1] } EOG Parse::RecDescent->Precompile($grammar, 'VCSConfigParser') or die("Bad grammar\n");

test.pl, a sample program that uses the parser.

use strict; use warnings; use VCSConfigParser qw( ); use Data::Dumper qw( Dumper ); #$::RD_TRACE = ''; my $vcs_parser = VCSConfigParser->new(); my $vcs_config = do { local $/; <DATA> }; my $tree = $vcs_parser->parse( $vcs_config ); print Dumper $tree; __DATA__ include "types.cf" include "LBSybase.cf" include "OracleTypes.cf" cluster vcs ( UserNames = { vcs = X1Nh6WIWs6ATQ } Administrators = { vcs } CounterInterval = abc ) system njengsunvcs1 ( ) system njengsunvcs2 ( )

Notes:

Replies are listed 'Best First'.
Re^2: Parse::RecDescent Grammar Questions
by gmarler (Sexton) on May 21, 2008 at 01:58 UTC
    Thanks very much - that's exactly what I was looking for. And very nice tips to boot.

    Still trying to wrap my head around exactly how this does it's job:

    def        : IDENTdef_[ $item[1] ]

    But I'll run it through with the -RD_TRACE flag a few times to figure it out...

    Now to build a sensible data structure out of all this parsed data - gotta think about this a bit.

      It passes an argument ($item[1], which contains what IDENT matched) to def_, which can access it via @arg.
        Yes, didn't notice the discussion of Subrule Argument Lists - got it now.