Skip Menu |
 

This queue is for tickets about the Regexp-Grammars CPAN distribution.

Report information
The Basics
Id: 61416
Status: open
Priority: 0/
Queue: Regexp-Grammars

People
Owner: Nobody in particular
Requestors: whatson [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Access to parent subrule results
Download (untitled) / with headers
text/plain 892b
In my dabblings with Regexp::Grammars I found myself wanting to be able to use backrefs (ie. <\IDENT>) to access the results of a subrule in the parent rule, rather than the current rule. In Parse::RecDescent, this is possible by using subrule arguments, but it doesn't seem that something like this is supported in Regexp::Grammars. I've attached a patch (for 1.005) in which I've added the former behavior using a new subrule modifier '^', so that <^\IDENT> will get the result of <IDENT> from the parent rule, and <^^\IDENT> gets the result from the grandparent rule (and so on). This patch isn't exactly comprehensive... I haven't spent any time adding debugging or error handling support for the new modifier - perl throws an exception if you attempt to reach too high. Perhaps this feature or something like it could be considered for a future version of Regexp::Grammars.
Subject: parent_backref.diff
Download parent_backref.diff
text/x-diff 3.4k
=== added file 'demo/demo_indented_blocks.pl' --- demo/demo_indented_blocks.pl 1970-01-01 00:00:00 +0000 +++ demo/demo_indented_blocks.pl 2010-09-17 04:52:35 +0000 @@ -0,0 +1,72 @@ +use v5.10; +use warnings; + +use Data::Dumper qw< Dumper >; +use Regexp::Grammars; + +# +# The following grammar matches indented lines. +# Try it out with any indented text, from eg. ifconfig. +# + +my $grammar = qr{ + # Match all groups + \A <[group]>+ + + # Match a variable amount of whitespace + # - stored privately, so that it won't be included in the match result + <token: _indent> + \s* + + # Match a sequence beginning and ending with a non-whitespace character that is + # followed by some whitespace and a newline + # - don't include the trailing whitespace and newline in the match result + <token: data> + <MATCH=(?: \S (?: .* \S )? )> \s* \n + + # Match a line containing data, optionally followed by a group with deeper indentation + # - this keeps any nested groups associated with their preceding line + <token: line> + <data> + (?: + (?= <^\_indent> \s ) <group> + )? + + # Match a series of lines on the same indent level + # - any nested groups (with deeper indentation) will be captured by the <line> token + <token: group> + <_indent> + <[line]> ** <\_indent> + +}x; + +sub clean_match ($) { + my $match = shift; + + return $match unless ref $match; + + my @children; + + given (ref $match) { + when ('HASH') { + delete $match->{''}; + push @children, values %$match; + } + when ('ARRAY') { + push @children, @$match; + } + default { + warn 'unhandled ref type: ' . ref $match; + } + } + + clean_match($_) for @children; + + return $match; +} + +undef $/; +my $text = <>; +$Data::Dumper::Indent = 1; +$Data::Dumper::Sortkeys = 1; +print Dumper clean_match \%/ if $text =~ $grammar; === modified file 'lib/Regexp/Grammars.pm' --- lib/Regexp/Grammars.pm 2010-09-16 12:34:29 +0000 +++ lib/Regexp/Grammars.pm 2010-09-17 04:51:05 +0000 @@ -1239,13 +1239,13 @@ \[ (?<alias>(?&IDENT)) \s* = \s* (?<varname>(?&HASH)) \s* (?<keypat>(?&BRACES))? \s* \] ) | (?<backref> - \s* (?<slash> \\ | /) (?<subrule>(?&QUALIDENT)) \s* + \s* (?<carat> \^*) (?<slash> \\ | /) (?<subrule>(?&QUALIDENT)) \s* ) | (?<alias_backref> - (?<alias>(?&IDENT)) \s* = \s* (?<slash> \\ | /) (?<subrule>(?&QUALIDENT)) \s* + (?<alias>(?&IDENT)) \s* = \s* (?<carat> \^*) (?<slash> \\ | /) (?<subrule>(?&QUALIDENT)) \s* ) | (?<alias_backref_list> - \[ (?<alias>(?&IDENT)) \s* = \s* (?<slash> \\ | /) (?<subrule>(?&QUALIDENT)) \s* \] + \[ (?<alias>(?&IDENT)) \s* = \s* (?<carat> \^*) (?<slash> \\ | /) (?<subrule>(?&QUALIDENT)) \s* \] ) | (?<minimize_directive> @@ -1384,7 +1384,8 @@ ); } elsif ($+{backref} || $+{alias_backref} || $+{alias_backref_list}) { - my $backref = qq{\$Regexp::Grammars::RESULT_STACK[-1]{'$+{subrule}'}}; + my $level = -1 * (length($+{carat}) + 1); + my $backref = qq{\$Regexp::Grammars::RESULT_STACK[$level]{'$+{subrule}'}}; my $quoter = $+{slash} eq '\\' ? "quotemeta($backref)" : "Regexp::Grammars::_invert_delim($backref)"
Subject: Re: [rt.cpan.org #61416] Access to parent subrule results
Date: Fri, 17 Sep 2010 20:59:26 +1000
To: bug-Regexp-Grammars [...] rt.cpan.org
From: Damian Conway <damian [...] conway.org>
Download (untitled) / with headers
text/plain 947b
Hi Andrew, Funny story: a few weeks back I had the need for exactly the same ability. And implemented exactly the same idea (except I used a slightly different marker for upleveling...and frankly, I like the one you chose better). Then I played with the results for a few days and realized that, as handy as this feature was, it also creates excessive coupling between rules. It's really annoying to have to change the "up-references" when other rules change. So I reluctantly ripped it all out again and went ahead and implemented full subrule arguments. :-) I've been meaning to upload the improvements for a few weeks now, and your feature request has pushed me over the edge...so if you give it a few hours you should be able to download the new version and take advantage of full parametric subrules. I think you'll be pleased with how easy I've made it to pass captured data from a parent rule down into subrules. All the best, Damian
From: whatson [...] gmail.com
Download (untitled) / with headers
text/plain 115b
Hi Damian, The new subrule argument implementation fits the bill perfectly! Thanks for your work, Andrew Whatson


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.