Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exporting regexes from grammars

Tags:

grammar

raku

Grammars are classes and, as such, they should get to be subject to the same rules as other classes. However, there seems to be a problem with exporting regexes from a Grammar:

grammar Word {
    token TOP { ^ <letters> $}
    regex letters   is export { <[\w] - [_]>+ };
    sub exported () is export  { return 'exported' };
}

import Word;

say exported;
say "what_ever" ~~ &letters;

import effectively imports exported and it does not complain about letters. However, there's this error in the last line:

Type check failed in binding to parameter '<anon>'; expected Word but got Match (Match.new(orig => "what_ev...)

The same error happens if &letters is changed to /<letters>/, which is the other way to invoke regexes. The error seems to point out to letters having some hidden argument when they are declared within a grammar, because this works:

module Regexes {
    my regex letters   is export { <[\w] - [_]>+ };
}
import Regexes;
say "what_ever" ~~ /<letters>/;
# Output: 
# 「what」
#  letters => 「what」

So what would effectively be that parameter? How could we effectively use exported regexes/tokens/rules from a Grammar

like image 355
jjmerelo Avatar asked Oct 08 '18 06:10

jjmerelo


1 Answers

Prefix the letters regex declaration with a my or our.

By default a method, regex, token, or rule declarator is declared with an implicit has declarator preceding it.


I'm still pondering what else is going on here but wanted to update my answer in reaction to your first comment.

Type check failed in binding to parameter '';
expected Word but got Match (Match.new(orig => "what_ev...)

The parameter '' bit is definitely Less Than Awesome.

Curiously the signature of routines declared with a my method or our method have the enclosing class or grammar as their type, with an assumption of Mu if they're declared in the mainline, whereas for regex, token, or rule, the invocant is always Mu:

grammar g {
          method method              { ... }  # (g $: *%_)
      has method has-method          { ... }  # (g $: *%_)
      my  method my-method is export { ... }  # (g $: *%_)

          regex  regex               { ... }  # (g $: *%_)
      has regex  has-regex           { ... }  # (g $: *%_)
      my  regex  my-regex is export  { ... }  # (Mu $: *%_)

          sub    sub is export       { ... }  # ()
#     has sub    has-sub is export   { ... }  # Cannot use 'has' with sub declaration
      my  sub    my-sub is export    { ... }  # ()
}

import g;

say .signature
  for g.^lookup('method'),
      g.^lookup('has-method'),
      &my-method,
      g.^lookup('regex'),
      g.^lookup('has-regex'),
      &my-regex,
      &sub,
      &my-sub

displays the signature for each routine declaration in the grammar. I've added the output as comments at the end of each routine.

like image 116
raiph Avatar answered Nov 03 '22 19:11

raiph