当前位置:首页 » 编程软件 » 编译原理名字的性质的说明方式

编译原理名字的性质的说明方式

发布时间: 2024-11-03 02:58:58

编译原理笔记9:语法分析树、语法树、二义性的消除

语法分析树和语法树不是一种东西 。习惯上,我们把前者叫做“具体语法树”,其能够体现推导的过程;后者叫做“抽象语法树”,其不体现过程,只关心最后的结果。

语法分析树是语言推导过程的图形化表示方法。这种表示方法反映了语言的实质以及语言的推导过程。

定义:对于 CFG G 的句型,分析树被定义为具有下述性质的一棵树:

推导,有最左推导和最右推导,这两种推导方式在推导过程中的分析树可能不同,但因最终得到的句子是相同的,所以最终的分析树是一样的。

分析树能反映句型的推导过程,也能反映句型的结构。然而实际上,我们往往不关心推导的过程,而只关心推导的结果。因此,我们要对 分析树 进行改造,得到 语法树 。语法树中全是终结符,没有非终结符。而且语法树中没有括号

定义:

说白了,语法树这玩意,就一句话: 叶子全是操作数,内部全是操作符 ,树里没有非终结符也不能有括号。

语法树要表达的东西,是操作符(运算)作用于操作数(运算对象)

举俩例子吧:

【例】: -(id+id) 的语法树:

【例】:-id+id 的语法树:

显然,我们从上面这两个语法树中,直接就能观察出来它们的运算顺序。

【例】:句型 if C then s1 else s2

二义性问题:一个句子可能对应多于一棵语法树。

【例】: 设文法 G: E → E+E | E*E | (E) | -E | id

则,句子 id+id*id、id+id+id 可能的分析树有:

在该例中,虽然 id+id+id 的 “+” 的结合性无论左右都不会影响结果。但万一,万一“+”的含义变成了“减法”,那么左结合和右结合就会引起很大的问题了。

我们在这里讲的“二义性”的“义”并非语义——我们现在在学习的内容是“语法分析器”,尚未到需要研究语言背后含义的阶段。

我们现在讲的“二义性”指的是一个句子对应多种分析树。

二义性的体现,是文法对同一句子有不止一棵分析树。这种问题由【句子产生过程中的某些推导有多于一种选择】引起。悬空 else 问题就可以很好地体现这种【超过一种选择】带来的二义性问题,示例如下。

看下面这么个例子。。

(其实,我感觉这个其实比较像是“说话大喘气”带来的理解歧义问题。。。)上面的产生式中并没体现出来该咋算分一块,所以两种完全不同的句子结构都是合法的。

二义性问题是有救的,大概有以下这三种办法:

这些办法的核心,其实都是将优先级和结合性说明白。

核心:把优先级和结合性说明白

既然要说明白,那就不能让一个非终结符可以直接在当次推导中能推出会带来优先级和结合性歧义的东西。(对分析树的一个内部节点,不会有出现在其下面的分支是相同的非终结符的情况。如果有得选,那就有得歧义了。没得选才能确定地一路走到黑)

改写为非二义文法的二义文法大概有下面这几个特点:

改写的关键步骤:

【例】改写下面的二义文法为非二义文法。图右侧是要达成的优先级和结合性

改写的核心其实就两句话:

所以能够得到非终结符与运算的对应关系(因为不同的运算有不同的优先级,我们想要引入多个优先级就要引入多个新的非终结符。这样每个非终结符就可以负责一个优先级的运算符号,也就是说新的非终结符是与运算有关系的了。因此这里搞出来了“对应关系”四个字)如下:

优先级由低到高分别是 +、 、-,而距离开始符号越近,优先级越低。因此在这里的排序也可以+ -顺序。每个符号对应一层的非终结符。根据所需要的结合性,则可确定是左递归还是右递归,以确定新的产生式长什么样子

【例】:规定优先级和结合性,写出改写的非二义文法

我们已经掌握了一种叫做【改写】的工具,能让我们消除二义性。接下来我们就要用这个工具来尝试搞搞悬空 else 问题!

悬空 else 问题出现的原因是 then 数量多于 else,让 else 有多个可以结合的 then。在二义文法中,由于选哪两个 then、else 配对都可以,故会引起出现二义的情况。在这里,我们规定 else 右结合,即与左边最靠近的 then 结合。

为改写此文法,可以将 S 分为完全匹配(MS)和不完全匹配(UMS)两类。在 MS 中体现 then、else 个数相等即匹配且右结合;在UMS 中 then、else 不匹配,体现 else 右结合。

【例】:用改写后的文法写一个条件语句

经过检查,无法再根据文法写出其他分析树,故已经消除了二义性

虽然二义文法会导致二义性,但是其并非一无是处。其有两个显着的优点:

在 Yacc 中,我们可以直接指定优先级、结合性而无需自己重写文法。

left 表示左结合,right 表示右结合。越往下的算符优先级越高。

嗯就这么简单。。。

我们其实可以把语言本身定义成没有优先级和结合性的。。然后所有的优先、结合都交由括号进行控制,哪个先算就加括号。把一个过程的结束用明确的标志标记出来。

比如在 Ada 中:

在 Pascal 中,给表达式加括号:

② 编译原理为什么存在递归文法

编译原理中存在递归文法是因为编程语言的语法和结构往往具有递归性质。递归文法是一种用来描述编程语言语法的形式化表示方法,其中规则可以包含对同一语法结构的递归引用。这种递归性质反映了编程语言中常见的嵌套和递归结构。
以下是一些原因,说明为什么编译原理中存在递归文法:
1. 语法结构的嵌套:编程语言中的语法结构通常可以嵌套在其他语法结构中,例如,一个函数可以包含其他函数,一个条件语句可以包含另一个条件语句,等等。递归文法可以很自然地表示这种嵌套结构。
2. 语法的可扩展性:编程语言通常需要具有可扩展性,允许程序员定义新的语法结构或数据类型。递归文法可以轻松地扩展以包括新的语法规则。
3. 函数调用和表达式求值:编程语言中的函数调用和表达式求值通常是递归的过程。递归文法可以用于清晰地描述这些递归计算过程。
4. 简洁性和可读性:递归文法可以帮助编译器设计者更简洁地表示语言的语法,这有助于提高编译器的可读性和维护性。
5. 符合语言设计的自然表示:递归文法使得语法规则的表示更符合编程语言设计的自然结构,因为它们允许对语法结构进行递归定义,而不需要多次重复相似的规则。
虽然递归文法在编译原理中非常有用,但它们也需要谨慎使用,以避免无限递归或歧义性。编译器设计者需要确保递归文法能够被正确解析和处理,通常需要使用递归下降解析器或其他技术来处理递归文法。

java中什么是堆和栈,如何应用,最好举个例子,并详细地说明一下,谢谢了

简单的说:
Java把内存划分成两种:一种是栈内存,一种是堆内存。

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。

在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

具体的说:
栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。

比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。

String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一次生成一个。
因此用第一种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

java中内存分配策略及堆和栈的比较
2.1 内存分配策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.

2.2 堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:
从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:
在编程中,例如C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.
堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中,要求创建一个对象时,只需用 new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点(晕~).

