PPI icon indicating copy to clipboard operation
PPI copied to clipboard

anon hashref after operator treated as code block

Open moregan opened this issue 11 years ago • 4 comments

from https://github.com/Perl-Critic/Perl-Critic/issues/192 , hash constructor parses as a code block

ppidump '0 || {b => 1, a => 1};'
                    PPI::Document
                      PPI::Statement
[    1,   1,   1 ]     PPI::Token::Number       '0'
[    1,   3,   3 ]     PPI::Token::Operator     '||'
                        PPI::Structure::Block   { ... }
                          PPI::Statement
[    1,   7,   7 ]         PPI::Token::Word     'b'
[    1,   9,   9 ]         PPI::Token::Operator         '=>'
[    1,  12,  12 ]         PPI::Token::Number   '1'
[    1,  13,  13 ]         PPI::Token::Operator         ','
[    1,  15,  15 ]         PPI::Token::Word     'a'
[    1,  17,  17 ]         PPI::Token::Operator         '=>'
[    1,  20,  20 ]         PPI::Token::Number   '1'
[    1,  22,  22 ]     PPI::Token::Structure    ';'

At least some other operators do not parse it as a block:

ppidump '0, {b => 1, a => 1};'
                    PPI::Document
                      PPI::Statement
[    1,   1,   1 ]     PPI::Token::Number       '0'
[    1,   2,   2 ]     PPI::Token::Operator     ','
                        PPI::Structure::Constructor     { ... }
                          PPI::Statement::Expression
[    1,   5,   5 ]         PPI::Token::Word     'b'
[    1,   7,   7 ]         PPI::Token::Operator         '=>'
[    1,  10,  10 ]         PPI::Token::Number   '1'
[    1,  11,  11 ]         PPI::Token::Operator         ','
[    1,  13,  13 ]         PPI::Token::Word     'a'
[    1,  15,  15 ]         PPI::Token::Operator         '=>'
[    1,  18,  18 ]         PPI::Token::Number   '1'
[    1,  20,  20 ]     PPI::Token::Structure    ';'

moregan avatar Feb 04 '14 04:02 moregan

Request for comments: are there more operators that dictate that what follows them must be a hash constructor and not a block?

%PPI::Lexer::CURLY_CLASSES contains, among other things, operators that cannot be immediately followed by a code block. Some of those, like '+' and 'return', are documented as such; others like 'bless' and (I assume) '||=' were determined experimentally. Have there been problems in the past trying to expand the list of operators trusted to not be followed by blocks? Can PPI take another bite out of the block/hash constructor ambiguity problem via these operators?

E.g., these compile (under 5.16.3 and 5.8.8):

perl -WE 'my $x = 0; $x ||= {};'
perl -WE 'my $x = 1; $x &&= {};'

and these don't:

perl -WE 'my $x = 0; $x ||= {;};'
perl -WE 'my $x = 1; $x &&= {;};'

The number of operators that don't accept a block on the right side appears to be large: ||, &&, &&=, //, //=, to name a few.

moregan avatar Feb 05 '14 06:02 moregan

Doing it manually this way is not strictly right. There are plenty of things a hash could come after, but in many cases it is illegal code.

So I tend to ignore those cases.

Adam On Feb 4, 2014 10:54 PM, "moregan" [email protected] wrote:

Request for comments: are there more operators that dictate that what follows them must be a hash constructor and not a block?

%PPI::Lexer::CURLY_CLASSES contains, among other things, operators that cannot be immediately followed by a code block. Some of those, like '+' and 'return', are documented as such; others like 'bless' and (I assume) '||=' were determined experimentally. Have there been problems in the past trying to expand the list of operators trusted to not be followed by blocks? Can PPI take another bite out of the block/hash constructor ambiguity problem via these operators?

E.g., these compile (under 5.16.3 and 5.8.8):

perl -WE 'my $x = 0; $x ||= {};' perl -WE 'my $x = 1; $x &&= {};'

and these don't:

perl -WE 'my $x = 0; $x ||= {;};' perl -WE 'my $x = 1; $x &&= {;};'

The number of operators that don't accept a block on the right side appears to be large: ||, &&, &&=, //, //=, to name a few.

Reply to this email directly or view it on GitHubhttps://github.com/adamkennedy/PPI/issues/34#issuecomment-34141926 .

adamkennedy avatar Feb 05 '14 18:02 adamkennedy

Currently PPI disambiguates hashes and blocks by checking for a few cases where a hash interpretation of {} compiles and a block interpretation does not: 'scalar', '||=', ',', '=', '=>'. In practical terms:

  1. PPI should not be doing what it is doing
  2. PPI should be doing what it is doing, but no more, due to points not raised in this conversation yet
  3. PPI should be doing more of the same -- "not strictly right", but no less right that PPI in general. e.g.: &&=

Are you asserting (1) or (2)? If not, is there any reason to not pursue (3)?

moregan avatar Feb 05 '14 20:02 moregan

My general rule is that pp I should be able to correctly match all real world production code.

Adam On Feb 5, 2014 12:29 PM, "moregan" [email protected] wrote:

Currently PPI disambiguates hashes and blocks by checking for a few cases where a hash interpretation of {} compiles and a block interpretation does not: 'scalar', '||=', ',', '=', '=>'. In practical terms:

  1. PPI should not be doing what it is doing
  2. PPI should be doing what it is doing, but no more, due to points not raised in this conversation yet
  3. PPI should be doing more of the same -- "not strictly right", but no less right that PPI in general. e.g.: &&=

Are you asserting (1) or (2)? If not, is there any reason to not pursue (3)?

Reply to this email directly or view it on GitHubhttps://github.com/adamkennedy/PPI/issues/34#issuecomment-34236367 .

adamkennedy avatar Feb 05 '14 21:02 adamkennedy