6

I would like to match any Num from part of a text string. So far, this (stolen from from https://docs.perl6.org/language/regexes.html#Best_practices_and_gotchas) does the job...

    my token sign { <[+-]> }
    my token decimal { \d+ }
    my token exponent { 'e' <sign>? <decimal> }
    my regex float {
        <sign>?
        <decimal>?
        '.' 
        <decimal>
        <exponent>?
    }   
    my regex int {
        <sign>?
        <decimal>
    }   
    my regex num {
        <float>?
        <int>?
    }   
    $str ~~ s/( <num>? \s*) ( .* )/$1/;

This seems like a lot of (error prone) reinvention of the wheel. Is there a perl6 trick to match built in types (Num, Real, etc.) in a grammar?

librasteve
  • 6,832
  • 8
  • 30
  • 1
    The Perl 6 grammar in Rakudo is written in NQP, so there may be some differences which make it harder to use. Anyway it appears to be in `$?LANG` – Brad Gilbert Feb 25 '18 at 18:04
  • 1
    Jeffrey Goff was starting to pull some of these common reusable grammar bits into Grammar::Common: https://github.com/drforr/perl6-Grammar-Common. – Curt Tilmes Feb 25 '18 at 23:39
  • Grammar::Common would be ideal - I think that it may be a bit too unfinished - thanks for the pointer, I will follow it. – librasteve Feb 26 '18 at 18:43

1 Answers1

6

If you can make reasonable assumptions about the number, like that it's delimited by word boundaries, you can do something like this:

regex number {
   «     # left word boundary
   \S+   # actual "number"
   »     # right word boundary
   <?{ defined +"$/" }>
}

The final line in this regex stringifies the Match ("$/"), and then tries to convert it to a number (+). If it works, it returns a defined value, otherwise a Failure. This string-to-number conversion recognizes the same syntax as the Perl 6 grammar. The <?{ ... }> construct is an assertion, so it makes the match fail if the expression on the inside returns a false value.

moritz
  • 12,710
  • 1
  • 41
  • 63
  • 1
    Why is it necessary to stringify the match before coercing it to `Num`? What will be the difference here between `+"$/"` and `+$/`? – Eugene Barsky Feb 26 '18 at 08:02
  • 2
    The difference is that I haven't looked in the documentation what `prefix:<+>` does with a `Match` object, but I'm quite sure what it does with a `Str`. It might behave the same. – moritz Feb 26 '18 at 09:55
  • Hmmm- I see what you are getting at with coercion and guess that would throw an error? if did not succeed... in my case, the presence of a number (specifically a Real) is not guaranteed - so neither are the delimiters. Sooo - I can adapt this to get me a string speculatively and then fail gracefully if either empty or does not coerce successfully. That'd save about 12 lines of code... thanks for the hint! – librasteve Feb 26 '18 at 18:48
  • @p6steve a failed conversion to a number does not throw an exception, but rather returns a Failure. – moritz Feb 27 '18 at 20:21
  • properly speaking, that the syntax {}> is a Regex Boolean check rather than an assertion as clarified here https://stackoverflow.com/questions/63426361/raku-effect-of-capture-markers-is-lost-higher-up – librasteve Aug 17 '20 at 21:14