【问题标题】:Parsing Perl 5 and examining the syntax tree解析 Perl 5 并检查语法树
【发布时间】:2018-08-22 01:05:04
【问题描述】:

我已经阅读并理解,由于 BEGIN 块,没有 Perl 解释器就无法解析 Perl 5 代码。

我知道有独立的解析器,比如 PPI (被Perl::Critic使用) 大致解析初始文档。

但我找不到任何关于输出某种程序的参考 抽象语法树,或任何类似于 Perl 用于执行阶段的树的内部结构。

比较解析和执行阶段的内部表示以查看代码扩展和更改会很有趣。

【问题讨论】:

  • 以 B::Concise 模块为例。
  • 除了B/O核心模块,还有MAD(未维护,同时被移除)。大多数解析 Perl 的软件要么是源过滤器(很容易破坏),要么是基于 PL_keyword_plugin 构建的(强大但有限)。见examples
  • @daxim, PL_keyword_plugin 实际上是有问题的,已经被Devel::CallParser取代了。
  • @mob,它不需要 Perl 来解析原型,并且use 语句也是BEGIN 块,因此该链接不会添加任何新内容。 /// 也就是说,当然也可以在运行时修改操作码。但是有人这样做吗?

标签: perl parsing abstract-syntax-tree


【解决方案1】:

所以基本上有几个选择:

  1. 对于静态分析,使用PPI,它的缺点是不处理BEGIN 块处的Perl 代码。这类似于“解析”。

  2. 对于动态分析,使用 B::Concise 获取用于执行的内部操作码。这类似于“编译”(对 Perl VM)。

  3. 两者的结合是使用B::Deparse 获取内部表示的Perl 代码(而不是VM 操作码),然后将其发送到PPI 以构建树。

    李>

编辑:根据评论澄清第 3 点。仍然不知道可以扩展导入并输出单个大文件的命令(以便解析语法扩展)。

【讨论】:

  • B::Deparse 确实评估 BEGIN - 它只是在解析后获取操作码并将它们呈现为 Perl 源代码,而 B::Concise 以更直接的符号呈现它们。请注意,这两个模块都是纯 Perl,因此您可以查看它们如何遍历操作码结构。 Perl 操作码既是 AST 指令又是 VM 指令。
  • 我认为它没有,因为即使在第 7 级,use 语句仍然扩展到提到的块。也许我期待一个大文件,一切都解决了(比如扩展 #include 的 C 预处理器的输出)。
  • Perl 的多阶段编译模型与 C 的基于文本的预处理器非常不同。看来您的实际问题(“如何将所有使用过的 Perl 模块打包到一个脚本中?”或“为什么 B::Deparse 像这样扩展 use 语句?”)与您的问题中的问题非常不同:“如何我检查 Perl 的语法树”。您能否提出一个更清楚地解释您的实际问题的新问题?
  • 这是一个类比,我知道它更类似于语法宏 (LISP) 而不是文本替换。但想法是:如果 Deparse 仍然输出这些块,那么其余的代码语法可以通过导入的模块进行更改。显然,在具有自省功能的动态语言中,这是没有止境的,因为程序可以在执行期间评估任何生成的字符串。但我想知道是否有可能在 BEGIN 处理阶段之后以 Perl 形式获取语法树的代码。有意义吗?
猜你喜欢
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多