解析子程序并确定perl中函数调用的参数

时间:2016-02-12 16:48:17

标签: perl parsing

我正在编写一个需要解析文件的perl脚本(或者更具体地说,是文件中的已知子),找到一个特定的函数调用,并检索该调用的所有参数。例如:

sub MySub {
    # some code here...
    # ...

    MyFunction ([q{I}, q{want}], [qw(to get)], 
        ["these", "arguments"]);

    # ...
    # more code...
}

我已经能够通过文件解析获取函数调用的相应行/行,然后我编写了自己的本地" MyFunction"这可以抓住args。然后我使用一个stringy eval来调用该函数并获取参数。例如:

sub MyFunction {
    return @_;
}

# Not actually doing this, but this is what I might get from parsing:
my $lines = 'MyFunction ({arg1 => "hashref"}, ["arg2", "arrayref"], "etc...");';

my @arguments = eval $lines;

除了我使用stringy eval这一事实外,这项工作很有效。直接从字符串中解析参数的问题是有许多不同的格式(包括多行)是可能的。所以我想有一种简单的方法可以直接从字符串中解析参数,或者在没有字符串eval的情况下调用函数吗?

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

如果你不想,你没有eval。您可以使用该名称来获取符号,然后使用它来获取代码ref。

my $func = do { 
    no strict 'refs';
    *{'main::MyFunction'}{CODE};
};

my @arguments = $func->( {arg1 => "hashref"}, ["arg2", "arrayref"], "etc..." );

答案 1 :(得分:-1)

解析Perl很难(并且只有Perl可以解析Perl的民间定理)。除了最简单的情况之外,使用您自己的手动字符串黑客解析perl可能会在灾难中结束。你真正想要的是一个可以解析Perl并为你提供参数的工具。

我们的DMS Software Reegineering Toolkit可以做到这一点。见下面的解析树, 从包含OP的MySub示例文本的文件中获取:

C:\DMS\Domains\Perl\Tools\Parser>run ..\domainparser ++AST C:\temp\test.pl