2.3 JVM中的堆和栈
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译原理中的活动纪录的概念是差不多的.
从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。

④ 编译程序有编译和翻译两种方式分别对其说明并比较 急 在线等

编译程序 编译程序
compiler
把用高级程序设计语言书写的源程序,翻译成等价的计算机汇编语言或机器语言的目标程序的翻译程序。编译程序属于采用生成性实现途径实现的翻译程序。它以高级程序设计语言书写的源程序作为输入,而以汇编语言或机器语言表示的目标程序作为输出。编译出的目标程序通常还要经历运行阶段,以便在运行程序的支持下运行,加工初始数据,算出所需的计算结果。编译程序的实现算法较为复杂。这是因为它所翻译的语句与目标语言的指令不是一一对应关系,而是一多对应关系;同时也因为它要处理递归调用、动态存储分配、多种数据类型,以及语句间的紧密依赖关系。但是,由于高级程序设计语言书写的程序具有易读、易移植和表达能力强等特点,编译程序广泛地用于翻译规模较大、复杂性较高、且需要高效运行的高级语言书写的源程序。
功能 编译程序的基本功能是把源程序翻译成目标程序。但是,作为一个具有实际应用价值的编译系统,除了基本功能之外,还应具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人-机联系等重要功能。①语法检查:检查源程序是否合乎语法。如果不符合语法,编译程序要指出语法错误的部位、性质和有关信息。编译程序应使用户一次上机,能够尽可能多地查出错误。②调试措施:检查源程序是否合乎设计者的意图。为此,要求编译程序在编译出的目标程序中安置一些输出指令,以便在目标程序运行时能输出程序动态执行情况的信息,如变量值的更改、程序执行时所经历的线路等。这些信息有助于用户核实和验证源程序是否表达了算法要求。③修改手段:为用户提供简便的修改源程序的手段。编译程序通常要提供批量修改手段(用于修改数量较大或临时不易修改的错误)和现场修改手段(用于运行时修改数量较少、临时易改的错误)。④覆盖处理:主要是为处理程序长、数据量大的大型问题程序而设置的。基本思想是让一些程序段和数据公用某些存储区,其中只存放当前要用的程序或数据;其余暂时不用的程序和数据,先存放在磁盘等辅助存储器中,待需要时动态地调入。⑤目标程序优化:提高目标程序的质量,即占用的存储空间少,程序的运行时间短。依据优化目标的不同,编译程序可选择实现表达式优化、循环优化或程序全局优化。目标程序优化有的在源程序级上进行,有的在目标程序级上进行。⑥不同语言合用:其功能有助于用户利用多种程序设计语言编写应用程序或套用已有的不同语言书写的程序模块。最为常见的是高级语言和汇编语言的合用。这不但可以弥补高级语言难于表达某些非数值加工操作或直接控制、访问外围设备和硬件寄存器之不足,而且还有利于用汇编语言编写核心部分程序,以提高运行效率。⑦人-机联系:确定编译程序实现方案时达到精心设计的功能。目的是便于用户在编译和运行阶段及时了解内部工作情况,有效地监督、控制系统的运行。
早期编译程序的实现方案,是把上述各项功能完全收纳在编译程序之中。然而,习惯做法是在操作系统的支持下,配置调试程序、编辑程序和连接装配程序,用以协助实现程序的调试、修改、覆盖处理,以及不同语言合用功能。但在设计编译程序时,仍须精心考虑如何与这些子系统衔接等问题。
工作过程 编译程序必须分析源程序,然后综合成目标程序。首先,检查源程序的正确性,并把它分解成若干基本成分;其次,再根据这些基本成分建立相应等价的目标程序部分。为了完成这些工作,编译程序要在分析阶段建立一些表格,改造源程序为中间语言形式,以便在分析和综合时易于引用和加工(图1)。
数据结构 分析和综合时所用的主要数据结构,包括符号表、常数表和中间语言程序。符号表由源程序中所用的标识符连同它们的属性组成,其中属性包括种类(如变量、数组、结构、函数、过程等)、类型(如整型、实型、字符串、复型、标号等),以及目标程序所需的其他信息。常数表由源程序中用的常数组成,其中包括常数的机内表示,以及分配给它们的目标程序地址。中间语言程序是将源程序翻译为目标程序前引入的一种中间形式的程序,其表示形式的选择取决于编译程序以后如何使用和加工它。常用的中间语言形式有波兰表示、三元组、四元组以及间接三元组等。
分析部分 源程序的分析是经过词法分析、语法分析和语义分析三个步骤实现的。词法分析由词法分析程序(又称为扫描程序)完成,其任务是识别单词(即标识符、常数、保留字,以及各种运算符、标点符号等)、造符号表和常数表,以及将源程序换码为编译程序易于分析和加工的内部形式。语法分析程序是编译程序的核心部分,其主要任务是根据语言的语法规则,检查源程序是否合乎语法。如不合乎语法,则输出语法出错信息;如合乎语法,则分解源程序的语法结构,构造中间语言形式的内部程序。语法分析的目的是掌握单词是怎样组成语句的,以及语句又是如何组成程序的。语义分析程序是进一步检查合法程序结构的语义正确性,其目的是保证标识符和常数的正确使用,把必要的信息收集和保存到符号表或中间语言程序中,并进行相应的语义处理。
综合部分 综合阶段必须根据符号表和中间语言程序产生出目标程序,其主要工作包括代码优化、存储分配和代码生成。代码优化是通过重排和改变程序中的某些操作,以产生更加有效的目标程序。存储分配的任务是为程序和数据分配运行时的存储单元。代码生成的主要任务是产生与中间语言程序符等价的目标程序,顺序加工中间语言程序,并利用符号表和常数表中的信息生成一系列的汇编语言或机器语言指令。
结构 编译过程分为分析和综合两个部分,并进一步划分为词法分析、语法分析、 语义分析、 代码优化、存储分配和代码生成等六个相继的逻辑步骤。这六个步骤只表示编译程序各部分之间的逻辑联系,而不是时间关系。编译过程既可以按照这六个逻辑步骤顺序地执行,也可以按照平行互锁方式去执行。在确定编译程序的具体结构时,常常分若干遍实现。对于源程序或中间语言程序,从头到尾扫视一次并实现所规定的工作称作一遍。每一遍可以完成一个或相连几个逻辑步骤的工作。例如,可以把词法分析作为第一遍;语法分析和语义分析作为第二遍;代码优化和存储分配作为第三遍;代码生成作为第四遍。反之,为了适应较小的存储空间或提高目标程序质量,也可以把一个逻辑步骤的工作分为几遍去执行。例如,代码优化可划分为代码优化准备工作和实际代码优化两遍进行。
一个编译程序是否分遍,以及如何分遍,根据具体情况而定。其判别标准可以是存储容量的大小、源语言的繁简、解题范围的宽窄,以及设计、编制人员的多少等。分遍的好处是各遍功能独立单纯、相互联系简单、逻辑结构清晰、优化准备工作充分。缺点是各遍之中不可避免地要有些重复的部分,而且遍和遍之间要有交接工作,因之增加了编译程序的长度和编译时间。
一遍编译程序是一种极端情况,整个编译程序同时驻留在内存,彼此之间采用调用转接方式连接在一起(图2)。当语法分析程序需要新符号时,它就调用词法分析程序;当它识别出某一语法结构时,它就调用语义分析程序。语义分析程序对识别出的结构进行语义检查,并调用“存储分配”和“代码生成”程序生成相应的目标语言指令。
随着程序设计语言在形式化、结构化、直观化和智能化等方面的发展,作为实现相应语言功能的编译程序,也正向自动程序设计的目标发展,以便提供理想的程序设计工具。
参考书目
陈火旺、钱家骅、孙永强编:《编译原理》,国防工业出版社,北京,1980。
A.V.Aho, Principles of Compiler Design,Addison Wes-ley, Reading, Massachusetts, 1977.
--------------------------------------------------------------------------------
编译程序 (compiler)
将用高级程序设计语言书写的源程序,翻译成等价的用计算机汇编语言、机器语言或某种中间语言表示的目标程序的翻译程序。用户利用编译程序实现数据处理任务时,先要经历编译阶段,再经历运行阶段。编译阶段以源程序作为输入,以目标程序作为输出,其主要任务是将源程序翻译成目标程序。运行阶段的任务是运行所编译出的目标程序,实现源程序中指定的数据处理任务,其工作通常包括:输入初始数据,对数据或文件进行数据加工,输出必要信息和加工结果等。编译程序的实现算法较为复杂。这是因为它所翻译的语句与目标语言的指令不是一一对应关系,而是一多对应关系;同时因为它要在编译阶段处理递归调用、动态存储分配、多种数据类型 实现 、 代码生成与代码优化等繁杂技术问题;还要在运行阶段提供良好、有效的运行环境。由于高级程序设计语言书写的程序具有易读、易移植和表达能力强等特点,所以编译程序广泛地用于翻译规模较大、复杂性较高、且需要高效运行的高级语言书写的源程序。
功能 编译程序的基本功能是把源程序翻译成目标程序。此外,还要具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人机联系等具有实际应用价值的重要功能。①语法检查。检查源程序是否合乎语法 。②调试措施。检查源程序是否合乎用户的设计意图。③修改手段。为用户提供简便的修改源程序的手段。④覆盖处理。主要为处理程序较长、数据量较大的大型问题程序而设置。基本思想是让一些程序段和数据公用某些存储区,其中只存放当前要用的程序段或数据,其余暂时不用的程序段和数据均存放在磁盘等辅助存储器中,待需要时动态地调入存储区中运行。⑤目标程序优化。提高目标程序的质量,即使编译出的目标程序运行时间短、占用存储少。⑥不同语言合用 。便于用户利用多种程序设计语言编写应用程序或套用已有的不同语言书写的程序模块。最为常见的是高级语言和汇编语言的合用。⑦人机联系。便于用户在编译和运行阶段及时了解系统内部工作情况,有效地监督、控制系统的运行。
早期编译程序的实现方案,是把上述各项功能完全收纳在编译程序之中 。后来的习惯方法是在操作系统的支持下,配置编辑程序、调试程序、连接装配程序等实用程序或工具软件,目的是创造一个良好的开发环境和运行环境,便于应用软件的编程、修改、调试、集成以及报表生成、界面设计等工作。但编译程序设计者设计编译方案时,仍需精心考虑上述各项功能,较好地解决目标程序与这些实用程序或软件工具之间的配合与衔接等问题。
工作过程 编译程序必须分析源程序,然后综合成目标程序。为达到这个目的,编译程序要在分析阶段建立一些表格,改造源程序为中间语言形式,以便在分析和综合时易于引用和加工。
数据结构 分析和综合时所用的主要数据结构,包括符号表、常数表和中间语言程序。符号表由源程序中所用的标识符连同它们的属性组成,其中属性包括种类(如变量、数组、结构、函数、过程等)、类型(如整型、实型、字符串、复型、标号等),以及目标程序所需的其他信息。常数表由源程序中用的常数组成,其中包括常数的机内表示以及分配给它们的目标程序地址。中间语言程序是将源程序翻译成目标程序前引入的一种中间形式的程序,其表示形式的选择取决于编译程序以后如何使用它和如何加工它。常用的中间语言形式有波兰表示、三元组、四元组以及间接三元组等。
分析部分 源程序的分析是经过词法分析、语法分析和语义分析三个步骤实现的。词法分析由词法分析程序(又称为扫描程序 )完成,其任务是识别单词(即标识符 、常数、保留字,以及各种运算符、标点符号等)、造符号表和常数表,以及将源程序换码为编译程序易于分析和加工的内部形式。语法分析程序是编译程序的核心部分,其主要任务是根据语言的语法规则,检查源程序是否合乎语法,并分解源程序。如果不合乎语法,则输出语法出错信息;如果合乎语法,则分解源程 序的语法结构, 构造中间语 言形式的内部程序。语法分析的目的是掌握单词是怎样组成语句的,以及语句又是如何组成程序的。语义分析程序进一步检查合法程序结构的语义正确性,其目的是保证标识符和常数的正确使用,把必要的信息收集和保存到符号表或中间语言程序中,并进行相应的语义处理。
综合部分 综合阶段根据符号表和中间语言程序产生出目标程序,其主要工作包括代码优化、存储分配和代码生成。代码优化是通过重排和改变程序中的某些操作,以产生更加有效的目标程序。存储分配是为程序和数据分配运行时的存储单元。 代码生成是产 生与中间语 言程序等价的目标程序,亦即,顺序加工中间语言程序,利用符号表和常数表中的信息生成一系列的汇编语言或机器语言指令。
动态 20世纪80年代以后,程序设计语言在形式化、结构化、直观化和智能化等方面有了长足的进步和发展,主要表现在两个方面:①随着程序设计理论和方法的发展,相继推出了一系列新型程序设计语言,如结构化程序设计语言、并发程序设计语言、分布式程序设计语言、函数式程序设计语言、智能化程序设计语言、面向对象程序设计语言等;②基于语法、语义和语用方面的研究成果,从不同的角度和层次上深刻地揭示了程序设计语言的内在规律和外在表现形式。与此相应地,作为实现程序设计语言重要手段之一的编译程序,在体系结构、设计思想、实现技术和处理内容等方面均有不同程度的发展、变化和扩充。另外,编译程序已作为实现编程的重要软件工具,被纳入到软件支援环境的基本层软件工具之中。因此,规划编译程序实现方案时,应从所处的具体软件支援环境出发,既要遵循整个环境的全局性要求和规定,又要精心考虑与其他诸层软件 工具之间的相互支援、配合和衔接关系。

