# New Ticket Created by Dino Morelli
# Please include the string: [perl #35971]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=35971 >
I implemented unit testing for subrules. I added new code to
Parrot::Test::PGE which accepts a ref to an array of arrays containing
named rules, generating the PIR to compile and store the rules in a
loop. Documentation changes to the POD are also included.
Also included is a new t/p6rules script to exercise it.
There are potentially lots of ways to go about this, this is just a
first crack at it. It's sort of a big change, let me know what I'm
missing. :)
files:
M MANIFEST
M lib/Parrot/Test/PGE.pm
A t/p6rules/subrules.t
-Dino
--
.~. Dino Morelli
/V\ email: [EMAIL PROTECTED]
/( )\ weblog: http://categorically.net/d/blog/
^^-^^ preferred distro: Debian GNU/Linux http://www.debian.org
Index: MANIFEST
===================================================================
--- MANIFEST (revision 8164)
+++ MANIFEST (working copy)
@@ -1740,6 +1740,7 @@
t/p6rules/capture.t []
t/p6rules/cclass.t []
t/p6rules/escape.t []
+t/p6rules/subrules.t []
t/p6rules/ws.t []
t/perl/Parrot_Distribution.t [devel]
t/perl/Parrot_Docs.t [devel]
Index: lib/Parrot/Test/PGE.pm
===================================================================
--- lib/Parrot/Test/PGE.pm (revision 8164)
+++ lib/Parrot/Test/PGE.pm (working copy)
@@ -10,6 +10,13 @@
use Parrot::Test::PGE;
p6rule_is('abc', '^abc', 'BOS abc');
+ p6rule_is(" int argc ",
+ [
+ [ type => 'int | double | float | char' ],
+ [ ident => '\w+' ],
+ [ _MASTER => ':w<type> <ident>' ],
+ ],
+ "simple subrules test");
p6rule_isnt('abc', '^bc', 'BOS bc');
p6rule_like('abcdef', 'bcd', qr/0: <bcd @ 1>/, '$0 capture');
@@ -31,33 +38,63 @@
=item C<p6rule_is($target, $pattern, $description)>
Runs the target string against the Perl 6 pattern, passing the test
-if they match. Note that the pattern should be specified as a string
-and without leading/trailing pattern delimiters. (Hint: if you try
-using qr// for the $pattern then you're misreading what this does.)
+if they match. Note that patterns should be specified as strings
+and without leading/trailing pattern delimiters.
+(Hint: if you try using qr// for the $pattern then you're misreading
+what this does.)
+
+subrules: In addition to a simple scalar string, the pattern can be a
+reference to an array of arrays. Containing subrules that refer to each
+other. In this form:
+
+ [
+ [ name1 => 'pattern 1' ],
+ [ name2 => 'pattern 2' ],
+ [ name3 => '<name1> pattern 3' ],
+ [ _MASTER => '<name1> <name2> <name3>' ],
+ ],
+
+The last rule, labelled with _MASTER, is the rule that your target string
+will be matched against. The 'outer rule' if you will.
+
=cut
sub p6rule_is {
my ($target, $pattern, $description) = @_;
- Parrot::Test::pir_output_is(
+ if (ref $pattern) {
+ Parrot::Test::pir_output_is(
+ Parrot::Test::PGE::_generate_subrule_pir($target, $pattern),
+ 'matched',
+ $description);
+ } else {
+ Parrot::Test::pir_output_is(
Parrot::Test::PGE::_generate_pir_for($target, $pattern),
'matched',
$description);
+ }
}
=item C<p6rule_isnt($target, $pattern, $description)>
-Runs the target string against the Perl 6 pattern, passing the test
-if they do not match.
+Runs the target string against the Perl 6 pattern, passing the test if
+they do not match. The same pattern argument syntax above applies here.
=cut
sub p6rule_isnt {
my ($target, $pattern, $description) = @_;
- Parrot::Test::pir_output_is(
+ if (ref $pattern) {
+ Parrot::Test::pir_output_is(
+ Parrot::Test::PGE::_generate_subrule_pir($target, $pattern),
+ 'failed',
+ $description);
+ } else {
+ Parrot::Test::pir_output_is(
Parrot::Test::PGE::_generate_pir_for($target, $pattern),
'failed',
$description);
+ }
}
=item C<p6rule_like($target, $pattern, $expected, $description)>
@@ -125,7 +162,58 @@
match_end:
.end\n);
}
-
+
+sub _generate_subrule_pir {
+ my($target, $pattern) = @_;
+ $target = _parrot_stringify($target);
+
+ # Beginning of the pir code
+ my $pirCode = qq(
+ .sub _PGE_Test
+ .local pmc p6rule_compile
+ load_bytecode "PGE.pbc"
+ find_global p6rule_compile, "PGE", "p6rule"
+
+ .local string target
+ .local pmc rulesub
+ .local pmc match
+ .local string name
+ .local string subpat
+
+ target = "$target"\n\n);
+
+ # Loop to create the subrules pir code
+ for my $ruleRow (@$pattern) {
+ my ($name, $subpat) = @$ruleRow;
+ $subpat = _parrot_stringify($subpat);
+
+ $pirCode .= qq(
+ name = "$name"
+ subpat = "$subpat"
+ rulesub = p6rule_compile(subpat)\n);
+
+ last if $name eq '_MASTER';
+
+ $pirCode .= qq(
+ store_global name, rulesub\n\n);
+ }
+
+ # End of the pir code
+ $pirCode .= qq(
+ match = rulesub(target)
+
+ unless match goto match_fail
+ match_success:
+ print "matched"
+ goto match_end
+ match_fail:
+ print "failed"
+ match_end:
+ .end\n);
+
+ return $pirCode;
+}
+
=back
=head1 AUTHOR
--- /dev/null 2005-05-25 09:27:40.465681720 -0400
+++ t/p6rules/subrules.t 2005-05-25 11:10:10.687678360 -0400
@@ -0,0 +1,39 @@
+use strict;
+use warnings;
+use Parrot::Test tests => 4;
+use Parrot::Test::PGE;
+
+
+p6rule_is (" int argc ",
+ [
+ [ type => 'int | double | float | char' ],
+ [ ident => '\w+' ],
+ [ _MASTER => ':w<type> <ident>' ],
+ ],
+ "simple subrules");
+
+p6rule_isnt("doggy",
+ [
+ [ type => 'int | double | float | char' ],
+ [ ident => '\w+' ],
+ [ _MASTER => ':w<type> <ident>' ],
+ ],
+ "simple subrules");
+
+p6rule_is ("(565) 325-2935",
+ [
+ [ digits => '\d+' ],
+ [ exch => '\(<digits>\)' ],
+ [ _MASTER => ':w<exch> <digits>-<digits>' ],
+ ],
+ "nested subrules");
+
+p6rule_isnt("0-900-04-41-59",
+ [
+ [ digits => '\d+' ],
+ [ exch => '\(<digits>\)' ],
+ [ _MASTER => ':w<exch> <digits>-<digits>' ],
+ ],
+ "nested subrules");
+
+# Don't forget to change the number of tests :-)