【问题标题】:How do C/C++ parsers work?C/C++ 解析器如何工作?
【发布时间】:2011-06-12 21:37:23
【问题描述】:

我花了很多时间研究 PHP 的解析器是如何工作的:

它将 PHP 代码最终转换为 c 代码。

但是 c 代码是如何翻译成可执行文件的呢?

顺便说一句,如何从数学角度判断A语言是否可以转换为B语言?

【问题讨论】:

  • c/c++ 不使用解析器,它们被称为编译器。有一个很大的不同。 PHP 代码不会被翻译成 c 代码。可能用 C 编写的程序解释 PHP 代码并产生输出。
  • PHP 解析器将 PHP 代码转换为 C 代码?什么?!
  • @squillman:C 编译器最明确地使用解析器。 GNU Bison 是解析器生成器的常见选择,它读取语言规范并输出解析器。
  • @squilman- 解析是编译中的一个步骤。你的说法绝对是不正确的。

标签: c parsing compiler-construction cross-compiling


【解决方案1】:

这是一个非常棒且非常深刻的问题,它涉及到计算机科学的许多部分。

最终,计算机上的所有程序都通过以机器代码向处理器发出指令来执行。没有一个“机器代码”,每个处理器都有自己的一组可以执行的指令。这些通常是低级操作,例如“将值加载到内存中”或“将两个值相加”。理论上,每个程序都可以用机器代码编写,但这种情况很少见。机器码本质上是由处理器以特定方式解码的一系列零和一,几乎不可能直接以这种方式构建任何复杂系统。

机器码之上的一个步骤是汇编语言,这是一种非常低级的宏式语言,通常与机器码具有一对一的映射关系。例如,你可能有像“add”这样的命令来做加法,“sub”来做减法,或者“call”来做函数调用。最终,使用汇编器将代码转换为机器代码,这是一个将汇编转换为机器代码的程序。可以在汇编中构建大型复杂系统,但非常困难。

C 和 C++ 等许多编程语言都经过编译,这意味着一个称为编译器 的特殊程序将源代码翻译成汇编语言,然后可以将其转换直接转机器码。通过这种方式,您可以编写在高层次上工作的代码——它可以有变量、函数、对象、模板、异常等——但可以直接在机器硬件上运行。其他编程语言是interpreted,这意味着一个称为interpreter的特殊程序解析源代码,构建它的一些内存表示,然后将其转换为汇编间接(通过使用程序控制要执行的指令)或直接(通过根据需要生成程序集)。

如何从一种语言转换为另一种语言的理论已被广泛研究。有很多挑战,从“你怎么看程序的源代码并理解你在看什么?”到“将此程序转换为其他语言的最有效方法是什么?”前者涉及词法分析解析语义分析;后者涉及优化代码生成

