9

In perl6 grammars, as explained here (note, the design documents are not guaranteed to be up-to-date as the implementation is finished), if an opening angle bracket is followed by an identifier then the construct is a call to a subrule, method or function.

If the character following the identifier is an opening paren, then it's a call to a method or function eg: <foo('bar')>. As explained further down the page, if the first char after the identifier is a space, then the rest of the string up to the closing angle will be interpreted as a regex argument to the method - to quote:

 <foo bar>

is more or less equivalent to

 <foo(/bar/)>

What's the proper way to use this feature? In my case, I'm parsing line oriented data and I'm trying to declare a rule that will instigate a seperate search on the current line being parsed:

#!/usr/bin/env perl6
# use Grammar::Tracer ;

grammar G {
    my $SOLpos = -1 ;   # Start-of-line pos

    regex TOP {  <line>+  }

    method SOLscan($regex) {
        # Start a new cursor
        my $cur = self."!cursor_start_cur"() ;

        # Set pos and from to start of the current line
        $cur.from($SOLpos) ;
        $cur.pos($SOLpos) ;

        # Run the given regex on the cursor
        $cur = $regex($cur) ;

        # If pos is >= 0, we found what we were looking for
        if $cur.pos >= 0 {
            $cur."!cursor_pass"(self.pos, 'SOLscan')
        }

        self
    }

    token line {
        { $SOLpos = self.pos ; say '$SOLpos = ' ~ $SOLpos }
        [
        || <word> <ws> 'two' { say 'matched two' }  <SOLscan \w+> <ws> <word>
        || <word>+ %% <ws>    { say 'matched words' }
        ]
        \n
    }

    token word  {  \S+  }
    token ws    {  \h+  }
}

my $mo = G.subparse: q:to/END/ ;
hello world
one two three
END

As it is, this code produces:

$ ./h.pl
$SOLpos = 0
matched words
$SOLpos = 12
matched two
Too many positionals passed; expected 1 argument but got 2
  in method SOLscan at ./h.pl line 14
  in regex line at ./h.pl line 32
  in regex TOP at ./h.pl line 7
  in block <unit> at ./h.pl line 41
$

Line 14 is $cur.from($SOLpos). If commented out, line 15 produces the same error. It appears as though .pos and .from are read only... (maybe :-)

Any ideas what the proper incantation is? Note, any proposed solution can be a long way from what I've done here - all I'm really wanting to do is understand how the mechanism is supposed to be used.

jjmerelo
  • 22,578
  • 8
  • 40
  • 86
Marty
  • 2,788
  • 11
  • 17
  • Out of curiosity, are the methods `cursor_start_cur()` and `cursor_pass()` documented anywhere? I could not find any in [class Cursor](https://docs.perl6.org/type/Cursor) – Håkon Hægland May 07 '18 at 09:37
  • 2
    Not formerly, as they're considered "internals." It's a little out of date, but edument's Rakudo internals course (https://edumentab.github.io/rakudo-and-nqp-internals-course/slides-day2.pdf) has some information half way down "day 2". Also, you can read the source (Luke) here: https://github.com/perl6/nqp/blob/master/src/QRegex/Cursor.nqp – Marty May 07 '18 at 10:03
  • 1
    @Marty if they are considered internals, shouldn't there be a way of defining that function without using them? – jjmerelo May 07 '18 at 10:13
  • @Marty also, if they are Cursor methods, would `self` be a Cursor? Or shouldn't you extract the cursor from the current match? (which is `$/`, I guess) – jjmerelo May 07 '18 at 10:17
  • @jjmerelo - I think there should be some way to do it without using those functions - I just wanted to "try everything" before asking other to come to my aid. self is a Cursor - have a look at how and are implemented (Ref in earlier comment) - you're supposed to call cursor-start-cur to get a new one (well, as far as I can make out...) – Marty May 07 '18 at 10:49
  • 1
    You can advance the cursor by return a `Match` object from the regex. But I can't get it to work in this case. The regex that's passed as an argument also comes out as `ForeignCode`, not as `Regex`, which makes me suspect that the feature might not work all that well in Rakudo at all. – moritz May 07 '18 at 15:14
  • 2
    moritz - my guess is that compiled regex (QAST::Regex nodes) are seen as ```ForeignCode``` as far as the main slang is concerned. – Marty May 07 '18 at 21:49
  • @Marty do you need another scalar to hold the "from" position? Something like `$cur.from($SOLfrom) ;` ? It seems that lines 14-15 just jump the `$SOLpos` value around a bit. Also (unless I've misunderstood), `.from` seems to be set by a successful match, while `:pos` appears to be a match adverb (with possibly different syntax requirements). See: https://docs.raku.org/routine/from#(Match)_method_from and https://docs.raku.org/language/regexes#Pos – jubilatious1 Dec 01 '20 at 05:08

1 Answers1

0

It does not seem to be in the corresponding directory in roast, so that would make it a "Not Yet Implemented" feature, I'm afraid.

jjmerelo
  • 22,578
  • 8
  • 40
  • 86