首页 > 解决方案 > Perl 如何解析未引用的裸词?

问题描述

不带引号的词在 Perl 中似乎有很多含义。

print STDERR $msg;

$hash{key}

func( param => $arg )

my $x = str;

如何确定这些的含义?

标签: perlparsing

解决方案


下图显示 Perl 如何按优先级降序解析标识符。

::除非另有说明,否则它也适用于链接的标识符(我将其称为“合格标识符”)。

  1. 语法上定义的含义,当语法上预期时。

     sub foo { }          # «foo» («sub» is covered later)
     sub main::foo { }    # «main::foo» («sub» is covered later)
     method Class         # «Class» («method» is covered later)
     method Some::Class   # «Some::Class» («method» is covered later)
     $foo
     $main::foo
     //i
     =head
     <<FOO
     Class::
     Some::Class::
     LABEL:
    
  2. 字符串字面量,当后跟一个=>或当整个哈希索引表达式时。

    这不适用于合格的标识符。

     my %h = ( a => 1 );
     $h{a}
    
  3. 变量名,当整个解引用表达式。

     ${foo}
     ${main::foo}
    

    请注意,使用关键字、命名运算符或声明的子名称将导致ambiguous use警告。

  4. 关键词。

     while (1) { }
     sub { }
     use
     __END__
    
  5. 子调用,当一个先前导入的子的名称。

     use Time::HiRes qw( time );
     time
     main::time
    
  6. 调用命名列表运算符、命名一元运算符或命名空元运算符。

     print $x, $y, $z;
     $c = chr $i;
     $t = time;
     $t = CORE::time;
    
  7. 标签,当用作 、 或 的next操作数last时。redogoto

    将合格标识符视为标签会导致编译错误,因为标签不能是合格标识符。

     next LABEL;
    
  8. 子调用或内联常量,当名称为先前声明的子或常量时。

     sub foo { }
     foo                          # Calls sub «foo»
     main::foo                    # Calls sub «foo»
    
     sub bar;
     bar                          # Calls sub «bar»
    
     use constant FOO => 123;
     FOO                          # Replaced with the value of the constant.
    
  9. 间接方法调用,当后跟可能限定标识符、后缀为 的可能限定标识符::、标量(包括数组元素或散列元素)或块时。

     method Class           # Calls method «method» («Class» is covered earlier)
     method Some::Class     # Calls method «method» («Some::Class» is covered earlier)
     method Class::         # Calls method «method» («Class» is covered earlier)
     method Some::Class::   # Calls method «method» («Some::Class» is covered earlier)
     method $o              # Calls method «method»
     method { $o }          # Calls method «method»
    
     Base::method Class     # Calls method «Base::method» («Class» is covered earlier)
    

    no indirect当以这种方式解析代码时,您可以使用编译指示发出警告。

  10. Glob,当用作期望文件句柄的运算符的操作数时。

     open(FH, '>', $qfn) or die $!;      # Equivalent to open(*FH, ...) or ...;
     print FH "Hello, World!\n";         # Equivalent to print *FH ...;
     print main::FH "Hello, World!\n";   # Equivalent to print *main::FH ...;
    
  11. 字符串字面量,在以下情况下:

    • 当用作直接方法调用的调用者时。

        Class->method(@args)         # Uses the string «Class» as the invocant.
        Some::Class->method(@args)   # Uses the string «Some::Class» as the invocant.
      
    • 当用作一元减号的操作数时。

        -foo
        -foo::bar
      
    • 当用作具有原型的子参数的参数时*

        sub myprint(*@);
        myprint(FH, "Hello, World\n");
        myprint(main::FH, "Hello, World\n");
      
  12. 字符串字面量。这是不允许的use strict qw( subs );

希望我没有错过任何一个。

感谢@mosvy、@Grinnz 和@stevesliva!每个人都发现了一些我错过的案例。


目前缺少

  • funcnamesort funcname.

  • BEGIN和类似的。它们有时充当关键字,有时充当声明的子。

  • 导入名为 sub 的子程序print不遵循上述步骤。

    $ perl -M5.010 -e'
       use subs qw( time );
       eval { time; };
       say $@ =~ /Undefined sub/ ? "ok" : "bad";
    '
    ok
    
    $ perl -M5.010 -e'
       use subs qw( system );
       eval { system; };
       say $@ =~ /Undefined sub/ ? "ok" : "bad";
    '
    ok
    
    $ perl -M5.010 -e'
       use subs qw( print );
       eval { print; };
       say $@ =~ /Undefined sub/ ? "ok" : "bad";
    '
    bad
    

    我不知道是什么让那个特别,我不知道是否还有其他人。我猜这是因为print没有原型,但system也没有原型。


推荐阅读