编译原理--第一篇

编译原理---第一篇:

  1.  

1.1编译器的结构分为两个部分:分析部分和综合部分.

分析部分:把源程序分解成为多个组成要素,并在这些要素智商加上语法结构。然后,他使用这个结构来创建该源程序中的一个中间表示。如果分析部分检查出源程序没有按照正确的语法构成,或者语义上不一致,并把信息存放在一个称为符号表的数据结构中,符号表将和中间表示形式一起传送给综合部分。

综合部分根据中间表示和符号表中的信息来构造用户期待的目标程序。

    1. 词法分析:

词法分析器读入组成源程序的字符流,并且将他们组成有意义的词素的序列。对于每个词素,词法分析器产生如下形式的词法单元(token)作为输出。

(token-name,attribute-value)  这个词法单元被传送给下一个步骤,即语法分析,在这个词法单元中,第一个分量token-name是一个由语法分析步骤使用的抽象符号,第二个分量attribute-value指向符号表中关于这个词法单元的条目。

符号条目表的信息会被语义分析和代码生成步骤使用。

例子: position =initial+rate*60

这个赋值语句可以组合成如下词素,并映射成如下词法单元,这些词法单元将被传递给语法分析阶段。

  1. position 是一个词素: 被映射成词法单元(id,1) ,其中id是表示标识符(indentifier)的抽象符号,而1指向符号表中position对应的条目,一个标识符对应的符号表条目存放该标识符有关的信息,比如他的名字类型。
  2. 赋值符号 =  是一个词素,被映射成词法单元<= >.因为这个词法单元不需要属性值,所以我们省略了第二个分量。也可以使用assign这样的抽象符号作为词法单元的名字,但是为了标记上的方便,我们选择使用词素本身作为抽象符号的名字。
  3. Initial是一个词素,被映射成词法单元<id,2>,其中2指向initial对应的符号表条目
  4. +是一个词素,被映射成词法单元+
  5. Rate是一个词素,被映射成词法单元<id,3>,其中3指向rate对应的符号表条目
  6. *是一个词素,被映射出词法单元<*>
  7. 60是一个词素,被映射成词法单元<60>
  8. 分隔词素的空格会被一次发分析器忽略掉。

             输出词法单元序列:<id,1><=><id,2><+><id,3><*><60>

 

 

 

 

1.2语法分析

 

语法分析使用由词法分析器生成的各个词法单元的第一个分量来创建树形的中间表示。该中间表示给出了词法分析产生的词法单元流的语法结构-----语法树。树中的每个内部节点表示一个运算,而该节点的子节点表示该运算的分量。

    1. 语义分析

使用语法树和符号表中的信息来检查源程序是否和语法定义的语义一直,他同时手机类型信息,并把这个信息存放在语法树或者符号表中。以便在随后的中间代码生成过程中使用。语义分析的一个重要组成部分是类型检查,编译器检查每个运算符是否具有匹配的运算分量。1.类型是否匹配 --数组下标是否是整数2.自动类型转换 int --double

 

 

1.4中间代码生成。

    在把一个源程序翻译成目标代码的过程中,一个编译器可能构造出一个或多个中间表示,这些中间表示可以有多种形式,语法树是一种中间表示形式,他们通常在语法分析和语义分析中使用。

在源程序的语法分析和语义分析完成之后,很多编译器生成一个明确的低级的活类机器余元的中间表示,我们可以把这个表示看做是某个抽象机器的程序,该中间表示应该具有两个重要的性质,他应该易于生成,且能够被轻松的翻译为目标机器上的语言。三地址代码的中间表现形式:

      T1=inttofloat(60);

      T2=id3*t1

      T3=id2+t2

      Id1=t3

1.5代码优化  机器无关的代码优化步骤试图改进中间代码。以便生成更好的目标代码。“更好通产意味着更快,但是也可能会有其他目标,如更短或者能耗更低的目标代码。”

1.6 代码生成 。代码生成器以源程序的中间表示形式作为输入,并把它映射到目标语言,如果目标语言是机器代码。那么久必须为程序使用的每个变脸阿甘选择寄存器或者内存位置。然后中间指令被翻译成为能够完成相同任务的机器指令序列。代码生成的一个至关重要的方面是合理分配寄存器以存放变量的值。

比如使用寄存器R1和R2,(1,4)中的中间代码可以被翻译成为如下的机器代码

LDF R2,Id3

MULF R2 ,R2,#60.0

LDF R1,id2

ADDF R1,R1,R2

STF  id1,R1

 

符号表管理: 编译器的重要功能之一是记录源程序中使用的变量的名字,并收集和每个名字各种属性有关的信息, 这些属性可以提供一个名字的存储分配,他的类型,作用域等信息,对于过程名字。这些信息还包括,他的参数数量和类型,每个参数的传递方法以及返回类型

符号表结构为每个变量名字创建了一个记录条目,记录的字段就是名字的各个属性,这个数据结构应该允许编译器迅速查找到每个名字的记录,并想记录中快速存放和获取记录中的数据。

 

3.编译技术的应用

高级程序设计语言的实现:

程序语言设计基础:

  1. 静态和动态的区别: 如果一个语言使用的策略支持编译器静态决定的某个问题,那么我们说这语言使用了静态策略,或者说这个问题可以编译时刻决定 ,另一方面,一个只允许在运行程序需的时候做出额决定的策略被称为动态策略,或者被认为需要在运行时刻做出决定。
  2. Public private protected 是用于声明作用域

 

声明作用域:如果仅仅通过阅读程序就可以确认一个声明的作用域,那么整个语言使用的是静态作用域,或者说词法作用域,否则就是动态作用域。

Java的static指的不是变量的作用域,而是编译器确定用于存放被声明变量的内存位置的能力。

Public static int x  x是一个类变量5,也就是说不管创建了多少这个类的对象,只存在一个x的copy。此外,编译器可以确定内存中的被用于存放整数x的位置,编译器没有办法在运行程序之前预先确定所有这些位置。

  1. 环境与状态

程序在运行时发生的改变是否会影响数据元素的值,还是影响了对那个数据的名字的解释。

X=y+1这样的赋值语句会改变名字x所指的值。更加明确的说,这个赋值改变了

X所指向的内存位置上的值。

名字和内存位置的关联,及之后和值的关联可以用两个映射来描述。这两个映射随着程序的运行而改变。

  1. 环境: 是一个从名字到存储位置的映射。因为变量就是指内存位置。(c语言的术语-左值)
  2. 状态:是一个从内存位置到他们的值的映射。右值

 

猜你喜欢

转载自blog.csdn.net/Jbinbin/article/details/83991444