zoukankan      html  css  js  c++  java
  • 编译器构造

    http://www.cnblogs.com/fanzhidongyzby/archive/2012/07/03/2574429.html

    一、             编译器简介

    前面谈到静态链接器构造的基本流程,最后提到所构造的链接器若要能正常工作的前提是需要构造一个能生成符合链接器输入文件格式的编译器,本文构造一个符合这种具体格式要求编译器。但是编译器的直接编译的结果一般是汇编语言文件,这种文件是不能满足上述静态链接器的需求的,因此在它们之间还需要一个汇编语言程序将汇编语言转换为二进制文件作为链接器的输入。恰如图1-1所示,

     1-1  静态编译步骤

    上次引用这张图是为了说明静态编译器的整体结构,而这次我们侧重于编译程序的构造的流程,在具体展开编译器构造的讨论之前,我们先简单介绍一下编译器的基本知识。

    编译从本质上讲就是语言翻译程序,它是把一种语言(称作源语言)书写的程序翻译为另一种语言(称作目标语言)的等价程序。源语言作为编译器的输入,必须让编译器“知道”自己的语法结构——文法,这样编译器才能正确处理语言的结构。所以编译器设计的第一步应该是源语言文法定义。

    编译器要处理源语言文件(源文件),必须扫描文件内容,提取出文件内的语法基本单元,比如标识符,关键字,界符等,这一步在编译中称为词法分析,通过这一步,编译器能获得源文件表达的所有语言单位。

    接下来,编译器需要分析这些语言单位的组合的合法性以及整体结构,这里编译原理提供了很多成熟的分析算法,这步成为语法分析,语法分析将合法的程序转换为一个逻辑上的语法树形式,方便后边的处理。

    另外,由于程序设计语言虽然是结构上是上下文无关的文法,但是实际应用中程序中每个语句并不是独立的,那么如何反应这种联系的存在,语义处理的工作就显得非常必要,它验证了语法模块之间的关联的合法性。

    通过以上的步骤,编译器就能判断源程序的合法性,如果是合法程序,编译器就会进行最后一步关键的工作——代码生成,这一步在现代编译器中实现方式多样,例如gcc会先生成中间代码,经过优化后再生成汇编语言,但是本文为了简化编译的流程,直接从语法树过渡到代码生成,按照语法树结构产生源文件对应的汇编代码。

    贯穿整个编译流程中,符号表具有很重要的作用,它记录编译过程中许多关键的数据结构,方便编译器存取符号相关信息。最后,错误处理模块会在合适的地方报告编译的错误信息。

     1-2  直接编译步骤

    为了和前述的静态链接器结构保持兼容,这里编译器的设计结构需要作特殊说明。链接器需要多个目标文件作为输入,因此,编译器生成的汇编文件就应该是多个,每个汇编文件会映射为一个目标文件。这样,编译器就不能采用前边所述的直接编译生成一个孤立文件的方式,图1-2,而是采用多文件分别处理的方式进行。由于之前实现了一个直接编译方式的编译器,所以必须对编译器结构进行修改以满足链接器的需要。

    既然是对单个的源文件进行编译,就必须要求编译器能处理引用的外部变量和函数,这里主要集中在extern变量和函数声明的语法结构上。为了清晰的阐述编译器的设计过程,下边就按照上述编译器设计的基本步骤阐述每个具体细节,图1-3展示了编译器的设计结构。

    图 1-3 编译器结构设计

    二、             文法定义

    一个程序设计语言是一个记号系统,它的完整定义包含语法和语义两个方面。语法规定了语言的书写规则,而语义定义了语言上下文之间的联系。因此,语言的形式化定义必须通过语法规则来表达,而语法规则就是所谓的文法。

    Chomsky于1956年建立了形式语言的描述,他把文法分为四种类型,即0型、1型、2型、3型。这四种文法的类型的范围是依次缩减的,其中2型文法(亦称为上下文无关文法)能很好的表达现代程序设计语言的结构,所以,一般程序设计语言都满足2型文法的规则。

    作为编译器处理的核心对象,高级语言的结构直接关系着编译系统的结构。本系统处理的高级语言主体是C语言的子集 ,另外对标准C语言的语法进行了适当的删减和扩充。

    自定义高级语言基本特性:

    1)类型:支持int、char、void基本类型和复杂的string类型。

    2)表达式:支持四则运算,简单关系运算和字符串连接运算。

    3)语句:赋值、while循环、if-else条件分支、函数调用、return、break、continue、输入in>>、输出out<<语句。

    4)声明和定义:变量、函数声明定义,外部变量声明extern。

    5)其它:支持多文件、默认类型转换、单行/多行注释等。

    自定义语言尽可能接近C语言的格式,以使得编译器的重点放在处理高级语言的过程上,而不过多关心复杂的语言细节,下边给出了自定义的语言的文法定义,见表2-1。

     2-1  文法规则

    文法定义中^表示空符,<>内表示非终结符,其他为终结符,稍后在词法分析中针对此具体说明。

    三、             词法分析

    词法分析是编译的第一个阶段,它的任务是从左向右逐个字符地对源程序进行扫描,产生一个个单词序列,用于语法分析。执行词法分析的程序称为词法分析程序或者扫描程序。

    在词法分析过程中,最关键的是对词法记号的描述。一般情况下,编译系统使用正则文法来描述词法的规则,而对正则文法识别的工具就是有限自动机。解析正则文法的有限自动机有时候可能不够简洁,这样就需要把不确定的有限自动机(NFA)转化为确定的有限自动机(DFA)。通过有限自动机把词法记号识别出来,就完成了词法分析的工作。

    词法分析的主要目的就是从源文件中获取合法的词法记号,主要功能如下:

    1)扫描输入文件,消除注释、无效空格、TAB、回车符。

    2)识别标识符、关键字、常量、界符等,产生词法记号。

    3)识别词法错误(记号过长、意外字符等)。

  • 相关阅读:
    java 堆、栈、方法区/ 类变量、成员变量、局部变量
    native的详细用法
    《Java项目中classpath路径详解》
    事务四大特征:原子性,一致性,隔离性和持久性(ACID)
    Tomcat 配置文件server.xml详解
    linux下vim常用命令 (更新中...)
    #1572 小Hi与花盆
    leetcode 120. Triangle
    leetcode 174. Dungeon Game
    leetcode 368. Largest Divisible Subset
  • 原文地址:https://www.cnblogs.com/feng9exe/p/6434890.html
Copyright © 2011-2022 走看看