Perl~Perl5 Domain Parser Version 2.6.15 DEBUG BUILD
Copyright (C) 1996-2015 Semantic Designs, Inc; All Rights Reserved; SD Confidential
Powered by DMS (R) Software Reengineering Toolkit
Using encoding Unicode-UTF-8?ANSI +CRLF +1 /^I
432 tree nodes in tree.
(Perl@Perl~Perl5=1#5c21d20^0 Line 1 Column 1 File C:/temp/test.pl
 (statements@Perl~Perl5=10#5c21c80^1#5c21d20:1 Line 1 Column 1 File C:/temp/test.pl
  (subroutine_head@Perl~Perl5=551#5c73680^1#5c21c80:1 Line 1 Column 1 File C:/temp/test.pl
   (IDENTIFIER@Perl~Perl5=573#5c735e0^1#5c73680:1[`MySub'] Line 1 Column 5 File C:/temp/test.pl)IDENTIFIER
   (prototype@Perl~Perl5=552#5c73640^1#5c73680:2 Line 1 Column 11 File C:/temp/test.pl)prototype
   (attributes@Perl~Perl5=554#5c73660^1#5c73680:3 Line 1 Column 11 File C:/temp/test.pl)attributes
  )subroutine_head#5c73680
  (block@Perl~Perl5=4#5c21640^1#5c21c80:2 Line 1 Column 11 File C:/temp/test.pl
   precomment 3:1 `# ...'
   precomment 3:2 `# more code...'
   (statement@Perl~Perl5=21#5c7cf40^1#5c21640:1 Line 5 Column 5 File C:/temp/test.pl
   |(call_statement@Perl~Perl5=561#5c209a0^1#5c7cf40:1 Line 5 Column 5 File C:/temp/test.pl
   | (IDENTIFIER@Perl~Perl5=573#5c73920^13#5c210a0:1#5c73ec0:1#5c778c0:1#5c21080:1#5c73e00:1#5c77860:1#5c209a0:1#5c7f860:1#5c73d60:1#5c77840:1#5c7f840:1#5c73560:1#5c777e0:1[`MyFunction'] Line 5 Column 5 File C:/temp/test.pl
   |  precomment 0:1 `# some code here...'
   |  precomment 0:2 `# ...')IDENTIFIER
   | (L20@Perl~Perl5=514#5c7f240^3#5c206c0:2#5c209a0:2#5c21020:1 Line 5 Column 17 File C:/temp/test.pl
   |  (L20@Perl~Perl5=514#5c7b540^3#5c7f240:1#5c7c640:1#5c738e0:1 Line 5 Column 17 File C:/temp/test.pl
   |   (L1_term@Perl~Perl5=187#5c7a700^11#5c7abc0:1#5c7b540:1#5c7c860:1#5c7d280:1#5c7b620:1#5c7ad60:1#5c7a9a0:1#5c20840:1#5c7c1c0:1#5c7b8a0:1#5c7aaa0:1 Line 5 Column 17 File C:/temp/test.pl
   |   |(L20@Perl~Perl5=514#5c77da0^2#5c7a700:1#5c7a380:2 Line 5 Column 18 File C:/temp/test.pl
   |   | (constant@Perl~Perl5=101#5c73180^6#5c77bc0:1#5c77da0:1#5c77d60:1#5c77a00:1#5c7a420:1#5c77ae0:1 Line 5 Column 18 File C:/temp/test.pl
   |   |  (string_prefix@Perl~Perl5=120#5c731a0^1#5c73180:1 Line 5 Column 18 File C:/temp/test.pl)string_prefix
   |   |  (ORDINARY_STRING@Perl~Perl5=604#5c77400^1#5c73180:2[`I'] Line 5 Column 19 File C:/temp/test.pl)ORDINARY_STRING
   |   | )constant#5c73180
   |   | (constant@Perl~Perl5=101#5c77e00^6#5c7a6a0:2#5c7a740:2#5c7a2a0:2#5c7a160:2#5c77da0:2#5c7a140:2 Line 5 Column 24 File C:/temp/test.pl
   |   |  (string_prefix@Perl~Perl5=120#5c7a020^1#5c77e00:1 Line 5 Column 24 File C:/temp/test.pl)string_prefix
   |   |  (ORDINARY_STRING@Perl~Perl5=604#5c7a000^1#5c77e00:2[`want'] Line 5 Column 25 File C:/temp/test.pl)ORDINARY_STRING
   |   | )constant#5c77e00
   |   |)L20#5c77da0
   |   )L1_term#5c7a700
   |   (L1_term@Perl~Perl5=187#5c7b420^14#5c7b600:2#5c7b780:2#5c7b620:2#5c7c7c0:1#5c7e880:1#5c20600:1#5c7d160:1#5c7c0c0:1#5c7bf00:2#5c7bf80:2#5c20c20:1#5c7c360:1#5c7b540:2#5c7b560:2 Line 5 Column 34 File C:/temp/test.pl
   |   |(qw_constant@Perl~Perl5=113#5c7b260^1#5c7b420:1 Line 5 Column 35 File C:/temp/test.pl
   |   | (WORD_LIST_STRING_START@Perl~Perl5=630#5c7b180^1#5c7b260:1["("] Line 5 Column 37 File C:/temp/test.pl)WORD_LIST_STRING_START
   |   | (word_list@Perl~Perl5=117#5c7b240^1#5c7b260:2 Line 5 Column 38 File C:/temp/test.pl
   |   |  (word_list@Perl~Perl5=117#5c7b200^1#5c7b240:1 Line 5 Column 38 File C:/temp/test.pl
   |   |   (word_list@Perl~Perl5=116#5c7b1c0^1#5c7b200:1 Line 5 Column 38 File C:/temp/test.pl)word_list
   |   |   (WORD@Perl~Perl5=633#5c7b1a0^1#5c7b200:2[`to'] Line 5 Column 38 File C:/temp/test.pl)WORD
   |   |  )word_list#5c7b200
   |   |  (WORD@Perl~Perl5=633#5c7b1e0^1#5c7b240:2[`get'] Line 5 Column 41 File C:/temp/test.pl)WORD
   |   | )word_list#5c7b240
   |   | (STRING_END@Perl~Perl5=620#5c7b220^1#5c7b260:3[")"] Line 5 Column 44 File C:/temp/test.pl)STRING_END
   |   |)qw_constant#5c7b260
   |   )L1_term#5c7b420
   |  )L20#5c7b540
   |  (L1_term@Perl~Perl5=187#5c20260^12#5c20e80:2#5c20ea0:2#5c20f20:2#5c20f60:2#5c205c0:2#5c20600:2#5c20620:2#5c20380:2#5c7f240:2#5c7f260:2#5c7e880:2#5c7e8a0:2 Line 6 Column 9 File C:/temp/test.pl
   |   (L20@Perl~Perl5=514#5c7e7e0^1#5c20260:1 Line 6 Column 10 File C:/temp/test.pl
   |   |(constant@Perl~Perl5=103#5c7d820^5#5c7de60:1#5c7e7e0:1#5c7e140:1#5c7f940:1#5c7dd60:1 Line 6 Column 10 File C:/temp/test.pl
   |   | (INTERPOLATED_STRING_START@Perl~Perl5=621#5c7d5e0^2#5c7d840:1#5c7d820:1["""] Line 6 Column 10 File C:/temp/test.pl)INTERPOLATED_STRING_START
   |   | (interpolated_string_content@Perl~Perl5=130#5c7d800^2#5c7d840:2#5c7d820:2 Line 6 Column 11 File C:/temp/test.pl
   |   |  (interpolated_string_content@Perl~Perl5=129#5c7d7c0^1#5c7d800:1 Line 6 Column 11 File C:/temp/test.pl)interpolated_string_content
   |   |  (ORDINARY_INTERPOLATED_STRING_CONTENT@Perl~Perl5=642#5c7c6e0^1#5c7d800:2[`these'] Line 6 Column 11 File C:/temp/test.pl)ORDINARY_INTERPOLATED_STRING_CONTENT
   |   | )interpolated_string_content#5c7d800
   |   | (STRING_END@Perl~Perl5=620#5c7d7e0^2#5c7d840:3#5c7d820:3["""] Line 6 Column 16 File C:/temp/test.pl)STRING_END
   |   |)constant#5c7d820
   |   |(constant@Perl~Perl5=103#5c7dc40^3#5c7e7e0:2#5c7e840:2#5c7e8e0:2 Line 6 Column 19 File C:/temp/test.pl
   |   | (INTERPOLATED_STRING_START@Perl~Perl5=621#5c76320^4#5c7dec0:1#5c7e420:1#5c7e400:1#5c7dc40:1["""] Line 6 Column 19 File C:/temp/test.pl)INTERPOLATED_STRING_START
   |   | (interpolated_string_content@Perl~Perl5=130#5c76800^4#5c7dec0:2#5c7e420:2#5c7e400:2#5c7dc40:2 Line 6 Column 20 File C:/temp/test.pl
   |   |  (interpolated_string_content@Perl~Perl5=129#5c76140^1#5c76800:1 Line 6 Column 20 File C:/temp/test.pl)interpolated_string_content
   |   |  (ORDINARY_INTERPOLATED_STRING_CONTENT@Perl~Perl5=642#5c76120^1#5c76800:2[`arguments'] Line 6 Column 20 File C:/temp/test.pl)ORDINARY_INTERPOLATED_STRING_CONTENT
   |   | )interpolated_string_content#5c76800
   |   | (STRING_END@Perl~Perl5=620#5c76180^4#5c7dec0:3#5c7e420:3#5c7e400:3#5c7dc40:3["""] Line 6 Column 29 File C:/temp/test.pl)STRING_END
   |   |)constant#5c7dc40
   |   )L20#5c7e7e0
   |  )L1_term#5c20260
   | )L20#5c7f240
   |)call_statement#5c209a0
   )statement#5c7cf40
  )block#5c21640
 )statements#5c21c80
)Perl#5c21d20

你仍然需要遍历解析树并挑选出参数。如果你确实选择了子树,可以使用它们来生成表面语法字符串。