编译原理-预测分析法(附源码)

编译原理-预测分析法(附源码)
编译原理-预测分析法(附源码)

预测分析法实验报告

一、实验项目名称

预测分析法

二、实验目的

根据某一LL(1)文法编制调试预测分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对预测分析法的理解。

三、实验环境

Windows 10

Microsoft Visual Studio 2015

四、实验内容

本次实验的LL(1)文法为表达式文法:

E→E+T | T

T→T*F | F

F→i | (E)

编写识别表达式文法的合法句子的预测分析程序,对输入的任意符号串,给出分析过程及分析结果。分析过程要求输出步骤、分析栈、剩余输入串和所用产生式。如果该符号串不是表达式文法的合法句子,要给出尽量详细的错误提示

五、源程序清单、测试数据、结果

#include

#include

using namespace std;

const int NUM = 20;//初始化的栈的大小

//非终结符数组集

char Var[5] = { 'E','R','T','M','F' };

//终结符数组集

char Ter[6] = { 'i','+','*','(',')','#' };

string pred[5][6] =

{ { "TR","","","TR","","" },{ "","+TR","","","@","@" },{ "FM","","","FM","","" },{ ""," @","*FM","","@","@" },{ "i","","","(E)","","" } };

typedef struct {

char *top;

char *base;

int stacksize;

int num;

}Stack;// 栈结构体

void init(Stack *ss) {//初始化栈

ss->base = (char *)malloc(NUM * sizeof(char));

if (!ss->base)

exit(1);

ss->top = ss->base;

ss->stacksize = NUM;

ss->num = 0;

}

void push(Stack *ss, char c) {//入栈操作

if (ss->top - ss->base >= ss->stacksize)

exit(1);

*(ss->top) = c;

ss->top++;

ss->num++;

}

void pop(Stack *ss) {//出栈操作

if (ss->top == ss->base)

exit(1);

ss->top--;

ss->num--;

}

char getTop(Stack *ss) {//取得栈顶元素

if (ss->top == ss->base)

exit(1);

return *(ss->top - 1);

}

int isT(char c) {//判断是否为终结符

int i = 0;

int ret = 0;

for (i = 0; i<6; i++) {

if (Ter[i] == c)

{

ret = 1; break;

}

}

return ret;

}

string isInPred(char v, char t) {//查找预测分析表,并返回产生式右部int i, j;

for (i = 0; i<5; i++)

{

if (Var[i] == v)

break;

}

for (j = 0; j<6; j++)

{

if (Ter[j] == t)

break;

}

if (pred[i][j] !="")

{

return pred[i][j];

}

else

return"";

}

void displayStack(Stack *stack) { //输出分析站的内容

string str;

int i = 0;

Stack ss = *stack;

while (ss.num != 0)

{

str += getTop(&ss);

pop(&ss);

}

for (i = str.length() - 1; i >= 0; i--)

{

cout << str.at(i);

}

}

void predict(Stack stack, string input)//预测分析总函数

{

int a = 1;

char b;

char ctop;//当前栈顶符号

char cinput;//当前输入符号

int i = 0, j = 0, count = 0;

int error = 0;

cout <<"步骤"<<'\t'<<"栈"<<'\t'<<"输入缓冲区"<<'\t'<<"所用的产生式"<

cout << count++ <<'\t';

displayStack(&stack);

cout <<'\t'<

while (getTop(&stack) != '#')

{

string produce = "";

ctop = getTop(&stack);

cinput = input.at(i);

if (isT(ctop))//栈顶符号为终结符

{

if (ctop == cinput)

{

pop(&stack);

i++;

}

else

{

error = 1; break;

}

produce +="\"";

produce += ctop;

produce +="\"匹配";

}

else//栈顶符号位非终结符

{

string str = isInPred(ctop, cinput);

if (str !="")

{

pop(&stack);

if (str !="@")

{

for (j = str.length() - 1; j >= 0; j--)

push(&stack, str.at(j));

}

produce += ctop;

produce +="→";

produce += str;

}

else

{

error = 1; break;

}

}//栈顶符号位非终结符

cout << count++ <<'\t';

displayStack(&stack);

cout <<'\t'<

}

if (error)

cout <<"不接受"<< endl;

else

cout <<"接受"<< endl;

}

void main()

{

while (1) {

int sel;//继续或者退出程序选择

string input;//输入串

int i = 0, j = 0;

Stack stack;

init(&stack);

push(&stack, '#');

push(&stack, 'E');

cout <<"----------------文法如下--------------"<< endl;

cout <<"E→E+T | T"<< endl;

cout <<"T→T*F | F"<< endl;

cout <<" F→i | (E)"<< endl;

cout <<"----------------请输入表达式(以#结尾)--------------"<< endl;

cin >> input;

cout <<"“R表示“E'”,”M“表示“T'”,”@“表示“空”"<< endl;

predict(stack, input);

sel=0;

if (sel == 0)

exit(0);

else

system("cls");

}

}

