I have recently had the good fortune of seeing TheDamian's Perl6::Rules tutorial. I have been playing with the module for a few hours now, and have a few observations.

I wouldn't use it in production (right now it only works in perl5.8.3) but I was able to get it to work. I did experience a few segfaults as I tried different features. Some of the other error indications spew mightily!

If you already know lex (or flex), Perl6::Rules will make a lot of sense. I like the way that the rules are declarative. This means that I can change the order of the rules without changing the functionality.

I suspect that Perl6::Rules and Parse::RecDescent can be combined to provide a decent API to implement the front end of a compiler. These may be an acceptable substitute for lex and yacc (or flex and bison).

Perl is already very strong in the data-format-translation domain, and will become much stronger in Perl6. This is because of the re-use capabilities inherent in the collections of regular expressions, which are called grammars.

Here is a simple example that checks if a string represents a number, including scientific notation. For example, it detects that -12e3 is a number but does not say that 1e.2 is a number. Notice that the code defines a grammar, which will be reusable in the same way that a module is reusable. Reusable grammars will increase a perl programmers productivity, since presumably many grammars will be available from CPAN.

use Perl6::Rules; grammar P6G_IsNumeric { rule oporm { <[+-]>? } rule fixed { <oporm> <digit>+ \.? <digit>* | <oporm> <digit>* \.? <digit>+ } rule scino { <fixed> <[eE]> <oporm> <digit>+ | <fixed> | <digit>+ + } } sub is_scino { my $num = shift; if ($num =~ m/^<P6G_IsNumeric.scino>$/) { $num = $num + 0; # is this really necessary? return $num; } return undef; } sub is_fixed { my $num = shift; if ($num =~ m/^<P6G_IsNumeric.fixed>$/) { $num = $num + 0; return $num; } return undef; }
It should work perfectly the first time! - toma

Replies are listed 'Best First'.
Re: Perl6::Rules Rules
by hv (Prior) on Aug 04, 2004 at 08:23 UTC

    I'm guessing "oporm" is short for "optional plus or minus", but it took me a while to guess that. I'd suggest replacing it with:

    rule sign { <[+-]> }
    and using <sign>? instead of <oporm> in the other rules to improve readability.

    The $num = $num + 0; ensures the returned result will be treated as a number if used in an ambiguous context, such as with a bitwise operator. So yes, if the is_* functions are documented to return a number it's helpful to do this.

    I'd normally expect a function 'is_thing' to be asking a question that returns a boolean though, and to use it like:

    if (is_fixed($string)) { ... it's a number ... }
    and would usually name functions such as yours more like 'as_thing':
    my $num = as_scino($string);

    Hugo

      The $num = $num + 0; ensures the returned result will be treated as a number if used in an ambiguous context, such as with a bitwise operator. So yes, if the is_* functions are documented to return a number it's helpful to do this.

      Would that he were using a real Perl6, he could just use unary + on the return to force numeric context:

      return +$num;

      This would remove the extra, potentially confusing addition which IMHO is a good thing. /me waits for Perl6 with bated breath.

        And in Perl5, of course, you just write

        return 0 + $num;

        :-)

        Makeshifts last the longest.

Re: Perl6::Rules Rules
by tilly (Archbishop) on Aug 04, 2004 at 14:55 UTC
    My understanding is that the Perl6 version of Perl6::Rules is meant as a replacement for Parse::RecDescent. That the Perl 5 version of the former is less capable than the latter is due to shortcomings in Perl's RE engine. (The same applies to the segfaults that you mentioned.)
Perl5 version
by sleepingsquirrel (Chaplain) on Aug 04, 2004 at 17:30 UTC
    Just for the heck of it, I'd thought I'd throw out the perl5 version...
    $oporm = qr{[+-]?}; $digit = qr{\d}; $fixed = qr{ $oporm $digit+ \.? $digit* | $oporm $digit* \.? $digit+ }x; $scino = qr{ $fixed [eE] $oporm $digit+ | $fixed | $digit+ }x; sub is_scino { my $num = shift; if ($num =~ m/^$scino$/) { $num = $num + 0; # is this really necessary? return $num; } return undef; } sub is_fixed { my $num = shift; if ($num =~ m/^$fixed$/) { $num = $num + 0; return $num; } return undef; }


    -- All code is 100% tested and functional unless otherwise noted.