in reply to Why won't this basic Parse::RecDescent example work?
use strict; use warnings; use 5.012; use Parse::RecDescent; $::RD_ERRORS = 1; #Parser dies when it encounters an error $::RD_WARN = 1; #Enable warnings - warn on unused rules &c. $::RD_HINT = 1; # Give out hints to help fix problems. our %HASH; my $grammar = <<'END_OF_GRAMMAR'; startrule : from_clause from_clause : 'from' dir(s) { print "-->$item{dir}<--\n"; $main::HASH{dirs} = $item{dir} } dir : m{/} END_OF_GRAMMAR my $parser = Parse::RecDescent->new($grammar); $parser->startrule("from ./"); use Data::Dumper; say Dumper(\%HASH); --output:-- $VAR1 = {};
Expected output:
-->./<-- $Var1 = { "dirs" => "./" };
|
---|
Replies are listed 'Best First'. | |||
---|---|---|---|
Re^2: Why won't this basic Parse::RecDescent example work?
by Athanasius (Archbishop) on Jan 28, 2013 at 08:58 UTC | |||
I’m not familiar with Parse::RecDescent, but by reference to the docs plus a bit of trial-and-error I got this to work by adjusting the regex and assigning $1 to a local variable (see the section “Start-up Actions” in Parse::RecDescent):
Output:
Note that setting $::RD_TRACE = 1; is useful for understanding what the parser is doing. Hope that helps,
| [reply] [d/l] [select] | ||
by 7stud (Deacon) on Jan 28, 2013 at 19:55 UTC | |||
I’m not familiar with Parse::RecDescent, Then thanks for being brave enough to take a look! by reference to the docs plus a bit of trial-and-error I got this to work by adjusting the regex and assigning $1 to a local variable. Nice going! After reading the "Start up Action" section in the docs, I reread the "Action" section, and I noticed this statement: The results of named subrules are stored in the hash under each subrule's name (including the repetition specifier, if any) So the key I was using in the %item hash, 'dir', was wrong. The key should be 'dir(s)'. So now I can get this output:
Partial success! Note the dereference of $item{'dir(s)'}. Now, what is that '1'? The return value from print()? But print() isn't the last statement of the action. If I change the dir rule to:
I get this output:
Is 2 the count of the words matched? What is going on? I am using the exact same array in each of these lines:
...yet I am getting different results 'hello world' v. 2! How is that possible? Argghh, of course! Perl doesn't care about giving you the exact same results for any expression you use--because perl determines the result by the context in which the expression appears. In my case, the print() statement supplies list context for the array, and "$main::... =" provides scalar context for the array--and an array provides its length in scalar context. So now I can get the expected output:
Next up, the regex problem. This doesn't work:
Note that I tried using the @item array this time. The first item in @item is the rule name, "from_clause", and the next items should be the matches for the subrules, so $item[2], or equivalently $item[-1], should be the matches for dir(s). But because I am not even seeing the arrows in my print statement, that means the parser isn't finding a match for my rule. I also notice there are weird rules the parser follows for comments. This does not cause an error:
...but this does cause an error:
Back to the regex problem. It seems that Parse::RecDescent takes the regex pattern and adds a ^ to the beginning of the pattern and adds $ to the end of the pattern. In other words, the regex you specify has to match all of the text you are interested in examining.
And reworking my original example:
Success! Thanks. | [reply] [d/l] [select] |