六、实验小结和思考

本次实验的文法是写在程序中的,不可以自行输入,难度不是很难,并没有太大问题,只是一些未初始化的小问题。以后要积极做实验,做的程序要更加灵活。

编译原理实验报告实验一编写词法分析程序

编译原理实验报告实验名称:实验一编写词法分析程序 实验类型:验证型实验 指导教师:何中胜 专业班级:13软件四 姓名:丁越 学号: 电子邮箱: 实验地点:秋白楼B720 实验成绩: 日期:2016年3 月18 日

一、实验目的 通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析 程序所用的工具自动机,进一步理解自动机理论。掌握文法转换成自动机的技术及有穷自动机实现的方法。确定词法分析器的输出形式及标识符与关键字的区分方法。加深对课堂教学的理解;提高词法分析方法的实践能力。通过本实验,应达到以下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、实验过程 以编写PASCAL子集的词法分析程序为例 1.理论部分 (1)主程序设计考虑 主程序的说明部分为各种表格和变量安排空间。 数组 k为关键字表,每个数组元素存放一个关键字。采用定长的方式,较短的关键字 后面补空格。 P数组存放分界符。为了简单起见,分界符、算术运算符和关系运算符都放在 p表中 (编程时,还应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。 id和ci数组分别存放标识符和常数。 instring数组为输入源程序的单词缓存。 outtoken记录为输出内部表示缓存。 还有一些为造表填表设置的变量。 主程序开始后,先以人工方式输入关键字,造 k表;再输入分界符等造p表。 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上 送来的一个单词;调用词法分析过程;输出每个单词的内部码。 ⑵词法分析过程考虑 将词法分析程序设计成独立一遍扫描源程序的结构。其流程图见图1-1。 图1-1 该过程取名为 lexical,它根据输入单词的第一个字符(有时还需读第二个字符),判断单词类,产生类号:以字符 k表示关键字;i表示标识符;c表示常数;p表示分界符;s表示运算符(编程时类号分别为 1,2,3,4,5)。 对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有 该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id中,将常数 变为二进制形式存入数组中 ci中,并记录其在表中的位置。 lexical过程中嵌有两个小过程:一个名为getchar,其功能为从instring中按顺序取出一个字符,并将其指针pint加1;另一个名为error,当出现错误时,调用这个过程, 输出错误编号。 2.实践部分

编译原理知识点汇总

编译原理的复习提纲 1.编译原理=形式语言+编译技术 2.汇编程序: 把汇编语言程序翻译成等价的机器语言程序 3.编译程序: 把高级语言程序翻译成等价的低级语言程序 4.解释执行方式: 解释程序,逐个语句地模拟执行 翻译执行方式: 翻译程序,把程序设计语言程序翻译成等价的目标程序 5.计算机程序的编译过程类似,一般分为五个阶段: 词法分析、语法分析、语义分析及中间代码生成、代码优化、目标代码生成 词法分析的任务: 扫描源程序的字符串,识别出的最小的语法单位(标识符或无正负号数等) 语法分析是: 在词法分析的基础上的,语法分析不考虑语义。语法分析读入词法分析程序识别出的符号,根据给定的语法规则,识别出各个语法结构。 语义分析的任务是检查程序语义的正确性,解释程序结构的含义,语义分析包括检查变量是否有定义,变量在使用前是否具有值,数值是否溢出等。

语法分析完成之后,编译程序通常就依据语言的语义规则,利用语法制导技术把源程序翻译成某种中间代码。所谓中间代码是一种定义明确、便于处理、独立于计算机硬件的记号系统,可以认为是一种抽象机的程序 代码优化的主要任务是对前一阶段产生的中间代码进行等价变换,以便产生速度快、空间小的目标代码 编译的最后一个阶段是目标代码生成,其主要任务是把中间代码翻译成特定的机器指令或汇编程序 编译程序结构包括五个基本功能模块和两个辅助模块 6.编译划分成前端和后端。 编译前端的工作包括词法分析、语法分析、语义分析。编译前端只依赖于源程序,独立于目标计算机。前端进行分析 编译后端的工作主要是目标代码的生成和优化后端进行综合。独立于源程序,完全依赖于目标机器和中间代码。 把编译程序分为前端和后端的优点是: 可以优化配置不同的编译程序组合,实现编译重用,保持语言与机器的独立性。 7.汇编器把汇编语言代码翻译成一个特定的机器指令序列 第二章 1.符号,字母表,符号串,符号串的长度计算P18,子符号串的含义,符号串的简单运算XY,Xn, 2.符号串集合的概念,符号串集合的乘积运算,方幂运算,闭包与正闭包的概念P19,P20A0 ={ε} 3.重写规则,简称规则。非xx(V

编译原理实验指导

编译原理实验指导 实验安排: 上机实践按小组完成实验任务。每小组三人,分别完成TEST语言的词法分析、语法分析、语义分析和中间代码生成三个题目,语法分析部分可任意选择一种语法分析方法。先各自调试运行,然后每小组将程序连接在一起调试,构成一个相对完整的编译器。 实验报告: 上机结束后提交实验报告,报告内容: 1.小组成员; 2.个人完成的任务; 3.分析及设计的过程; 4.程序的连接; 5.设计中遇到的问题及解决方案; 6.总结。

实验一词法分析 一、实验目的 通过设计编制调试TEST语言的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 二、实验预习提示 1.词法分析器的功能和输出格式 词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示 成以下的二元式(单词种别码,单词符号的属性值)。 2.TEST语言的词法规则 |ID|ID |NUM →a|b|…|z|A|B|…|Z →1|2|…|9|0 →+|-|*|/|=|(|)|{|}|:|,|;|<|>|! →>=|<=|!=|== →/* →*/ 三、实验过程和指导 1.阅读课本有关章节,明确语言的语法,画出状态图和词法分析算法流程图。 2.编制好程序。 3.准备好多组测试数据。 4.程序要求 程序输入/输出示例:

实验1-3-《编译原理》词法分析程序设计方案

实验1-3 《编译原理》S语言词法分析程序设计方案 一、实验目的 了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式; 二、实验内容 1.根据状态转换图直接编程 编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法分析程序作为单独的一遍,如下图所示。 具体任务有: (1)组织源程序的输入 (2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件 (3)删除注释、空格和无用符号 (4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。将错误信息输出到屏幕上。 (5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。 标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址 注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。 常量表结构:常量名,常量值 三、实验要求 1.能对任何S语言源程序进行分析 在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。 2.能检查并处理某些词法分析错误 词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。 本实验要求处理以下两种错误(编号分别为1,2): 1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。 2:源程序文件结束而注释未结束。注释格式为:/* …… */ 四、保留字和特殊符号表

编译原理实验代码

[实验任务] 完成以下正则文法所描述的Pascal语言子集单词符号的词法分析程序。 <标识符>→字母︱<标识符>字母︱<标识符>数字 <无符号整数>→数字︱<无符号整数>数字 <单字符分界符> →+ ︱-︱* ︱; ︱(︱) <双字符分界符>→<大于>=︱<小于>=︱<小于>>︱<冒号>=︱<斜竖>* <小于>→< <等于>→= <大于>→> <冒号> →: <斜竖> →/ 该语言的保留字:begin end if then else for do while and or not 说明:1 该语言大小写不敏感。 2 字母为a-z A-Z,数字为0-9。 3可以对上述文法进行扩充和改造。 4 ‘/*……*/’为程序的注释部分。 [设计要求] 1、给出各单词符号的类别编码。 2、词法分析程序应能发现输入串中的错误。 3、词法分析作为单独一遍编写,词法分析结果为二元式序列组成的中间文件。 4、设计两个测试用例(尽可能完备),并给出测试结果。 demo.cpp #include #include #include #include "demo.h" char token[20]; int lookup(char *token) { for (int i = 0; i < 11; i++) { if (strcmp(token, KEY_WORDS[i]) == 0) { return i+1; } } return 0; } char getletter(FILE *fp) { return tolower(fgetc(fp)); } void out(FILE *fp, int c, char *value) {

编译原理实验词法分析实验报告

编译技术实验报告 实验题目:词法分析 学院:信息学院 专业:计算机科学与技术学号: 姓名:

一、实验目的 (1)理解词法分析的功能; (2)理解词法分析的实现方法; 二、实验内容 PL0的文法如下 …< >?为非终结符。 …::=? 该符号的左部由右部定义,可读作“定义为”。 …|? 表示…或?,为左部可由多个右部定义。 …{ }? 表示花括号内的语法成分可以重复。在不加上下界时可重复0到任意次 数,有上下界时可重复次数的限制。 …[ ]? 表示方括号内的成分为任选项。 …( )? 表示圆括号内的成分优先。 上述符号为“元符号”,文法用上述符号作为文法符号时需要用引号…?括起。 〈程序〉∷=〈分程序〉. 〈分程序〉∷= [〈变量说明部分〉][〈过程说明部分〉]〈语句〉 〈变量说明部分〉∷=V AR〈标识符〉{,〈标识符〉}:INTEGER; 〈无符号整数〉∷=〈数字〉{〈数字〉} 〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉} 〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉}; 〈过程首部〉∷=PROCEDURE〈标识符〉; 〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉 〈赋值语句〉∷=〈标识符〉∶=〈表达式〉 〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END 〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉 〈表达式〉∷=〈项〉{〈加法运算符〉〈项〉} 〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉} 〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')' 〈加法运算符〉∷=+|- 〈乘法运算符〉∷=* 〈关系运算符〉∷=<>|=|<|<=|>|>= 〈条件语句〉∷=IF〈条件〉THEN〈语句〉 〈字母〉∷=a|b|…|X|Y|Z 〈数字〉∷=0|1|2|…|8|9 实现PL0的词法分析

编译原理 第十章 代码优化

第十章代码优化 某些编译程序在中间代码或目标代码生成之后要对生成的代码进行优化。所谓优化,实质上是对代码进行等价变换,使得变换后的代码运行结果与变换前代码运行结果相同,而运行速度加大或占用存储空间少,或两者都有。优化可在编译的不同阶段进行,对同一阶段,涉及的程序范围也不同,在同一范围内,可进行多种优化。一般,优化工作阶段可在中间代码生成之后和(或)目标代码生成之后进行。中间代码的优化是对中间代码进行等价变换。目标代码的优化是在目标代码生成之后进行的,因为生成的目标代码对应于具体的计算机,因此,这一类优化在很大程度上依赖于具体的机器,我们不做详细讨论。另外依据优化所涉及的程序范围,又可分为局部优化、循环优化和全局优化三个不同的级别。局部优化指的是在只有一个入口、一个出口的基本程序块上进行的优化。循环优化对循环中的代码进行的优化。全局优化是在整个程序范围内进行的优化。 本章重点:局部优化基本块的DAG表示 第一节优化技术简介 为了说明问题,我们来看下面这个例子,源程序是: P :=0 For I :=1 to 20 do P :=P+A[I]*B[I]; 经过编译得到的中间代码如图10-1-1所示,这个程序段由B1和B2两个部分组成,B2是一个循环,假定机器按字节编址。那么,对于这个中间代码段,可进行如下这些优化。 1、删除多余运算(删除公共子表达式)优化的目的在于使目标代码执行速度较快。图10-1-1中间代码(3)和(6)中都有4*I的运算,而从(3)到(6)没有对I赋值,显然,两次计算机的值是相等的。所以,(6)的运算是多余的。我们可以把(6)变换成:T4 :=T1。这种优化称为删除多余运算或称为删除公共子表达式。 2、代码外提减少循环中代码总数的一个重要办法是代码外提。这种变换把循环不变运算,即其结果独立于循环执行次数的表达式,提到循环的前面。使之只在循环外计算一次,上例中,我们可以把(4)和(7)提到循环外。经过删除多余运算和代码外提后,代码变成图10-1-2。

编译原理实验题目及报告要求

编译原理上机实验试题 一、实验目的 通过本实验使学生进一步熟悉和掌握程序设计语言的词法分析程序的设计原理及相关的设计技术, 如何针对确定的有限状态自动机进行编程序;熟悉和 掌握程序设计语言的语法分析程序的设计原理、熟悉 和掌握算符优先分析方法。 二、实验要求 本实验要求:①要求能熟练使用程序设计语言编程;②在上机之前要有详细的设计报告(预习报告); ③要编写出完成相应任务的程序并在计算机上准确 地运行;④实验结束后要写出上机实验报告。 三、实验题目 针对下面文法G(S): S→v = E E→E+E│E-E│E*E│E/E│(E)│v │i 其中,v为标识符,i为整型或实型数。要求完成 ①使用自动机技术实现一个词法分析程序; ②使用算符优先分析方法实现其语法分析程序,在 语法分析过程中同时完成常量表达式的计算。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第一项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理: (1)单词分类:标识符,保留字,常数,运算符,分隔符等等 (2)单词类型编码 (3)自动机 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第二项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理:构造出算法优先关系表 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

编译原理词法分析实验报告

词法分析器实验报告 一、实验目的 选择一种编程语言实现简单的词法分析程序,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 : = + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 各种单词符号对应的种别码: 表各种单词符号对应的种别码 词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根

据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 主程序示意图: 主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,}; 图3-1 (2)程序中需要用到的主要变量为syn,token和sum 扫描子程序的算法思想: 首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn 用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

编译原理实验:目标代码的生成

5. 目标代码生成 本章实验为实验四,是最后一次实验,其任务是在词法分析、语法分析、语义分析和中间代码生成程序的基础上,将C 源代码翻译为MIPS32指令序列(可以包含伪指令),并在SPIM Simulator上运行。当你完成实验四之后,你就拥有了一个自己独立编写、可以实际运行的编译器。 选择MIPS作为目标体系结构是因为它属于RISC范畴,与x86等体系结构相比形式简单便于我们处理。如果你对于MIPS体系结构或汇编语言不熟悉并不要紧,我们会提供详细的参考资料。 需要注意的是,由于本次实验的代码会与之前实验中你已经写好的代码进行对接,因此保持一个良好的代码风格、系统地设计代码结构和各模块之间的接口对于整个实验来讲相当重要。 5.1 实验内容 5.1.1 实验要求 为了完成实验四,我们建议你首先下载并安装SPIM Simulator用于对生成的目标代码进行检查和调试,SPIM Simulator的官方下载地址为:https://www.360docs.net/doc/3a10302207.html,/~larus/spim.html。这是由原Wisconsin-Madison的Jame Larus教授(现在在微软)领导编写的一个功能强大的MIPS32汇编语言的汇编器和模拟器,其最新的图形界面版本QtSPIM由于使用了Qt组件因而可以在各大操作系统平台如Windows、Linux、Mac等上运行,推荐安装。我们会在后面介绍有关SPIM Simulator的使用方法。 你需要做的就是将实验三中得到的中间代码经过与具体体系结构相关的指令选择、寄存器选择以及栈管理之后,转换为MIPS32汇编代码。我们要求你的程序能输出正确的汇编代码。“正确”是指该汇编代码在SPIM Simulator(命令行或Qt版本均可)上运行结果正确。因此,以下几个方面不属于检查范围: 1)寄存器的使用与指派可以不必遵循MIPS32的约定。只要不影响在SPIM Simulator中的 正常运行,你可以随意分配MIPS体系结构中的32个通用寄存器,而不必在意哪些寄存器应该存放参数、哪些存放返回值、哪些由调用者负责保存、哪些由被调用者负责保存,等等。 2)栈的管理(包括栈帧中的内容及存放顺序)也不必遵循MIPS32的约定。你甚至可以使 用栈以外的方式对过程调用间各种数据的传递进行管理,前提是你输出的目标代码(即MIPS32汇编代码)能运行正确。

编译原理词法分析和语法分析报告+代码(C语言版)

信息工程学院实验报告(2010 ~2011 学年度第一学期) 姓名:柳冠天 学号:2081908318 班级:083

词法分析 一、实验目的 设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 2.1 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 := + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 2.2 各种单词符号对应的种别码: 表2.1 各种单词符号对应的种别码 2.3 词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 3.1 主程序示意图:

编译原理模拟题

《编译原理》模拟题(补) 一.单项选择题 1.()是两类程序语言处理程序。 A. 高级语言程序和低级语言程序 B. 解释程序和编译程序 C. 编译程序和操作系统 D. 系统程序和应用程序 2. 编译程序前三个阶段完成的工作是()。 A. 词法分析、语法分析和代码优化 B. 代码生成、代码优化和词法分析 C. 词法分析、语法分析、语义分析和中间代码生成 D. 词法分析、语法分析和代码优化 3. 一个上下文无关文法G包括四个组成部分:一组终结符,一组非终结符,一个开始符号,以及一组()。 A. 字符串 B. 产生式 C. 非开始符号 D. 文法 4. 词法分析器的输出结果是()。 A. 单词的种别编码 B. 单词在符号表中的位置 C. 单词的种别编码和自身值 D. 单词自身值 5. 一个句型中称为句柄的是该句型的最左()。 A. 非终结符号 B. 短语 C. 句子 D. 直接短语 6. 高级语言编译程序常用的语法分析方法中,递归下降分析法属于()分析方法。 A. 自左向右 B. 自顶向下 C. 自底向上 D. 自右向左 7. 在通常的语法分析方法中,()特别适用于表达式的分析。 A. 算符优先分析法 B. LR分析法 C. 递归下降分析法 D. LL(1)分析法 8. 优化可生成_____的目标代码。 A. 运行时间较短 B. 占用存储空间较小 C. 运行时间短但占用内存空间大 D. 运行时间短且占用存储空间小 9.()是两类程序语言处理程序。 A. 系统程序和应用程序 B.编译程序和操作系统 C. 解释程序和编译程序 D.高级语言程序和低级语言程序 10. 经过编译所得到的目标程序是()。 A. 四元式序列 B. 间接三元式序列

编译原理实验 中间代码生成

实验四中间代码生成 一.实验目的: 掌握中间代码的四种形式(逆波兰式、语法树、三元式、四元式)。 二.实验内容: 1、逆波兰式定义:将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表 达式也称做后缀式。 2、抽象(语法)树:运算对象作为叶子结点,运算符作为内部结点。 3、三元式:形式序号:(op,arg1,arg2) 4、四元式:形式(op,arg1,arg2,result) 三、以逆波兰式为例的实验设计思想及算法 (1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。 (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。 (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。 (4)如果不是数字,该字符则是运算符,此时需比较优先关系。 做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。 (5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。 四、程序代码: //这是一个由中缀式生成后缀式的程序 #include<> #include<> #include<> #include<> #define maxbuffer 64 void main() { char display_out(char out_ch[maxbuffer], char ch[32]); //int caculate_array(char out_ch[32]); static int i=0; static int j=0; char ch[maxbuffer],s[maxbuffer],out[maxbuffer]; cout<<"请输入中缀表达式: ";

编译原理 第八章符号表

第八章符号表 编译过程中编译程序需要不断汇集和反复查证出现在源程序中各种名字的属性和特征等有关信息。这些信息通常记录在一张或几张符号表中。符号表的每一项包含两部分,一部分是名字(标识符),另一部分是此名字的有关信息。每个名字的有关信息一般指种属(如简单变量、数组、过程等)、类型(如整、实、布尔等)等等。这些信息将使用于语义检查、产生中间代码以及最终生成目标代码等不同阶段。 编译过程中,每当扫描器识别出一个单词后,编译程序就查阅符号表,看它是否已在其中。如果它是一个新名就将它填进表里。它的有关信息将在词法分析和语法-语义分析过程中陆续填入。 符号表中所登记的信息在编译的不同阶段都要用到。在语义分析中,符号表所登记的内容将用于语义检查(如检查一个名字的使用和原先的说明是否相一致)和产生中间代码。在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。对于一个多遍扫描的编译程序,不同遍所用的符号表也往往各有不同。因为每遍所关心的信息各有差异。 本章重点:符号表的一般组织和使用方法。 第一节符号表的组织和使用 信息栏通常包含许多子栏和标志位,用来记录相应名字的种种不同属性。由于查填符号表一般都是通过匹配名字来实现的,因此,名字栏也称主栏。主栏的内容称为关键字(key word)。 虽然原则上说,使用一张统一的符号表也就够了,但是,许多编译程序按名字的不同种属分别使用许多符号表,如常数表、变量名表、过程名表等等。这是因为,不同种属名字的相应信息往往不同,并且信息栏的长度也各有差异的缘故。因而,按不同种属建立不同的符号表在处理上常常是比较方便的。 对于编译程序的符号表来说,它所涉及的基本操作大致可归纳为五类: 1、对给定名字,确定此名是否在有中; 2、填入新名; 3、对给定名字,访问它的有关信息; 4、对给字名字,填写或更新它的某些信息; 5、删除一个或一组无用的项。 不同种类的表格所涉及的操作往往也是不同的。上述五方面只是一些基本的共同操作。 符号表最简单的组织方式是让各项各栏所占的存储单元的长度都是固定的。这种项栏长度固定的表格易于组织、填写和查找。对于这种表格,每一栏的内容可直接填写在有关的区段里。例如,有些语言规定标识符的长度不得超过8个字符,于是,我们就可以用两个机器字作为主栏(假定每个机器字可容四个字符)每个名字直接填写在主栏中。若标识长度不到8个字符,则用空白符补足。这种直接填写式的表格形式如下: 但是,有许多语言对标识符的长度几乎不加限制,或者说,标识符的长度范围甚宽。譬如说,

编译原理实验(词法分析)

编译原理实验报告 实验一 实验题目:词法分析 指导老师:任姚鹏 专业班级:计算机科学与技术系网络工程方向1002班姓名:xxxx

2013年 4月13日 实验类型__验证性__ 实验室_软件实验室三__ 一、实验项目的目的和任务: 了解和掌握词法分析的方法,编程实现给定源语言程序的词法分析器,并利用该分析器扫描源语言程序的字符串,按照给定的词法规则,识别出单词符号作为输出,发现其中的词法错误。 二、实验内容: 1.设计一个简单的程序设计语言(语言中有若干运算符和分界符;有若干关健字;若干标识符及若干常数) 2.确定编译中使用的表格、词法分析器的输出形式、标识符与关键字的区分方法。 3.把词法分析器设计成一个独立的过程。 三、实验要求: 1.从键盘上输入源程序; 2.处理各单词,计算个单词的值和类型; 3.输出个单词名、单词的值和类型。 四、实验代码 #include #include char file[1024]; int length=0; int index; char keywords[][10]={"auto","short","int","long","float", "double","char","struct","union","enum", "typedef","const","unsigned","signed","extern", "register","static","volatile","void","default", "if","else","switch","case","for", "do","while","goto","continue","break", "sizeof","return"}; char limits[]={'(',')','[',']','{','}',',',';'}; char operators[]={'+', '-', '*', '/', '%', '>','<','&','|','^', '~','!','='}; //13 int IsChar(char ch) //是否是字符 { if ( (ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z')) return 1; return 0;}

编译原理实验 (词法语法分析报告 附源代码

编译原理实验报告 ******************************************************************************* ******************************************************************************* PL0语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而PL0语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。PL/0语言文法的EBNF表示如下: <程序>::=<分程序>. <分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句> <常量说明> ::=CONST<常量定义>{,<常量定义>}; <常量定义> ::=<标识符>=<无符号整数> <无符号整数> ::= <数字>{<数字>} <变量说明> ::=VAR <标识符>{, <标识符>}; <标识符> ::=<字母>{<字母>|<数字>} <过程说明> ::=<过程首部><分程序>{; <过程说明> }; <过程首部> ::=PROCEDURE <标识符>; <语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句> |<复合语句>|<读语句><写语句>|<空> <赋值语句> ::=<标识符>:=<表达式> <复合语句> ::=BEGIN <语句> {;<语句> }END <条件语句> ::= <表达式> <关系运算符> <表达式> |ODD<表达式> <表达式> ::= [+|-]<项>{<加法运算符> <项>} <项> ::= <因子>{<乘法运算符> <因子>} <因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’ <加法运算符> ::= +|- <乘法运算符> ::= *|/ <关系运算符> ::= =|#|<|<=|>|>= <条件语句> ::= IF <条件> THEN <语句> <过程调用语句> ::= CALL 标识符 <当循环语句> ::= WHILE <条件> DO <语句> <读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’ <写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’ <字母> ::= a|b|…|X|Y|Z <数字> ::= 0|1|…|8|9 【预处理】 对于一个pl0文法首先应该进行一定的预处理,提取左公因式,消除左递归(直接或间接),接着就可以根据所得的文法进行编写代码。 【实验一】词法分析 【实验目的】给出PL/0文法规,要求编写PL/0语言的词法分析程序。 【实验容】已给PL/0语言文法,输出单词(关键字、专用符号以及其它标记)。

编译原理练习三

编译原理练习三 一、填空题 1.编译过程中,每当扫描器识别出一个名字后,编译程序就查阅,看该名字是否在其中。如果该名字是一个新名字就将它添进。 2.在语义分析阶段,符号表所登记的信息将用于和;在目标代码生成阶段,符号表是的依据。 3.过程信息表中必须包括、和。 4.编译程序使用区别标识符的作用域。 5.编译程序在其工作过程中使用最多的数据结构是。它记录着源程序中的各种信息,以便查询和修改。在这些中,尤以最为重要,它的生存期最长,使用也最频繁。 6.过程与过程引用中信息交换的方法是和。 7.PASCAL语言中局部变量的作用域为。 8.将过程的每次执行和过程的相对应就解决了过程递归调用所引起的问题。 9.形式参数和实在参数之间的对应关系通常按来确定。 10.对于某个压缩了的上下文无关文法,当把每个文法符号联系于一组属性,且让该文法的规则附加以时,称该文法为属性文法。 11.文法符号的属性有两种,一种称为,另一种称为。 12.一个文法符号的继承属性是通过语法树中它的结点的相应文法符号的属性来计算的,而综合属性是通过语法树中它的结点的属性之值来计算的。 13.语法制导的编译程序能同时进行分析和分析。 14.在PASCAL中,由于允许用户动态申请与释放内存空间,所以必须采用存储分配技术。 15.静态区的分配对象是。静态区分配的特点是。

二、选择题(单项和多项) 1.在编译过程中,符号表的主要作用是。 a.帮助错误处理 b.辅助语法错误的检查 c.辅助语义的(即上下文有关的)正确性检查 d.辅助代码生成 e.辅助对目标代码的优化 2.PASCAL中过程说明的局部量地址分配在。 a.调用者的数据区中 b.被调用者的数据区中 c.主程序的数据区中 d.公共数据区中 3.与PASCAL语言存储分配方式相似的语言是。 a.C语言 b.BASIC语言 c.FORTRAN-77 4.运行阶段的存储组织与管理的目的是。 a.提高编译程序的运行速度 b.提高目标程序的运行速度 c.为运行阶段的存储分配作准备 5.动态存储分配时,可以采用的分配方法有:。 a.以过程为单位的栈式动态存储分配 b.堆存储分配 c.最佳分配方法 6.过程调用时,参数的传递方法通常有。 a.传值 b.传地址 c.传结果 d.传名 7.过程调用的参数传递中,将出现的任一形蚕都代之以相应的实参的为,过程体对形参的任何引用或赋值都被处理成对形式单元的间接访问的为,像使用局部变量一样使用形式单元的为。 a.传值 b. 传名 c.传地址 d.传结果 8.FORTRAN编译中存储分配是。 a.静态存储分配 b. 动态存储分配 9.在编译方法中,动态存储分配的含义是什么? a.在运行阶段对源程序中的量进行分配 b.在编译阶段对源程序中的量进行分配 c.在编译阶段对源程序中的量进行分配,在运行时这些量的地址可以根据需要 改变 d.以上都不正确

编译原理词法分析程序实现实验报告

编译原理词法分析程序实现实验报告实验一词法分析程序实现 一、实验内容 选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。输入:由无符号数和+,,,*,/, ( , ) 构成的算术表达式,如 1.5E+2,100。输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。二、设计部分 因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下: 输入字符p指向第一个字符 符号识别*p=+||-||*||/ YYNN*p=0~9*p=E*p=0~9||"." N无效符号Y *p=“.”GOTO 2 GOTO 1 GOTO 1: NY无符号数GOTO 1*p=0~9*p='/0' YN P++NNP++*p=E*p='+'||'-' YY P++P++continue

YY *p=0~9*p=0~9 NN 无符号数无符号数 P++P++ continuecontinue GOTO 2: GOTO 2 *p=Econtinue Y 无符号数 P++ continue 三、源程序代码部分 #include #include #include #define MAX 100 #define UNSIGNEDNUMBER 1 #define PLUS 2 #define SUBTRACT 3 #define MULTIPLY 4 #define DIVIDE 5 #define LEFTBRACKET 6 #define RIGHTBRACKET 7 #define INEFFICACIOUSLABEL 8 #define FINISH 111

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

编译原理试题及答案3

编译原理复习题 一、填空题: 1、编译方式与解释方式的根本区别在于(是否生成目标代码)。 2、对编译程序而言,输入数据是(源程序),输出结果是(目标程序)。 3、如果编译程序生成的目标程序是机器代码程序,则源程序的执行分为两大阶段:(编译阶段)和(运行阶段)。 4、如果编译程序生成的目标程序是汇编语言程序,则源程序的执行分成三个阶段:(编译阶段)、(汇编阶段)和(运行阶段)。 5、自顶向下语法分析方法会遇到的主要问题有(回溯)和((左递归带来的)无限循环)。 6、LL(k)分析法中,第一个L的含义是(从左到右进行分析),第二个L的含义是(每次进行最左推导),“k”的含义是(向输入串中查看K个输入符号)。 7、LL(1)分析法中,第一个L的含义是(从左到右进行分析),第二个L的含义是(每次进行最左推导),“1”的含义是(向输入串中查看1个输入符号)。 8、自顶向下语法分析方法的基本思想是:从(识别符号)出发,不断建立(直接推导),试图构造一个推导序列,最终由它推导出与输入符号相同的(符号串)。 9、自底向上语法分析方法的基本思想是:从待输入的符号串开始,利用文法的规则步步向上进行(直接归约),试图(归约)到文法的(识别符号|开始符号)。 10、LR(0)分析法的名字中,“L”的含义是(从左到右进行分析),“R”的含义是(采用最右推导的逆过程---最左归约),“0”的含义是(向貌似句柄的符号串后查看0个输入符号)。 11、LR(1)分析法的名字中,“L”的含义是(从左到右进行分析),“R”的含义是(采用最右推导的逆过程---最左归约),“1”的含义是(向貌似句柄的符号串后查看1个输入符号)。 12、SLR(1)分析法的名字中,“S”的含义是(简单的),“L”的含义是(从左到右进行分析),“R”的含义是(采用最右推导的逆过程---最左归约),“1”的含义是(向貌似句柄的符号串后查看1个输入符号)。 13、在编译过程中,常见的中间语言形式有(逆波兰表示)、(三元式)、(四元式)和(树形表示)。 14、在编译程序中安排中间代码生成的目的是(便于代码优化)和(便于目标程序的移植)。 15、表达式-a+b*(-c+d)的逆波兰表示为(a-bc-d+*+ )。 16、表达式a+b*(c+d/e)的逆波兰表示为(abcde/+*+ )。 17、表达式a:=a+b*c↑(d/e)/f的逆波兰表示为(aabcde/↑*f/+:= )。 18、文法符号的属性有(继承属性)和(综合属性)两种。 19、一个文法符号的继承属性是通过语法树中它的(兄弟结点与父)结点的相应文法符号的属性来计算的。 20、一个文法符号的综合属性是通过语法树中它的(子)结点的属性来计算的。

相关文档
最新文档