use strict; use warnings; use Parse::RecDescent qw( ); my $grammar = <<'EOG'; { # 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 ident : IDENT string : STRING number : NUMBER key_list : '{' '}' assoc_list : '{' '}' 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");