通常情况下,任何语言的程序都可以转换为另一种语言的等效程序,尽管效率可能会显着下降。一些编程语言具有访问底层硬件的特殊功能,因此不能用无法访问该硬件的语言编写,但这种情况很少见。一个程序是否可以用另一种语言重写的一个典型衡量标准是询问这两种语言是否 图灵完备,这是一个数学术语,表示编程语言是否具有足够的表达能力来编码特定类别的函数。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    PHP 并没有真正“翻译”成 C 代码; PHP 解释器在运行可执行代码时解释 PHP,而 PHP 解释器是一个状态机,它知道如何执行进程中的所有 PHP。不需要或不需要中间体 C。因为是解释的,所以每次 PHP 可执行文件解释 PHP 程序时,都会重新计算。

    PHP 解释器是用 C 语言编写的,但它也可以用 C++ 或 Assembly 或 Pascal 或 Erlang 或 bash 或 Java 或其他任何你可能想要的语言编写。 (我认为它是从 Perl 开始的,但我的记忆越来越模糊了。)

    C 是用 compiler 编译的,在程序可能运行数千次之前运行一次。大多数 C 编译器会进行多次“通过”:lexing 输入到 tokensparsing 将令牌输入到 tree,然后修改 Abstract Syntax Tree 以生成 symbol tables对于每个scopes 的执行。在抽象语法树经过各种优化(例如dead code removalstatic single assignment)之后,该树被传递给code generator,这将为可以在目标architecture 上运行的输入生成所需的object file有问题。对象文件通过linker 链接到未在该特定translation unit 中定义的对象(C 中的函数和变量),以便程序可以在运行时由linker/loader 加载。

    dragon book 是学习编译器的最佳资源,但我推荐 Pragprog 的 Language Implementation Patterns

    【讨论】:

    • +1 为龙书,正要提到这一点。我强烈推荐它。
    • 您能否详细说明代码生成器是如何完成的,IMO,解析器/代码生成器之间最显着的区别在于:代码生成器将语言 A 映射到语言 B,而解析器在相同的语言语法中工作。
    • @yoyo:不。如果您有一个将语言 A 翻译成语言 A 的“编译器”,那么解析器和代码生成器将执行完全相反的任务。解析器将语言 A 中的文本转换为一组数据结构(内部表示,IR)。代码生成器采用这样一组数据结构并将其转换为语言 B 中的“文本”。(引号中的文本,因为语言 B 可以使用二进制表示,例如机器代码)
    【解决方案3】:

    据我了解,您的主要问题似乎与编译过程有关。正如您在 cmets 中提到的,您对解析器和编译器感到困惑。让我帮你一点:

    解析只是编译过程中的步骤之一。为了更好地理解您的问题,您必须首先了解编译器的工作原理。通常,编译器通常会采用上述几个步骤。要理解上述内容需要一些工作。如果您想进一步深入研究,请阅读this link 的讲座。源代码和目标代码取决于上下文。通常源代码是高级语言,目标代码是机器码。

    【讨论】:

      【解决方案4】:

      如何判断语言A是否可以 以某种方式转换为语言 B 数学方面?

      如果两种语言都是Turing complete,那么可以将一种语言翻译成另一种语言。

      至于您的 PHP 到 C 假设,有像 HipHop 这样的“源到源”编译器,但这不是常见的情况。大多数动态类型语言都编译为字节码并在虚拟机上运行。

      对于 C,编译器基本上将其翻译成目标处理器的汇编语言。

      如果您想了解更多信息,可以阅读有关编译器设计、抽象语法树和语言语义的信息。不过,如果您是新手的话,需要同时学习很多内容,所以 Stack Overflow 确实不是开始处理这么大的主题的最佳场所。

      【讨论】:

      • 不正确。在虚拟机上运行的唯一语言是 JVM 或 CLR 上的语言。事实上,大多数语言都是经过解释的。
      • @Billy Whaaa???这对这些人来说是个新闻:Parrot VM (Perl 6)、YARV (Ruby)、Python VM。现在 shell 语言肯定是被解释的,但 JVM 和 CLR 并不是唯一的虚拟机。
      • @Billy ONeal、Erlang、Dalvik、LLVM、Lua、Forth、Flash、Smalltalk、SQLite、Squeek、Valgrind、Zend。大多数计算机科学专业的学生都写过语言解释器和虚拟机,但是对于玩具语言,他们的教授设计的目的是让这项任务变得平易近人。 :)
      • @Billy,补充 crisaycock 的回答,LLVM 也是一个虚拟机,尽管它通常用于提前编译 C/C++ 代码。
      • Smalltalk、Lua、Zend 和 SQLite 不是 VM。 Smalltalk 可以在虚拟机之类的东西上运行,但这从语言本身来看并不明显(在 Smalltalk-80 的全盛时期,它当然没有使用虚拟机之类的东西)。 Lua 被解释。 Zend 是一个操作码缓存——它只是缓存一些 PHP 的解析;它不是虚拟机。 SQLite 被完全解释。不确定其他人。我的观点并不是特别针对虚拟机,更多的是不合格的“大多数……语言”是垃圾。
      猜你喜欢
      • 2011-08-14
      • 2016-12-28
      • 2023-03-23
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      相关资源
      最近更新 更多