1

I am debugging a larger grammar, and was able to reduce the error to the following minimal example:

#! /usr/bin/env perl6

use v6;

my $str = q:to/END/;
bar baz, bak
END

class Actions {
    method arg-separator ($match-data) {
        my $match-str = $match-data.Str;
        if $match-str ~~ /^ \s+ $/ {
            make ", ";
        }
        else {
            make $match-str;
        }
    }
}

grammar Simple-Grammar {
    token TOP { ^ \s* [[<argument> <arg-separator>]* <argument>] \s* $ }

    token argument {
        [<!before <arg-separator>> . ]+  
    }

    token arg-separator {
        [<!before <eos>> \s+] || [\s* ',' [<!before <eos>> \s*]]
    }

    token eos { \s* $ }
}

Simple-Grammar.parse( $str, actions => Actions.new);

Output:

Cannot bind attributes in a Nil type object
  in method arg-separator at ./p.p6 line 16
  in regex arg-separator at ./p.p6 line 28
  in regex argument at ./p.p6 line 24
  in regex TOP at ./p.p6 line 22
  in block <unit> at ./p.p6 line 35

Line 16 is here

make $match-str;

I do not understand why $match-str is here a Nil type object ? The strange thing is that if I replace $match-str in line 16 with any constant string, for example make "xxx"; I still get the same error..

1
  • 2
    Think I found the mistake. I forgot that make operates on $/ by default, so I should use $match-data.make($match-str) instead when I don't use $/ as an input argument. The reason I did not use $/ from the beginning was that the regex match operator ~~ also uses $/, so there would be a conflict.. Commented Mar 7, 2018 at 7:51

1 Answer 1

3

Running make $match-str tries to attach $match-str as match data to $/, see the documentation. However, $/ is not what you perhaps thought it would be. The previous statement

$match-str ~~ /^ \s+ $/ 

sets $/ implicitly to Nil since the match failed. Hence, you get the error message:

Cannot bind attributes in a Nil type object

when trying to attach $match-str to $/. The solution is to not use $/ in this case, instead of

if $match-str ~~ /^ \s+ $/ {
    make ", ";
}
else {
    make $match-str;
}

you should explicitly call the make method on $match-data:

if $match-str ~~ /^ \s+ $/ {
    $match-data.make(", ");
}
else {
    $match-data.make($match-str);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.