⑤ JAVA入门都需要那些书

java入门教程《21天学通java2》第三版
《Java编程思想》(thinking in java)第三版
TOMCAT HOME是指安装tomcat的主目录,并非是说目录的名字就叫“TOMCAT HOME”。

JAVA编程详解
Think in JAVA(有点难度,推荐在熟悉之后再看)
刚开始其实只要是基础的都能看,我给你个好的JAVA书籍下载站点:
http://www.javafan.net/index.jsp

学习一门新的知识,不可能指望只看一本,或者两本书就能够完全掌握。需要有一个循序渐进的阅读过程。我推荐Oreilly出版的Java系列书籍。

在这里我只想补充一点看法,很多人学习Java是从《Thinking in Java》这本书入手的,但是我认为这本书是不适合初学者的。我认为正确的使用这本书的方法应该是作为辅助的读物。《Thinking in Java》并不是在完整的介绍Java的整个体系,而是一种跳跃式的写作方法,是一种类似tips的方法来对Java很多知识点进行了深入的分析和解释。

对于初学者来说,最好是找一本Java入门的书籍,但是比较完整的循序的介绍Java的语法,面向对象的特性,核心类库等等,在看这本书的同时,可以同步来看《Thinking in Java》,来加深对Java的理解和原理的运用,同时又可以完整的了解Java的整个体系。

对于Java的入门书籍,蔡学镛推荐的是Oreilly的《Exploring Java, 2nd Edition》 或者《Java in a Nutshell,2nd Edition(针对C++背景)》,我并没有看过这两本书。其实我觉得电子工业出版社的《Java 2编程详解》或者《Java 2从入门到精通》就很不错。

在所有的Java书籍当中,其实最最有用的,并不是O'reilly的 Java Serials,真正最最有用处是JDK的Documentation!几乎你想获得的所有的知识在Documentation里面全部都有,其中最主要的部分当然是Java基础类库的API文档,是按照package来组织的,对于每一个class都有详细的解释,它的继承关系,是否实现了某个接口,通常用在哪些场合,还可以查到它所有的public的属性和方法,每个属性的解释,意义,每个方法的用途,调用的参数,参数的意义,返回值的类型,以及方法可能抛出的异常等等。可以这样来说,所有关于Java编程方面的书籍其实都不过是在用比较通俗易懂的语言,和良好的组织方式来介绍Documentation里面的某个package里面包含的一些类的用法而已。所以万变不离其宗,如果你有足够的能力来直接通过Documentation来学习Java的类库,那么基本上就不需要看其他的书籍了。除此之外,Documentation也是编程必备的手册,我的桌面上有三个Documentation的快捷方式,分别是J2SDK1.4.1的Documentation,Servlet2.3的Documentation和J2SDKEE1.3.1的Documentation。有了这个三个Documentation,什么其他的书籍都不需要了。

对于Java Web 编程来说,最核心的是要熟悉和掌握HTTP协议,这个就和Java无关了,在熟悉HTTP协议之后,就需要熟悉Java的实现HTTP协议的类库,也就是Servlet API,所以最重要的东西就是Servlet API。当然对于初学者而言,直接通过Servlet API来学习Web编程有很大的难度,我推荐O'reilly的《Java Server Pages 》这本书来学习Web 编程。

EJB的书籍当中,《Enterprise JavaBeans, 2nd Edition》是一本很不错的书, EJB的学习门槛是比较高,入门很难,但是这本书完全降低了学习的难度,特别重要的一点是,EJB的学习需要结合一种App Server的具体实现,所以在学习EJB的同时,必须同步的学习某种App Server,而这本书相关的出了三本书,分别是Weblogic6.1,Websphere4.0和JBoss3.0上面部署书中例子的实做。真是既有理论,又有实践。在学习EJB的同时,可以边看边做,EJB的学习会变得很轻松。

但是这本书也有一个问题,就是版本比较旧,主要讲EJB1.1规范和部分EJB2.0的规范。而Ed Roman写的《Mastering EJB 2.0》这本书完全是根据EJB2.0规范写的,深入浅出,覆盖了EJB编程的各个方面,并且还有很多编程经验tips,也是学习EJB非常推荐的书籍之一。

如果是结合Weblogic来学习J2EE的话,《J2EE应用与BEA Weblogic Server》绝对是首选读物,虽然是讲述的Weblogic6.0,仍然值得购买,这本书是BEA官方推荐的教材,作者也是BEA公司的工程师。现在中文版已经随处可见了。这本书结合Weblogic介绍了J2EE各个方面的技术在Weblogic平台上的开发和部署,实践指导意义非常强。

在掌握了Java平台基础知识和J2EE方面的知识以后,更进一步的是学习如何运用OO的方法进行软件的设计,那么就一定要学习“设计模式”。Sun公司出版了一本《J2EE核心模式》,是每个开发Java企业平台软件的架构师必备的书籍。这本书全面的介绍了J2EE体系架构的各种设计模式,是设计师的必读书籍。

Java Learning Path(三)过程篇

每个人的学习方法是不同的,一个人的方法不见得适合另一个人,我只能是谈自己的学习方法。因为我学习Java是完全自学的,从来没有问过别人,所以学习的过程基本上完全是自己摸索出来的。我也不知道这种方法是否是比较好的方法,只能给大家提供一点参考了。

学习Java的第一步是安装好JDK,写一个Hello World, 其实JDK的学习没有那么简单,关于JDK有两个问题是很容易一直困扰Java程序员的地方:一个是CLASSPATH的问题,其实从原理上来说,是要搞清楚JRE的ClassLoader是如何加载Class的;另一个问题是package和import问题,如何来寻找类的路径问题。把这两个问题摸索清楚了,就扫除了学习Java和使用JDK的最大障碍。推荐看一下王森的《Java深度历险》,对这两个问题进行了深入的探讨。

第二步是学习Java的语法。Java的语法是类C++的,基本上主流的编程语言不是类C,就是类C++的,没有什么新东西,所以语法的学习,大概就是半天的时间足够了。唯一需要注意的是有几个不容易搞清楚的关键字的用法,public,protected,private,static,什么时候用,为什么要用,怎么用,这可能需要有人来指点一下,我当初是完全自己琢磨出来的,花了很久的时间。不过后来我看到《Thinking in Java》这本书上面是讲了这些概念的。

第三步是学习Java的面向对象的编程语言的特性的地方。比如继承,构造器,抽象类,接口,方法的多态,重载,覆盖,Java的异常处理机制。对于一个没有面向对象语言背景的人来说,我觉得这个过程需要花很长很长时间,因为学习Java之前没有C++的经验,只有C的经验,我是大概花了一个月左右吧,才彻底把这些概念都搞清楚,把书上面的例子反复的揣摩,修改,尝试,把那几章内容反复的看过来,看过去,看了不下5遍,才彻底领悟了。不过我想如果有C++经验的话,应该一两天时间足够了。那么在这个过程中,可以多看看《Thinking in Java》这本书,对面向对象的讲解非常透彻。可惜的是我学习的时候,并没有看到这本书,所以自己花了大量的时间,通过自己的尝试和揣摩来学会的。

第四步就是开始熟悉Java的类库。Java的基础类库其实就是JDK安装目录下面jre\lib\rt.jar这个包。学习基础类库就是学习rt.jar。基础类库里面的类非常非常多。据说有3000多个,我没有统计过。但是真正对于我们来说最核心的只有4个,分别是
java.lang.*;
java.io.*;
java.util.*;
java.sql.*;

这四个包的学习,每个包的学习都可以写成一本厚厚的教材,而O'reilly也确实是这样做的。我觉得如果时间比较紧,是不可能通过读四本书来学习。我觉得比较好的学习方法是这样的:
首先要通读整个package的框架,了解整个package的class,interface,exception的构成,最好是能够找到介绍整个包框架的文章。这些专门介绍包的书籍的前几章应该就是这些总体的框架内容介绍。

对包整体框架的把握并不是要熟悉每个类的用法,记住它有哪些属性,方法。想记也记不住的。而是要知道包有哪些方面的类构成的,这些类的用途是什么,最核心的几个类分别是完成什么功能的。我在给人培训的时候一般是一次课讲一个包,所以不可能详细的介绍每个类的用法,但是我反复强调,我给你们讲这些包的不是要告诉你们类的方法是怎么调用的,也不要求你们记住类的方法调用,而是要你们了解,Java给我们提供了哪些类,每个类是用在什么场合,当我遇到问题的时候,我知道哪个类,或者哪几个类的组合可以解决我的问题,That'all!,当我们具体写程序的时候,只要你知道该用哪个类来完成你的工作就足够了。编码的时候,具体的方法调用,是边写代码,边查Documentation,所有的东西都在Documentation里面,不要求你一定记住,实际你也记不住3000多个类的总共将近10万个方法调用。所以对每个包的总体框架的把握就变得极为重要。

第五步,通过上面的学习,如果学的比较扎实的话,就打好了Java的基础了,剩下要做的工作是扫清Documentation里面除了上面4个包之外的其他一些比较有用处的类。相信进展到这一步,Java的自学能力已经被培养出来了,可以到了直接学习Documentation的水平了。除了要做GUI编程之外,JDK里面其他会有用处的包是这些:
java.text.*;
java.net.*;
javax.naming.*;
这些包里面真正用的比较多的类其实很少,只有几个,所以不需要花很多时间。

第六步,Java Web 编程
Web编程的核心是HTTP协议,HTTP协议和Java无关,如果不熟悉HTTP协议的话,虽然也可以学好Servlet/JSP编程,但是达不到举一反三,一通百通的境界。所以HTTP协议的学习是必备的。如果熟悉了HTTP协议的话,又有了Java编程的良好的基础,学习Servlet/JSP简直易如反掌,我学习Servlet/JSP就用了不到一周的时间,然后就开始用JSP来做项目了。

在Servlet/JSP的学习中,重头仍然是Servlet Documentation。Servlet API最常用的类很少,花比较少的时间就可以掌握了。把这些类都看一遍,多写几个例子试试。Servlet/JSP编程本质就是在反复调用这些类来通过HTTP协议在Web Server和Brower之间交谈。另外对JSP,还需要熟悉几个常用JSP的标记,具体的写法记不住的话,临时查就是了。

此外Java Web编程学习的重点要放在Web Application的设计模式上,如何进行业务逻辑的分析,并且进行合理的设计,按照MVC设计模式的要求,运用Servlet和JSP分别完成不同的逻辑层,掌握如何在Servlet和JSP之间进行流程的控制和数据的共享,以及Web Application应该如何配置和部署。

第七步,J2EE编程
以上的学习过程如果是比较顺利的话,进行到这一步,难度又陡然提高。因为上面的知识内容都是只涉及一个方面,而像EJB,JMS,JTA等核心的J2EE规范往往是几种Java技术的综合运用的结晶,所以掌握起来难度比较大。

首先一定要学习好JNDI,JNDI是App Server定位服务器资源(EJB组件,Datasouce,JMS)查找方法,如果对JNDI不熟悉的话,EJB,JMS这些东西几乎学不下去。JNDI其实就是javax.naming.*这个包,运用起来很简单。难点在于服务器资源文件的配置。对于服务器资源文件的配置,就需要看看专门的文档规范了,比如web.xml的写法,ejb-jar.xml的写法等等。针对每种不同的App Server,还有自己的服务资源配置文件,也是需要熟悉的。

然后可以学习JTA,主要是要理解JTA对于事务的控制的方法,以及该在什么场合使用JTA。这里可以简单的举个例子,我们知道一般情况可以对于一个数据库连接进行事务控制(conn.setAutoCommit(false),....,conn.commit()),做为一个原子操作,但是假设我的业务需求是要把对两个不同数据库的操作做为一个原子操作,你能做的到吗?这时候只能用JTA了。假设操作过程是先往A数据库插一条记录,然后删除B数据库另一个记录,我们自己写代码是控制不了把整个操作做为一个原子操作的。用JTA的话,由App Server来完成控制。

在学习EJB之前要学习对象序列化和RMI,RMI是EJB的基础。接着学习JMS和EJB,对于EJB来说,最关键是要理解EJB是如何通过RMI来实现对远端对象的调用的,以及在什么情况下要用到EJB。

在学习完EJB,JMS这些东西之后,你可能会意识到要急不可待学习两个领域的知识,一个是UML,另一个是Design Pattern。Java企业软件的设计非常重视框架(Framework)的设计,一个好的软件框架是软件开发成功的必要条件。在这个时候,应该开始把学习的重点放在设计模式和框架的学习上,通过学习和实际的编程经验来掌握EJB的设计模式和J2EE的核心模式。

J2EE规范里面,除了EJB,JMS,JTA,Servlet/JSP,JDBC之外还有很多很多的企业技术,这里不一一进行介绍了。

另外还有一个最新领域Web Services。Web Services也完全没有任何新东西,它像是一种黏合剂,可以把不同的服务统一起来提供一个统一的调用接口,作为使用者来说,我只要获得服务提供者给我的WSDL(对服务的描述),就够了,我完全不知道服务器提供者提供的服务究竟是EJB组件,还是.Net组件,还是什么CORBA组件,还是其他的什么实现,我也不需要知道。Web Services最伟大的地方就在于通过统一的服务提供方式和调用方式,实现了整个Internet服务的共享,是一个非常令人激动的技术领域。Web Services好像目前还没有什么很好的书籍,但是可以通过在网络上面查资料的方式来学习。

Java Learning Path(四) 方法篇

Java作为一门编程语言,最好的学习方法就是写代码。当你学习一个类以后,你就可以自己写个简单的例子程序来运行一下,看看有什么结果,然后再多调用几个类的方法,看看运行结果,这样非常直观的把类给学会了,而且记忆非常深刻。然后不应该满足把代码调通,你应该想想看如果我不这样写,换个方式,再试试行不行。记得哪个高人说过学习编程就是个破坏的过程,把书上的例子,自己学习Documentation编写的例子在运行通过以后,不断的尝试着用不同的方法实现,不断的尝试破坏代码的结构,看看它会有什么结果。通过这样的方式,你会很彻底的很精通的掌握Java。

举个例子,我们都编过Hello World

public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

很多初学者不是很理解为什么main方法一定要这样来定义public static void main(String[] args),能不能不这样写?包括我刚学习Java的时候也有这样的疑问。想知道答案吗?很简单,你把main改个名字运行一下,看看报什么错误,然后根据出错信息进行分析;把main的public取掉,在试试看,报什么错误;static去掉还能不能运行;不知道main方法是否一定要传一个String[]数组的,把String[]改掉,改成int[],或者String试试看;不知道是否必须写args参数名称的,也可以把args改成别的名字,看看运行结果如何。

我当初学习Java的时候就是这样做的,把Hello World程序反复改了七八次,不断运行,分析运行结果,最后就彻底明白为什么了main方法是这样定义的了。

此外,我对于staic,public,private,Exception,try{ }catch {}finally{}等等等等一开始都不是很懂,都是把参考书上面的例子运行成功,然后就开始破坏它,不断的根据自己心里面的疑问来重新改写程序,看看能不能运行,运行出来是个什么样子,是否可以得到预期的结果。这样虽然比较费时间,不过一个例子程序这样反复破坏几次之后。我就对这个相关的知识彻底学通了。有时候甚至故意写一些错误的代码来运行,看看能否得到预期的运行错误。这样对于编程的掌握是及其深刻的。

其中特别值得一提的是JDK有一个非常棒的调试功能,-verbose
java –verbose
javac –verbose 以及其它很多JDK工具都有这个选项
-verbose 可以显示在命令执行的过程中,JVM都依次加载哪里Class,通过这些宝贵的调试信息,可以帮助我们分析出JVM在执行的过程中都干了些什么。

另外,自己在学习过程中,写的很多的这种破坏例程,应该有意识的分门别类的保存下来,在工作中积累的典型例程也应该定期整理,日积月累,自己就有了一个代码库了。遇到类似的问题,到代码库里面 Copy & Paste ,Search & Replace,就好了,极大提高了开发速度。最理想的情况是把一些通用的例程自己再抽象一层,形成一个通用的类库,封装好。那么可复用性就更强了。

所以我觉得其实不是特别需要例程的,自己写的破坏例程就是最好的例子,如果你实在对自己写的代码不放心的话,我强烈推荐你看看JDK基础类库的Java源代码。在JDK安装目录下面会有一个src.zip,解开来就可以完整的看到整个JDK基础类库,也就是rt.jar的Java源代码,你可以参考一下Sun是怎么写Java程序的,规范是什么样子的。我自己在学习Java的类库的时候,当有些地方理解的不是很清楚的时候,或者想更加清晰的理解运作的细节的时候,往往会打开相应的类的源代码,通过看源代码,所有的问题都会一扫而空。

Java Learning Path(五)资源篇

1、 http://java.sun.com/ (英文)
Sun的Java网站,是一个应该经常去看的地方。不用多说。

2、http://www-900.ibm.com/developerWorks/cn/
IBM的developerWorks网站,英语好的直接去英文主站点看。这里不但是一个极好的面向对象的分析设计网站,也是Web Services,Java,Linux极好的网站。强烈推荐!!!

3、http://www.javaworld.com/ (英文)
关于Java很多新技术的讨论和新闻。想多了解Java的方方面面的应用,这里比较好。

4、http://dev2dev.bea.com.cn/index.jsp
BEA的开发者园地,BEA作为最重要的App Server厂商,有很多独到的技术,在Weblogic上做开发的朋友不容错过。

5、http://www.huihoo.com/
灰狐动力网站,一个专业的中间件网站,虽然不是专业的Java网站,但是在J2EE企业应用技术方面有深厚的造诣。

6、http://www.theserverside.com/home/ (英文)
TheServerSide是一个着名的专门面向Java Server端应用的网站。

7、http://www.javaresearch.org/
Java研究组织,有很多优秀的Java方面的文章和教程,特别是在JDO方面的文章比较丰富。

8、http://www.cnjsp.org/
JSP技术网站,有相当多的Java方面的文章和资源。

9、http://www.jdon.com/
Jdon论坛,是一个个人性质的中文J2EE专业技术论坛,在众多的Java的中文论坛中,Jdon一个是技术含量非常高,帖子质量非常好的论坛。

10、http://sourceforge.net/
SourgeForge是一个开放源代码软件的大本营,其中也有非常非常丰富的Java的开放源代码的着名的软件。

⑥ 编译原理全部的名词解释

书上有别那么懒!。。。。
编译过程的六个阶段:词法分析,语法分析,语义分析,中间代码生成,代码优化,目标代码生成
解释程序:把某种语言的源程序转换成等价的另一种语言程序——目标语言程序,然后再执行目标程序。解释方式是接受某高级语言的一个语句输入,进行解释并控制计算机执行,马上得到这句的执行结果,然后再接受下一句。
编译程序:就是指这样一种程序,通过它能够将用高级语言编写的源程序转换成与之在逻辑上等价的低级语言形式的目标程序(机器语言程序或汇编语言程序)。
解释程序和编译程序的根本区别:是否生成目标代码
句子的二义性(这里的二义性是指语法结构上的。):文法G[S]的一个句子如果能找到两种不同的最左推导(或最右推导),或者存在两棵不同的语法树,则称这个句子是二义性的。
文法的二义性:一个文法如果包含二义性的句子,则这个文法是二义文法,否则是无二义文法。
LL(1)的含义:(LL(1)文法是无二义的; LL(1)文法不含左递归)
第1个L:从左到右扫描输入串 第2个L:生成的是最左推导
1 :向右看1个输入符号便可决定选择哪个产生式
某些非LL(1)文法到LL(1)文法的等价变换: 1. 提取公因子 2. 消除左递归
文法符号的属性:单词的含义,即与文法符号相关的一些信息。如,类型、值、存储地址等。
一个属性文法(attribute grammar)是一个三元组A=(G, V, F)
G:上下文无关文法。
V:属性的有穷集。每个属性与文法的一个终结符或非终结符相连。属性与变量一样,可以进行计算和传递。
F:关于属性的断言或谓词(一组属性的计算规则)的有穷集。断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。
综合属性:若产生式左部的单非终结符A的属性值由右部各非终结符的属性值决定,则A的属性称为综合属
继承属性:若产生式右部符号B的属性值是根据左部非终结符的属性值或者右部其它符号的属性值决定的,则B的属性为继承属性。
(1)非终结符既可有综合属性也可有继承属性,但文法开始符号没有继承属性。
(2) 终结符只有综合属性,没有继承属性,它们由词法程序提供。
在计算时: 综合属性沿属性语法树向上传递;继承属性沿属性语法树向下传递。
语法制导翻译:是指在语法分析过程中,完成附加在所使用的产生式上的语义规则描述的动作。
语法制导翻译实现:对单词符号串进行语法分析,构造语法分析树,然后根据需要构造属性依赖图,遍历语法树并在语法树的各结点处按语义规则进行计算。
中间代码(中间语言)
1、是复杂性介于源程序语言和机器语言的一种表示形式。
2、一般,快速编译程序直接生成目标代码。
3、为了使编译程序结构在逻辑上更为简单明确,常采用中间代码,这样可以将与机器相关的某些实现细节置于代码生成阶段仔细处理,并且可以在中间代码一级进行优化工作,使得代码优化比较容易实现。
何谓中间代码:源程序的一种内部表示,不依赖目标机的结构,易于代码的机械生成。
为何要转换成中间代码:(1)逻辑结构清楚;利于不同目标机上实现同一种语言。
(2)便于移植,便于修改,便于进行与机器无关的优化。
中间代码的几种形式:逆波兰记号 ,三元式和树形表示 ,四元式
符号表的一般形式:一张符号表的的组成包括两项,即名字栏和信息栏。
信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,名字栏也称主栏。主栏的内容称为关键字(key word)。
符号表的功能:(1)收集符号属性 (2) 上下文语义的合法性检查的依据: 检查标识符属性在上下文中的一致性和合法性。(3)作为目标代码生成阶段地址分配的依据
符号的主要属性及作用:
1. 符号名 2. 符号的类型 (整型、实型、字符串型等))3. 符号的存储类别(公共、私有)
4. 符号的作用域及可视性 (全局、局部) 5. 符号变量的存储分配信息 (静态存储区、动态存储区)
存储分配方案策略:静态存储分配;动态存储分配:栈式、 堆式。
静态存储分配
1、基本策略
在编译时就安排好目标程序运行时的全部数据空间,并能确定每个数据项的单元地址。
2、适用的分配对象:子程序的目标代码段;全局数据目标(全局变量)
3、静态存储分配的要求:不允许递归调用,不含有可变数组。
FORTRAN程序是段结构,不允许递归,数据名大小、性质固定。 是典型的静态分配
动态存储分配
1、如果一个程序设计语言允许递归过程、可变数组或允许用户自由申请和释放空间,那么,就需要采用动态存储管理技术。
2、两种动态存储分配方式:栈式,堆式
栈式动态存储分配
分配策略:将整个程序的数据空间设计为一个栈。
【例】在具有递归结构的语言程序中,每当调用一个过程时,它所需的数据空间就分配在栈顶,每当过程工作结束时就释放这部分空间。
过程所需的数据空间包括两部分
一部分是生存期在本过程这次活动中的数据对象。如局部变量、参数单元、临时变量等;
另一部分则是用以管理过程活动的记录信息(连接数据)。
活动记录(AR)
一个过程的一次执行所需要的信息使用一个连续的存储区来管理,这个区 (块)叫做一个活动记录。
构成
1、临时工作单元;2、局部变量;3、机器状态信息;4、存取链;
5、控制链;6、实参;7、返回地址
什么是代码优化
所谓优化,就是对代码进行等价变换,使得变换后的代码运行结果与变换前代码运行结果相同,而运行速度加快或占用存储空间减少。
优化原则:等价原则:经过优化后不应改变程序运行的结果。
有效原则:使优化后所产生的目标代码运行时间较短,占用的存储空间较小。
合算原则:以尽可能低的代价取得较好的优化效果。
常见的优化技术
(1) 删除多余运算(删除公共子表达式) (2) 代码外提 +删除归纳变量+ (3)强度削弱; (4)变换循环控制条件 (5)合并已知量与复写传播 (6)删除无用赋值
基本块定义
程序中只有一个入口和一个出口的一段顺序执行的语句序列,称为程序的一个基本块。

给我分数啊。。。

⑦ 谁能告诉我:计算机程序设计语言发展史和对程序设计语言未来的看法

【摘要】

本文以自然辩证的观点探讨了计算机语言的发展历程,运用自然辩证法的基本理论、基本方法,系统分析了计算机语言的发展历史、现状和未来。并对其的发展趋势和未来模式做了探索性研究和预测,同时以哲学的观点阐述其发展的因果关系,揭示其事物发展的共性问题;最后文章介绍了在计算机语言发展历程中做出杰出贡献的科学家,以其在计算机事业中的突出表现来折射出人类智慧的伟大,以其不平凡的一生来激励和指导我们在计算机语言的发展中向着正确的方向前进。

【关键字】

自然辩证法 计算机语言 计算机技术 编程语言 因特网 面向对象

正文

一九九三年美国的克林顿政府提出了“信息高速公路”计划,从而在这十多年间在全球范围内引发了一场信息风暴,信息技术几乎触及了现代生活的方方面面,毫不夸张的说没有了信息技术,现代文明的生活将无从谈起;作为信息技术中最重要的部分,计算机技术无疑是其发展的核心问题,而我们知道计算机只是一台机器,它只能按照计算机语言编好的程序执行,那么正确认识计算机语言的过去和未来,就是关系到计算机发展的重中之重;以自然辩证法的观点认识和分析计算机语言的发展历程,将有助于更加全面地推动计算机技术的发展,有助于更加准确地掌握计算机语言发展趋势。

一、科学认识大门的钥匙--当代自然辩证法

自然辩证法,是马克思主义对于自然界和科学技术发展的一般规律以及人类认识自然改造自然的一般方法的科学,是辩证唯物主义的自然观、科学技术观、科学技术方法论。它主要研究自然界发展的总规律,人与自然相互作用的规律,科学技术发展的一般规律,科学技术研究的方法。

马克思、恩格斯全面地、系统地概括了他们所处时代的科学技术成功,批判吸取了前人的合理成分,系统地论述了辩证唯物主义自然观、自然科学发展过程及其规律性,以及科学认识方法的辩证法,以恩格斯的光辉着作《自然辩证法》为标志,创立了自然辩证法继续发展的广阔道路。

自然辩证法是马克思主义哲学的一个重要组成部分。在辩证唯物主义哲学体系中,自然辩证法与历史唯物论相并列。它集中研究自然界和科学技术的辩证法,是唯物主义在自然界和科学技术领域中的应用,它的原理和方法主要适用于自然领域和科学技术领域。

学习和运用自然辩证法将有助于我们搞清科学和哲学的关系,从而更加清楚地认识科学的本质和发展规律,更加全面的观察思考问题,只有加深了认识,我们才能更好地发挥主观能动性,迎接新的科学技术的挑战。下面我将以自然辩证法的观点来分析计算机语言的发展历程。

二、计算机语言的发展历程和发展趋势

计算机语言的发展是一个不断演化的过程,其根本的推动力就是抽象机制更高的要求,以及对程序设计思想的更好的支持。具体的说,就是把机器能够理解的语言提升到也能够很好的模仿人类思考问题的形式。计算机语言的演化从最开始的机器语言到汇编语言到各种结构化高级语言,最后到支持面向对象技术的面向对象语言。

1、计算机语言的发展历史:二十世纪四十年代当计算机刚刚问世的时候,程序员必须手动控制计算机。当时的计算机十分昂贵,唯一想到利用程序设计语言来解决问题的人是德国工程师楚泽 (konrad zuse)。几十年后,计算机的价格大幅度下跌,而计算机程序也越来越复杂。也就是说,开发时间已经远比运行时间来得宝贵。于是,新的集成、可视的开发环境越来越流行。它们减少了所付出的时间、金钱(以及脑细胞)。只要轻敲几个键,一整段代码就可以使用了。这也得益于可以重用的程序代码库。随着c, pascal,fortran,等结构化高级语言的诞生,使程序员可以离开机器层次,在更抽象的层次上表达意图。由此诞生的三种重要控制结构,以及一些基本数据类型都能够很好的开始让程序员以接近问题本质的方式去思考和描述问题。随着程序规模的不断扩大,在60年代末期出现了软件危机,在当时的程序设计模型中都无法克服错误随着代码的扩大而级数般的扩大,以至到了无法控制的地步,这个时候就出现了一种新的思考程序设计方式和程序设计模型-----面向对象程序设计,由此也诞生了一批支持此技术的程序设计语言,比如eiffel,c++,java,这些语言都以新的观点去看待问题,即问题就是由各种不同属性的对象以及对象之间的消息传递构成。面向对象语言由此必须支持新的程序设计技术,例如:数据隐藏,数据抽象,用户定义类型,继承,多态等等。

2、计算机语言的发展现状:目前通用的编程语言有两种形式:汇编语言和高级语言。

汇编语言的实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,更容易识别和记忆。用汇编语言所能完成的操作不是一般高级语言所能实现的,而且源程序经汇编生成的可执行文件不仅比较小,而且执行速度很快。

高级语言是目前绝大多数编程者的选择。和汇编语言相比,它不但将许多相关的机器指令合成为单条指令,并且去掉了与具体操作有关但与完成工作无关的细节,例如使用堆栈、寄存器等,这样就大大简化了程序中的指令。同时,由于省略了很多细节,编程者也就不需要有太多的专业知识。

高级语言主要是相对于汇编语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,如目前流行的vb、vc、foxpro、delphi等,这些语言的语法、命令格式都各不相同。

高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,按转换方式可将它们分为两类: 解释类和编译类。

3、计算机语言的发展趋势:面向对象程序设计以及数据抽象在现代程序设计思想中占有很重要的地位,未来语言的发展将不在是一种单纯的语言标准,将会以一种完全面向对象,更易表达现实世界,更易为人编写,其使用将不再只是专业的编程人员,人们完全可以用订制真实生活中一项工作流程的简单方式来完成编程。下面是一张计算机语言发展图表,从中不难得出计算机语言发展的特性:

² 简单性

提供最基本的方法来完成指定的任务,只需理解一些基本的概念,就可以用它编写出适合于各种情况的应用程序

² 面向对象

提供简单的类机制以及动态的接口模型。对象中封装状态变量以及相应的方法,实现了模块化和信息隐藏;提供了一类对象的原型,并且通过继承机制,子类可以使用父类所提供的方法,实现了代码的复用

² 安全性

用于网络、分布环境下有安全机制保证。

² 平台无关性

与平台无关的特性使程序可以方便地被移植到网络上的不同机器、不同平台。

三、面向未来的汉语程序设计语言:

从计算机诞生至今,计算机自硬件到软件都是以印欧语为母语的人发明的。所以其本身就带有印欧语的语言特征,在硬件上cpu、i/o、存储器的基础结构都体现了印欧语思维状态的"焦点视角",精确定义,分工明确等特点。计算机语言也遵照硬件的条件,使用分析式的结构方法,严格分类、专有专用,并在其发展脉络中如同他们的语言-常用字量和历史积累词库量极度膨胀。实际上,计算机硬件的发展越来越强调整体功能,计算机语言的问题日益突出。为解决这一矛盾,自六十年代以来相继有500多种计算机语言出现,历经五代,至今仍在变化不已。

汉语没有严格的语法框架,字词可以自由组合、突出功能的整体性语言。在计算机语言问题成为发展瓶颈的今天,汉语言进入计算机程序设计语言行列,已经成为历史的必然。

1、 发展汉语程序设计语言的理由:

1)计算机语言问题解决,只能从人类语言中寻找解决方案;

2)计算机语言的现存问题是形式状态与功能需求的矛盾;

3)计算机硬件的发展已为整体性语言-汉语进入计算机程序设计语言提供了条件

2、 汉语程序设计语言的技术特点:

1)汉文字的常用字高度集中,生命力极强,能灵活组合,简明准确地表达日新月异的词汇,这些优点是拼音文字无法企及的。

2)汉语言的语法简易灵活,语词单位大小和性质往往无一定规,可随上下语境和逻辑需要自由运用。汉语言的思维整体性强,功能特征突出。

3)汉语程序设计语言的发明者采用核心词库与无限寄存器相结合的方法,实现了汉语言的词素自由组合;将编译器与解释器合一,使汉语程序设计语言既能指令又能编程;以独特的虚拟机结构设计,将数据流与意识流分开,达到汉语程序设计语言与汉语描述完全一致,通用自如。

具有汉语言特性的汉语程序设计语言的出现,打破了汉语言不具备与计算机结合的条件而不能完成机器编码的神话。还为计算机科学与现代语言学研究提出了一条崭新的路径,它从计算机语言的角度,从严格的机械活动及周密的算法上,向世人证实汉语的特殊结构状态,及其特殊的功能。

四、计算机语言之父——尼盖德

尼盖德帮助因特网奠下了基础,为计算机业做出了巨大贡献。

尼盖德是奥斯陆大学的教授,因为发展了simula编程语言,为ms-dos和因特网打下了基础而享誉国际。克里斯汀·尼盖德于1926年在奥斯陆出生,1956年毕业于奥斯陆大学并取得数学硕士学位,此后致力于计算机计算与编程研究。

1961年~1967年,尼盖德在挪威计算机中心工作,参与开发了面向对象的编程语言。因为表现出色,2001年,尼盖德和同事奥尔·约安·达尔获得了2001年a.m.图灵机奖及其它多个奖项。当时为尼盖德颁奖的计算机协会认为他们的工作为java,c++等编程语言在个人电脑和家庭娱乐装置的广泛应用扫清了道路,“他们的工作使软件系统的设计和编程发生了基本改变,可循环使用的、可靠的、可升级的软件也因此得以面世。”

尼盖德因其卓越的贡献,而被誉为“计算机语言之父”,其对计算机语言发展趋势的掌握和认识,以及投身于计算机语言事业发展的精神都将激励我们向着计算机语言无比灿烂的明天前进。

五、结束语

用科学的逻辑思维方法认识事物才会清楚的了解其过去、现在和未来,计算机语言的发展同样遵循着科学技术发展的一般规律,以自然辩证法的观点来分析计算机语言,有助于我们更加深入地认识计算机语言发展的历史、现状和趋势,有了自然辩证法这把开启科学认识大门的钥匙,我们将回首过去、把握现在、放眼未来,正确地选择计算机语言发展的方向,更好的学习、利用和发展计算机语言。

六、致谢

热点内容
差距的算法 发布:2024-11-23 06:48:09 浏览:884
hmcl离线服务器怎么装皮肤 发布:2024-11-23 06:42:49 浏览:230
各型缓存器年额最高多少 发布:2024-11-23 06:42:43 浏览:62
光谱特征编译 发布:2024-11-23 06:19:46 浏览:893
怎样拍视频上传 发布:2024-11-23 06:15:39 浏览:904
创建个存储过程 发布:2024-11-23 06:15:35 浏览:378
市场配置资源的主体地位如何理解 发布:2024-11-23 06:13:48 浏览:729
单循环编程题 发布:2024-11-23 06:09:04 浏览:564
解压后有个文件看不到 发布:2024-11-23 05:54:01 浏览:126
android功耗 发布:2024-11-23 05:53:53 浏览:752