Exporting regexes from grammars
Asked Answered
M

1

8

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

Microtone answered 8/10, 2018 at 6:6 Comment(0)
T
7

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.

Torrie answered 8/10, 2018 at 9:45 Comment(7)
I guess that's a difference then between subs and regexes, the default scope and definition. I don't think that's documented...Microtone
The scope aspect is documented at has. (For that aspect a regex is the same as a method.) I don't recall seeing the signature variance documented. It presumably is to do with the way a regex/token/rule is a method but also is different. I've updated my answer but I'm still pondering it and may return to update it later.Torrie
I'm checking out the signature of regex numbers is export { <[\d]>+ }; via say Word.^lookup("numbers").signature; and it happens to be (Word: *%_). That implies that it needs to be invoked by a Word. Let's see how that can be hacked...Microtone
I would say that regex|token|rule are actually method, not subs. They have an implicit has, but the problem is not the scope, but the fact that the methods have an implicit invocant in the signature. In that sense, you can't meaningfully import methods from classes. In that sense, prefixing them with my or our makes them actually behave like subs, thus they don't have anything attached, thus they can be exported.Microtone
"I would say that regex|token|rule are actually method, not subs." Is that addressed to me or to others? If addressed to me are you saying so to suggest I edit my answer? I certainly didn't mean to suggest otherwise. I got lazy as I wrote some comments in this exchange. I was trying to connect with you, specifically, and assumed you knew that regexes are actually methods. If I'm to edit my answer, perhaps the way to say it is that regexes are methods but regexes aren't methods (like grammars are classes but grammars aren't classs). But that overly downplays how different they are imo.Torrie
to you, but of course do whatever you want, it's your answer and it's great anyway. And as a matter of fact, regexes|rules|tokens are methods unless they have a lexical scoper, in which case they are subs.Microtone
@Microtone Thanks. "regexes|rules|tokens are methods unless they have a lexical scoper, in which case they are subs." Well, I totally get your point, but they still have an invocant in their signature and will still typecheck as methods, not subs. I'll sleep on it and probably edit my answer tomorrow.Torrie

© 2022 - 2024 — McMap. All rights reserved.