Dear Monks
Suppose I want to match text like this:
{ hello }
{{ hello }}
{{{ hello }}}
I started simply by writing a grammar to match the two brace string:
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. #$::RD_TRACE = 1; #Trace parsers' behaviour my $text = <<'END_OF_TEXT'; {{ hello }} END_OF_TEXT my $grammar = <<'END_OF_GRAMMAR'; { use 5.012; use Data::Dumper; } startrule: lbrace(2) 'hello' rbrace(2) lbrace: / [{] /xms rbrace: / [}] /xms END_OF_GRAMMAR my $parser = Parse::RecDescent->new($grammar) or die "Bad grammar!\n"; defined $parser->startrule($text) or die "Can't match text";
Then I tried to adjust the grammar to make the rbrace subrule dynamic. My idea was to use <rulevar:> to declare a local variable called $lbrace_count:
startrule: <rulevar: $lbrace_count>
Then use an action to assign $lbrace_count the number of lbraces that matched:
startrule: lbrace(2) { $lbrace = length $item[1] } 'hello' rbrace(2)
The grammar above still matches.
Next I used <matchrule:> to create the string 'rbrace(2)'. According to the docs, you are supposed to put an unquoted series of characters after the colon in <matchrule:> and then P::RD will put the series of characters inside a qq{} to produce the name of a subrule:
startrule: <rulevar: $lbrace_count> startrule: lbrace(2) { $lbrace_count = length $item[1] } 'hello' <matchrule: rbrace($lbrace_count)> lbrace: / [{] /xms rbrace: / [}] /xms
But that produces a weird error that I can't sort out:
Unknown starting rule (Parse::RecDescent::namespace000001::rbrace(18)) + called at prd1.pl line 39.
In fact, I can't even get the following simplification to work:
startrule: lbrace(2) 'hello' <matchrule: rbrace(2)> lbrace: / [{] /xms rbrace: / [}] /xms --output:-- Unknown starting rule (Parse::RecDescent::namespace000001::rbrace(2)) +called at prd1.pl line 39.
Here's the complete program:
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. $::RD_TRACE = 1; #Trace parsers' behaviour my $text = <<'END_OF_TEXT'; {{ hello }} END_OF_TEXT my $grammar = <<'END_OF_GRAMMAR'; { use 5.012; use Data::Dumper; } startrule: <rulevar: $lbrace_count> startrule: lbrace(2) { $lbrace_count = length $item[1] } 'hello' <matchrule: rbrace($lbrace_count)> lbrace: / [{] /xms rbrace: / [}] /xms END_OF_GRAMMAR my $parser = Parse::RecDescent->new($grammar) or die "Bad grammar!\n"; #ERRROR ON NEXT LINE ***************************** defined $parser->startrule($text) or die "Can't match text";
In reply to Parse::RecDescent: how does <matchrule:> work? by 7stud
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |