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

Hi

I am writing a library for which I need to define a grammar to read a few special statements. For parsing this grammar I am using Parse::RecDescent library. The grammar is working fine but there is only one catch.

For a few rules, I want to catch a particular value and store it in an object while that rule should return different tokens.

For example, for statement 'file("abcd")', I want to check existence of file and return tokens '-e "abc"' but I also want to store the filename "abc" to keep track of all files that were accessed.

Is there any way to keep track of all the file names?

Replies are listed 'Best First'.
Re: Parse grammar via RecDescent parser
by Anonymous Monk on May 17, 2016 at 11:56 UTC
    Youve heard of arrays? Use an array, or a hash
Re: Parse grammar via RecDescent parser
by the_dark_lord (Novice) on May 17, 2016 at 13:18 UTC
    Hi I would use arrays or a hash if I could. I would have to specify that array in the grammar which would mean that it would be inside the parser's namespace and cannot be accessed from outside. I am looking for some way I could store the data in the parser itself and then retrieve later after all statements in the file have been tokenized.

      You know that you can get the parse tree from Parse::RecDescent with the <autotree> directive? This should give you all the data that is available in the structure and content of your source file.

      Maybe you can show us a short, workable example of maybe 20-35 lines that shows what you have and where you are trying to get to?

      Why would you need to specify the array in the grammar? Your plan is to store the data in the parser.

      But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)

      Hi

      My grammar rule looks like the following:

      file_exists: 'file(' filename ')' { $return = "-e $item{ 'filename' } }
      Now I would want this rule to do two things: 1) return the string "-e < filename>" so that I can eval it later and check existence of that file 2) store the file names which I can retrieve later

      I can achieve only one of the two from the grammar that I have. I want to do both.

        Why not store both, the string and the filename?

        file_exists: 'file(' filename ')' { $return = [ "-e $item{ 'filename' }", $item{ 'filename' +}] }

        guessing...

        file_exists: 'file(' filename ')' { $return = "-e $item{ 'filename' }; push @somepackagename +::savedfilenames, $item{ 'filename' } }

        Then outside the parser, retrieve the array as @somepackagename::savedfilenames

Re: Parse grammar via RecDescent parser
by polettix (Vicar) on May 19, 2016 at 13:21 UTC
    You might use $thisparser->{local} to collect stuff along the way (as opposed to using package variables):
    #!/usr/bin/env perl use strict; use warnings; use Parse::RecDescent; use Data::Dumper; my $grammar = <<'END'; foo: word(s) word: /\S+/ { push @{$thisparser->{local}}, lc $item[1]; $return = uc $item[1]; } END my $parser = Parse::RecDescent->new($grammar); my $what = $parser->foo("Foo bAr baZ"); print Dumper $what, $parser->{local}; __END__ $VAR1 = [ 'FOO', 'BAR', 'BAZ' ]; $VAR2 = [ 'foo', 'bar', 'baz' ];
    The docs say that ... the use of $this...->{local} is always safe. You will have to reset this field if you plan to call the same parser multiple times and you don't want each run to add its items to those of the previous runs. And, of course, nothing prevents you from using local for storing more complicated data structures.

    This said, I suggest that you read Corion's advices again. It seems like you're trying to mix parsing and evaluation, which might not be the wisest thing to do.

    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Io ho capito... ma tu che hai detto?