编译原理实验报告
- 格式:docx
- 大小:315.00 KB
- 文档页数:24
实验1简单的词法分析子程序【实验目的】●理解词法分析在编译程序中的作用●初步了解和掌握词法分析程序的实现方法和技术【实验内容】1. 编写程序,输入一串字符,判断该字符串是否为合法标识符或合法整型常量。
2. 无符号数的算术四则运算中的各类单词的识别。
输入:由无符号数、+、-、*、/、(、)构成的算术表达式。
输出:对识别出的每一单词均单行输出。
如,输入:8*2.5-1.0e2则,输出:8*2.5-1.0e2描述无符号数的确定的、最小化的状态转换图如图1所示。
其中编号1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
图1 文法G[<无符号数>]的状态转换图实验2词法分析程序设计【实验目的】●理解词法分析中的正规式和自动机●掌握词法分析程序的实现方法和技术【实验内容】某一高级程序设计语言的部分语言子集定义如下:(1)关键字:for if then else while do(所有关键字都是小写)(2)运算符和分隔符:+ - * / : = <><= <>>= == ; ( ) #(3)其他标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter|digit)*NUM=digit·digit*(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM、运算符、分隔符和关键字,词法分析阶段通常被忽略。
各种词法单元对应的词法记号如下:编写程序,实现词法分析功能。
输入:源程序输出:二元组(词法记号,属性值/其在符号表中的位置)构成的序列。
例如:输入源程序x=5;if (x>0)thenx=2*x+1/3;elsex=2/x;#(# 表示输入结束)经词法分析后输出如下序列:(10,x)(18,=)(11,5)(26,;)(2,if)(27,()…说明:关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符,查关键字表。
编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
编译原理实验编译原理实验。
编译原理是计算机科学中的一个重要领域,它研究的是编译器的设计和实现原理。
编译器是将高级语言代码转换成机器语言代码的程序,它在软件开发过程中起着至关重要的作用。
而编译原理实验则是帮助学生深入理解编译原理的重要手段之一,通过实际操作来加深对编译原理知识的理解和掌握。
在编译原理实验中,我们需要掌握以下几个关键点:1. 词法分析,词法分析是编译过程中的第一步,它负责将源代码分割成一个个的单词(Token)。
在词法分析实验中,我们需要实现一个词法分析器,能够正确地识别出源代码中的各种单词,并进行分类和标记。
2. 语法分析,语法分析是编译过程中的第二步,它负责将词法分析得到的单词序列转换成抽象语法树。
在语法分析实验中,我们需要实现一个语法分析器,能够根据给定的文法规则,将单词序列转换成抽象语法树,并进行语法检查。
3. 语义分析,语义分析是编译过程中的第三步,它负责对抽象语法树进行语义检查和翻译。
在语义分析实验中,我们需要实现一个语义分析器,能够对抽象语法树进行类型检查、作用域分析等,并生成中间代码。
4. 代码生成,代码生成是编译过程中的最后一步,它负责将中间代码转换成目标机器代码。
在代码生成实验中,我们需要实现一个代码生成器,能够将中间代码转换成目标机器代码,并进行优化。
通过以上实验,我们可以深入理解编译原理的各个环节,并掌握编译器的设计和实现原理。
同时,实验过程中还能培养我们的动手能力和解决问题的能力,为今后的软件开发打下坚实的基础。
总之,编译原理实验是非常重要的,它能够帮助我们深入理解编译原理知识,提高我们的动手能力和解决问题的能力。
希望大家能够认真对待编译原理实验,从中获得更多的收获和成长。
【编译原理】词法分析(CC++源代码+实验报告)⽂章⽬录1 实验⽬的和内容1.1实验⽬的(1)根据 PL/0 语⾔的⽂法规范,编写PL/0语⾔的词法分析程序;或者调研词法分析程序的⾃动⽣成⼯具LEX或FLEX,设计并实现⼀个能够输出单词序列的词法分析器。
(2)通过设计调试词法分析程序,实现从源程序中分离出各种类型的单词;加深对课堂教学的理解;提⾼词法分析⽅法的实践能⼒。
(3)掌握从源程序⽂件中读取有效字符的⽅法和产⽣源程序的内部表⽰⽂件的⽅法。
(4)掌握词法分析的实现⽅法。
(5)上机调试编出的词法分析程序。
1.2实验内容根据PL/0语⾔的⽂法规范,编写PL/0语⾔的词法分析程序。
要求:(1)把词法分析器设计成⼀个独⽴⼀遍的过程。
(2)词法分析器的输出形式采⽤⼆元式序列,即:(单词种类, 单词的值)2 设计思想2.1单词种类及其正规式(1)基本字单词的值单词类型正规式rbegin beginsym begincall callsym callconst constsym constdo dosym doend endsym endif ifsym ifodd oddsym oddprocedure proceduresym procedureread readsym readthen thensym thenvar varsym varwhile whilesym whilewrite writesym write(2)标识符单词的值单词类型正规式r标识符ident(字母)(字母|数字)*(3)常数单词的值单词类型正规式r常数number(数字)(数字)*(4)运算符单词的值单词类型正规式r+plus+-minus-*times*/slash/=eql=<>neq<><lss<<=leq<=>gtr>>=geq>=:=becomes:=(5)界符单词的值单词类型正规式r(lparen()rparen),comma,;semicolon;.period.2.2 根据正规式构造NFA下⾯我们根据上述的正规式来构造该⽂法的NFA,如下图所⽰,其中状态0为初态,凡带双圈的状态均为终态,状态24是识别不出单词符号的出错情形,其他状态的识别情况如下图中右边的注释所⽰。
编译原理实验报告一、实验概述本次实验旨在设计并实现一个简单的词法分析器,即实现编译器的第一个阶段,词法分析。
词法分析器将一段源程序代码作为输入,将其划分为一个个的词法单元,并将其作为输出。
二、实验过程1.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。
2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。
词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。
3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。
测试用例应包含各种情况下的源程序代码。
4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。
重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。
三、实验结果我们设计了一个简单的词法分析器,并进行了测试。
测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。
经过测试,词法分析器能够正确处理所有的测试用例。
词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。
通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。
四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。
词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。
在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。
通过测试和修正,我掌握了调试和错误修复的技巧。
本次实验的经验对我今后的编程工作有很大帮助。
编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。
我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。
编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
编译原理实习报告一、实习目的和意义编译原理是计算机科学的核心分支之一,涉及到将一种编程语言转换成另一种编程语言的过程。
通过本次实习,我希望能够深入理解编译原理的基本概念、方法和实现技术,提高自己的编程能力和软件设计能力。
二、实习内容和步骤1. 阅读实习指导书和相关的理论知识,了解编译程序的基本思想和构造方法。
2. 选择一个自己熟悉的程序设计语言,例如C语言,作为编译对象。
3. 设计并实现一个C语言子集的编译程序,包括词法分析、语法分析和语义分析等功能。
4. 对编译程序进行测试和调试,修复可能存在的问题和错误。
5. 撰写实习报告,总结实习过程中的经验和教训。
三、实习过程和成果在实习过程中,我首先阅读了相关的理论知识和实习指导书,对编译原理的基本概念和实现方法有了更深入的理解。
然后,我选择了C语言作为编译对象,并设计了一个C语言子集的编译程序。
在实现编译程序的过程中,我首先编写了词法分析器,用于识别源代码中的单词和符号。
然后,我编写了语法分析器,用于分析源代码的语法结构。
最后,我编写了语义分析器,用于检查源代码中的语义错误。
在完成编译程序的实现后,我对程序进行了测试和调试,发现并修复了一些可能的问题和错误。
通过测试,我发现我的编译程序能够正确地编译和生成目标代码。
最后,我撰写了实习报告,总结了实习过程中的经验和教训。
我意识到编译原理不仅是理论知识的掌握,还需要通过实践来加深理解和提高能力。
同时,我也学会了如何设计和实现一个简单的编译程序,提高了自己的编程能力和软件设计能力。
四、实习收获和展望通过本次实习,我对编译原理的基本概念和实现方法有了更深入的理解,提高了自己的编程能力和软件设计能力。
我学会了如何设计和实现一个简单的编译程序,并能够将其应用于实际的编程实践中。
在未来的学习和工作中,我将继续深入学习和研究编译原理相关的知识和技术,提高自己的专业水平和竞争力。
同时,我也希望能够将编译原理的应用扩展到更多的编程语言和领域中,为自己的职业发展打下更坚实的基础。
一、实习背景与目的随着计算机技术的飞速发展,编译原理作为计算机科学的重要基础理论之一,其研究与应用越来越受到重视。
为了更好地理解和掌握编译原理的基本原理和方法,提高自己的编程能力和设计能力,我参加了编译原理的实习课程。
本次实习旨在通过设计和实现一个简单的编译程序,加深对编译原理的理解,掌握编译程序的设计与实现方法,提高自己的编程能力,并培养自己的计算思维。
二、实习内容本次实习主要分为以下几个部分:1. 词法分析:识别源程序中的单词,将其转换为对应的词法单元。
2. 语法分析:根据文法规则,分析源程序的语法结构,生成抽象语法树(AST)。
3. 语义分析:检查AST的语义正确性,进行类型检查等。
4. 中间代码生成:将AST转换为中间代码。
5. 代码优化:对中间代码进行优化,提高程序性能。
6. 目标代码生成:将优化后的中间代码转换为特定平台的目标代码。
三、实习过程1. 词法分析:- 首先,分析源程序的文法规则,确定需要识别的单词种类和对应的正则表达式。
- 然后,设计状态转换图,实现词法分析器。
- 最后,编写测试用例,验证词法分析器的正确性。
2. 语法分析:- 分析文法规则,确定语法结构,设计抽象语法树(AST)。
- 选择合适的语法分析方法,如递归下降分析、LL分析、LR分析等。
- 实现语法分析器,将词法分析器生成的词法单元转换为AST。
3. 语义分析:- 根据AST,检查语义正确性,如类型检查、作用域分析等。
- 实现语义分析器,处理语义错误,并给出错误信息。
4. 中间代码生成:- 根据AST,生成中间代码,如三地址代码、四元式等。
- 实现中间代码生成器,将AST转换为中间代码。
5. 代码优化:- 分析中间代码,找出可优化的部分。
- 实现代码优化器,优化中间代码,提高程序性能。
6. 目标代码生成:- 根据目标平台的指令集,生成目标代码。
- 实现目标代码生成器,将优化后的中间代码转换为目标代码。
四、实习成果通过本次实习,我成功地设计和实现了一个简单的编译程序,实现了词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等功能。
实验报告第 1 页专业____软件工程________ 班级____2_____ 姓名_71李飞强77欧艺欣81吴文浩89张泰鑫__ 组别:第四组实验日期:2014年 3 月26 日报告退发(订正、重做)课程编译原理实验名称递归下降的预测分析一、实验目的1. 学会用语法图来形式化地描述一门简单的语言;2. 掌握递归下降的预测分析;3. 掌握词法分析。
二、实验环境Visual Studio 或 GCC 或Eclipse三、实验内容、步骤和结果分析实验内容:请基于递归下降的分析方法(教材P55页),编写一个“语法图.doc”所对应语言的语法分析器。
该语法分析器能读入一个源代码文件(如“test.c”文件所示),并判断其中的源代码是否符合“语法图.doc”的规定。
如果符合,打印出Yes;如果不符合,打印出No。
(所用编程语言不限)C语言版:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MaxIdLen 20 //标志符的最大长度#define KeyWordsCount 5 //该语言拥有的关键字个数#define BoolValueCount 2 //bool类型可能取值的个数#define SymTypeCount 17 //symType个数enum SymType//枚举{OR , //或AND, //与LP, //左括号RP, //右括号ID, //标志符ASSIGN, //赋值LB, //左大括号RB, //右大括号COMMA, //逗号SEMICOLON, //分号UNDEFINED, //未定义BOOLVALUE, //bool类型的值IF, //ifELSE, //elseWHILE, //whilePRINTF, //printfBOOL, //bool};enum boolValue{TRUE,FALSE,};//关键字static char * keywords[KeyWordsCount] = { "if","else","while","printf","bool",};//关键字对应类别static int keyType[KeyWordsCount] = { IF,ELSE,WHILE,PRINTF,BOOL,};static char * boolvalue[BoolValueCount]={"true","false",};static int boolValueType[BoolValueCount]={TRUE,FALSE,};char ch=' '; //当前字符char id[MaxIdLen+1]; //当前符号串int token; //当前记号(的类型)int value; //当前记号的值FILE * fp; //用来打开要识别的源代码文件int lineNum=1; //要识别的代码行数bool isPass = false ; //判断识别的代码是否全部合法void getToken();void program();void program();void statement();void definition();void term();void factor();void expression();void match(int t);void main(){fopen_s(&fp,"D:\\test.c","r");getToken();program();if(isPass)printf("Y\n");else printf("N\n");fclose(fp);}/****************************************lexical*****************************************/int getKeyWord(char * str){for(int i=0;i<KeyWordsCount;i++)if(strcmp(str,keywords[i])==0)return keyType[i];return UNDEFINED;}int getBoolValue(char* str){for(int i=0;i<BoolValueCount;i++)if(strcmp(str,boolvalue[i])==0){value = boolValueType[i];return BOOLVALUE;}return UNDEFINED;}bool isLetter(char ch){return (ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'); }bool isDigit(char ch){return ch>='0'&&ch<='9';}void nextChar(){ch = fgetc(fp);}void getToken(){while(ch==' '||ch=='\t'||ch=='\r'||ch=='\n'){if(ch == '\n')lineNum++;nextChar();}if(isLetter(ch)){int index=0;id[index++] = ch;nextChar();while(isLetter(ch) || isDigit(ch)){if(index<MaxIdLen){id[index++] = ch;nextChar();}else{//cout<<"identifier is too long."<<endl;//exit(1);}}id[index]='\0';token = getKeyWord(id);if(token == UNDEFINED)token = getBoolValue(id);if(token == UNDEFINED){token = ID;}}else if(ch == '='){token = ASSIGN;nextChar();}else if(ch=='|'){nextChar();if(ch=='|'){token=OR;nextChar();}elseexit(1);}else if(ch=='&'){nextChar();if(ch=='&'){token=AND;nextChar();}elseexit(1);}else if(ch == ';'){token = SEMICOLON;nextChar();}else if(ch == '('){token = LP;nextChar();}else if(ch == ')'){token = RP;nextChar();}else if(ch == ','){token = COMMA;nextChar();}else if(ch == '{'){token = LB;nextChar();}else if(ch == '}'){token = RB;nextChar();}else if(ch == EOF){printf(" EOF!\n");isPass = true;}else{printf("第%d行不能识别的符号!\n",lineNum );exit(1);}}/****************************************grammar*****************************************/void match(int t){if(t == token){getToken();}else{printf("大概在第%d行错误\n",lineNum);exit(1);}}void expression(){term();while(token == OR){match(OR);term();}}void factor(){if(token == BOOLVALUE && value == TRUE)match(BOOLVALUE);else if(token == BOOLVALUE && value == FALSE) match(BOOLVALUE);else if(token == LP){match(LP);expression();match(RP);}else if(token == ID)match(ID);}void term(){factor();while(token == AND){match(AND);factor();}}void definition(){do{match(BOOL);match(ID);match(ASSIGN);expression();match(SEMICOLON);}while(token == BOOL);}void statement(){if(token == IF){match(IF);match(LP);expression();match(RP);statement();if(token == ELSE){match(ELSE);statement();}}else if(token == PRINTF){match(PRINTF);match(LP);expression();while(token == COMMA){match(COMMA);expression();}match(RP);match(SEMICOLON);}else if(token == WHILE){match(WHILE);match(LP);expression();match(RP);statement();}else if(token == LB){match(LB);do{statement();}while(token != RB);match(RB);}else if(token == ID){match(ID);match(ASSIGN);expression();match(SEMICOLON);}else if(token == SEMICOLON){match(SEMICOLON);}}void program(){definition();statement();}Java版:(吴文浩)Java版的关键代码:// 由语法分析带动翻译public void parse(String src) {this.lexer = new GrammarLexer(src);lookahead = lexer.getToken();program();}private void match(TokenType type) {// 如果记号lookahead的类型是type,则取下一个记号System.out.println("------------>" + type);if (lookahead.tokenType.equals(type)) {lookahead = lexer.getToken();} else {error("NO");// 否则报错}}private void error(String str) {// out.println(str);System.out.println(str);System.exit(-1);}/*** program:程序 definition----->statement-------->*/public void program() {definition();//定义statement();// 声明}// definition:定义/*** bool-->id-->=-->expression-->;*/public void definition() {do {match(TokenType.BOOLEAN);match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);// 匹配分号} while (lookahead.isBoolean());}// statement:声明public void statement() {if(lookahead.isIf()) {// -->if-->(-->expression-->)-->statement--->match(TokenType.IF);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();if(lookahead.isElse()) {//缺陷:如果用全部代码测试时,程序走到这里停止了,while循环后的语句将不能执行!match(TokenType.ELSE);statement();} else {}} else if (lookahead.isWhile()) {match(TokenType.WHILE);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();} else if (lookahead.isPrint()) {match(TokenType.PRINT);match(TokenType.LeftP);expression();while (lookahead.isComma()) {match(MA);expression();}match(TokenType.RightP);match(TokenType.SEMICOLON);} else if (lookahead.isSemicolon()) {// ;match(TokenType.SEMICOLON);} else if (lookahead.isLeftBrace()) {match(TokenType.LeftBrace);statement();while(!lookahead.isRightBrace() || lookahead.isId() ){//必须加入lookahead.isId()否则a = false;运行不出来(语法图缺陷吧!)statement();}match(TokenType.RightBrace);} else if (lookahead.isId()) {// id = expression;// System.out.println("++++++++++++++++++++");match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);} else {}}/***expression:式子-------->term()----(---->||------->term()---->);*/private void expression() {term();while (lookahead.isOr()) {// 如果是||就继续循环处理match(TokenType.OR);term();}}/***term:项 Factor(); While(match(‘&&’)){ Factor(); }*/private void term() {factor();while (lookahead.isAnd()) {// 判断是&&就继续进行match(TokenType.AND);factor();}}/*** --->(------>expression--------->)--------->* ---->true---->* ---->false---->* ---->id------>*/private void factor() {if (lookahead.isTrue()) {match(TokenType.TRUE);} else if (lookahead.isLeftP()) {match(TokenType.LeftP);expression();match(TokenType.RightP);} else if (lookahead.isFalse()) {match(TokenType.FALSE);} else if (lookahead.isId()) {match(TokenType.ID);} else{}}/*** 获取下一个Token*/public Token getToken() {int value = 0;char cur;while (true) {if (index >= src.length())return Token.EOF;else {// 取下一字符cur = next();// 如果下一个字符是空白,继续读取字符if (this.isBlank(cur))continue;else if (this.isAlpha(cur)) {// 字符缓冲区StringBuilder buffer = new StringBuilder();buffer.append(cur);while (isAlpha((char) peek())) {buffer.append(next());}if(buffer.toString().equals(KeyWord.BOOLEAN)) {return new Token(TokenType.BOOLEAN, buffer.toString());} else if (buffer.toString().equals(KeyWord.FALSE)) {return new Token(TokenType.FALSE, buffer.toString());} else if (buffer.toString().equals(KeyWord.TRUE)) {return new Token(TokenType.TRUE, buffer.toString());} else if(buffer.toString().equals(KeyWord.IF)) {return new Token(TokenType.IF, buffer.toString());} else if (buffer.toString().equals(KeyWord.WHILE)) {return new Token(TokenType.WHILE, buffer.toString());} else if (buffer.toString().equals(KeyWord.PRINT)) {return new Token(TokenType.PRINT, buffer.toString());} else {return new Token(TokenType.ID, buffer.toString());}} else if (cur == ',') {return MA;} else if (cur == '(') {return Token.LeftP;} else if (cur == ')') {return Token.RightP;} else if (cur == '|' && next() == '|') {return Token.OR;// 或者} else if (cur == '&' && next() == '&') {return Token.AND;// 且} else if (cur == '=') {return Token.EQUAL;} else if (cur == ';') {return Token.SEMICOLON;// 分号} else if (cur == '{') {// 左大括号return Token.LeftBrace;} else if (cur == '}') {return Token.RightBrace;} else if (cur == '\n') {line++;} else {this.error();}}}}运行这个测试代码的截图:String src = "boolean a = true;boolean b = false;boolean c = (a && b);if( a || b) print(a,b);else print(c);";运行这个测试代码的截图:String src = "boolean a = true; while(a && (b||c)){print(a,b,c);a = false;}";四、讨论(说明实验过程中遇到的问题及解决办法;未解决/需进一步研讨的问题或建议新实验方法等)在text.c中先是声明bool类型,然后是if语句,最后是while语句。
编译技术实验报告实验题目:词法分析学院:信息学院专业:计算机科学与技术学号:姓名:一、实验目的(1)理解词法分析的功能;(2)理解词法分析的实现方法;二、实验内容PL0的文法如下‘< >’为非终结符。
‘::=’ 该符号的左部由右部定义,可读作“定义为”。
‘|’ 表示‘或’,为左部可由多个右部定义。
‘{ }’ 表示花括号内的语法成分可以重复。
在不加上下界时可重复0到任意次数,有上下界时可重复次数的限制。
‘[ ]’ 表示方括号内的成分为任选项。
‘( )’ 表示圆括号内的成分优先。
上述符号为“元符号”,文法用上述符号作为文法符号时需要用引号‘’括起。
〈程序〉∷=〈分程序〉.〈分程序〉∷= [〈变量说明部分〉][〈过程说明部分〉]〈语句〉〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉}:INTEGER;〈无符号整数〉∷=〈数字〉{〈数字〉}〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};〈过程首部〉∷=PROCEDURE〈标识符〉;〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉〈赋值语句〉∷=〈标识符〉∶=〈表达式〉〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉〈表达式〉∷=〈项〉{〈加法运算符〉〈项〉}〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'〈加法运算符〉∷=+|-〈乘法运算符〉∷=*〈关系运算符〉∷=<>|=|<|<=|>|>=〈条件语句〉∷=IF〈条件〉THEN〈语句〉〈字母〉∷=a|b|…|X|Y|Z〈数字〉∷=0|1|2|…|8|9实现PL0的词法分析三、实验分析与设计PL0词法分析程序是一个独立的过程,其功能是为语法语义分析提供单词,把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析。
实验一词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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 各种单词符号对应的种别码单词符号种别码单词符号种别码bgin 1 :17If 2 := 18Then 3 < 20wile 4 <> 21do 5 <= 22end 6 > 23lettet(letter|digit)* 10 >= 24 dight dight* 11 = 25 + 13 ;26—14 ( 27* 15 ) 28/ 16 # 02.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 主程序示意图:主程序示意图如图3-1所示。
编译原理上机实验报告一、实验目的本次实验旨在通过实践的方式理解和掌握编译原理中的一些重要概念和技术,包括词法分析、语法分析和语义分析等。
通过实验的操作,了解和体验编译器的工作过程,深入理解编译原理的相关理论知识。
二、实验环境本次实验使用了Java语言作为编程语言,使用Eclipse作为开发环境,实验所需的相关工具和库已经提前配置完成。
三、实验内容本次实验主要分为三个部分,分别是词法分析、语法分析和语义分析。
1.词法分析词法分析是编译器的第一个阶段,也是最基础的阶段。
在本次实验中,我们首先需要实现一个词法分析器,该分析器可以将源代码分割成一个个的词法单元,将其存储到一个词法单元表中。
我们首先需要定义一些词法单元的模式,比如关键字、标识符、常量等。
然后,我们使用正则表达式和有限自动机的思想来实现一个可以识别各种模式的词法分析器。
2.语法分析语法分析是编译器的第二个阶段,其目的是将词法单元表中的内容按照语法规则进行分析,生成一个语法树。
在本次实验中,我们需要实现一个递归下降的语法分析器。
我们首先需要定义一些语法规则,然后根据这些规则逐条实现相应的语法分析函数。
最终,我们可以通过递归调用这些函数,将源代码转换成语法树的形式。
3.语义分析语义分析是编译器的第三个阶段,其目的是对语法树进行进一步的检查和处理。
在本次实验中,我们需要实现一个简单的语义分析器。
我们可以在语法分析的基础上,增加一些语义规则,然后对生成的语法树进行检查。
比如,我们可以检查变量的定义和使用是否一致,是否存在未定义的变量等。
最终,我们可以通过语义分析器发现和纠正一些潜在的错误。
四、实验总结通过本次实验,我深入学习了编译原理的相关知识,并通过实践中加深了对这些知识的理解和掌握。
实验中,我了解到了词法分析、语法分析和语义分析在编译器设计中的重要性,也学会了如何使用相关工具和技术来实现这些功能。
通过实验,我发现编译原理是一门非常有趣且实用的课程,它既涉及到理论知识,又需要实践操作。
实验一1、程序设计思路在预处理处理程序的基础上,扩充程序,增加行注释。
首先,行注释以“\”开始,以回车“\n”结束。
参照星注释的源代码。
其次,要区分行注释与星注释,即星注释(指的是/* */ )注释中包含行注释,行注释无效;行注释后有星注释,星注释无效。
所以设计一个标记变量p,标记行注释。
2、实现过程输入的当前字符cur_c 等于''\"且old_c等于"\",如果满足这样的条件,就将in_comment改为ture,进入行注释。
并且标记p=1。
继续运行,当输入字符cur_c="\n"且p=1,表示行注释离开,将in_comment改为false。
3、源程序关键代码加粗的为自己修改的代码。
#include <fstream.h>#include <iostream.h>void pro_process(char *);void main( ) //测试驱动程序{//定义扫描缓冲区char buf[4048]={'\0'}; //缓冲区清0//调用预处理程序pro_process(buf);//在屏幕上显示扫描缓冲区的内容cout<<buf<<endl;}void pro_process(char *buf) //预处理程序{ ifstream cinf("source.txt",ios::in);int i=0,p=0; //计数器char old_c='\0',cur_c; //前一个字符,当前字符。
bool in_comment=false; //false表示当前字符未处于注释中。
while(cinf.read(&cur_c,sizeof(char))){ //从文件读一个字符switch(in_comment){case false:if(old_c=='/' && cur_c=='*'){ //进入多行注释i--; //去除已存入扫描缓冲区的字符'/'in_comment=true;}else{if(old_c=='/' && cur_c=='/'){ //进入行注释i--;p=1; //去除已存入扫描缓冲区的字符'/'in_comment=true;}else {if(old_c=='\\' && cur_c=='\n') //发现续行i--; //去除已存入扫描缓冲区的字符'\'else {if(cur_c>='A' && cur_c<='Z')//大写变小写cur_c+=32;if(cur_c =='\t' || cur_c =='\n') //空格取代TAB换行cur_c=' ';buf[i++]=cur_c ;}}}break;case true:if((old_c=='*' && cur_c=='/')) //离开注释in_comment=false;if(cur_c=='\n'&&p==1) in_comment=false;}//end of switchold_c= cur_c; //保留前一个字符}//end of whilebuf[i++]='#'; //在源程序尾部添加字符'#' }4、结果的输入与输出Source.txtBegin/*S=2*3.14*R*R+2*3.14*R*H*/Real R,h,s;s=2*3\14*r*(r+++h) kmoiulEnd运行结果如下:实验二1、程序设计思路:编写一个自动机(DFA)识别程序,判断一个字符序列是否为一个DFA所识别。
实验一词法分析一、实验目的通过设计、编写和调试词法分析程序,了解词法分析程序的作用,组成结构,不同种类单词的识别方法,掌握由单词的词法规则出发,画出识别单词的状态转换图,然后在用程序实现词法分析程序设计方法。
二、词法规则1、注释用{和}括起来。
注释体中不能有{。
注释可以出现在任何记号的后面。
2、记号间的空格可有可无,但关键字前后必须有空格、换行、程序的开头或者结尾的原点。
3、标识符的记号id 与以字母开头的字母数字串相匹配:Letter->[a-zA-Z]Digit->[0-9]Id->letter (letter | digit)*4、记号num与无符号整数相匹配:Digits->digit digit*Optional_fraction -> . Digits | ɛOptional_exponent->(E(+ | - | ɛ ) digits) | ɛNum ->digits optional_fraction optional_exponent5、关键字要被保留且在文法中以黑体出现6、关系运算符(relop)指:=、<、<>、<=、>=、>7、Addop: + 、 - 、or8、Mulop:*、/ 、div、mod、and9、Assignop: :=三、词法分析程序详细设计及判别状态图1、无符号数(可带小数和指数)的状态转换图:2、标识符/关键字的状态转换图:字母或数程序详细设计:四、开发环境本程序在Microsoft Visual C++ 6.0环境中编写,无特殊编译要求。
五、函数清单void LexcialAnalysis(FILE *fp);//词法分析主函数int JudgeFirstLetter(char ch);//判断单词的第一个字符int IsDigit(char ch);//判断是否为数字int IsLetter(char ch);//判断是否为字母int IsSpecialPunc(char ch);//判断是否为特殊标点void RecogDigit(char StrLine[]);//用状态图识别无符号数字void RecogIdentifier(char strLine[]);//用状态图识别标识符void RecogPunc(char strLine[]);//识别特殊标点int IsKeyWord(string str);//判断标识符是否为关键字void error();//出错处理六、测试程序program example(input, output);{comments goes here!}var x, y: integer;function gcd(a, b: integer): integer;beginif b =1.2e3 then gcd := aelse gcd := gcd(b, a mod b)end;beginread(x, y);write(gcd(x, y));end.七、运行效果八、实验总结通过这次编译器词法分析程序的编写,我更好地了解了词法分析的作用及工作原理,讲课本中的知识融入到程序编写过程中,理论结合了实际。
课程实验报告课程名称:《编译原理》专业班级:计算机科学与技术11级10班学号:XXXXXXX姓名:X X指导教师:**报告日期:2014年6月16日计算机科学与技术学院目录目录 (2)1 实验一词法分析 (3)1.1实验目的 (3)1.2实验要求 (3)1.3算法思想 (4)1.4实验程序设计说明 (5)1.5词法分析实现 (6)1.6词法实验结果及结果分析 (12)2 实验二语法分析 (13)2.1 实验目的 (13)2.2 实验要求 (13)2.3 算法思想 (13)2.4 实验程序设计说明 (15)2.5 语法分析实现 (15)4 实验中遇到的问题及解决 (22)参考资料 (23)1 实验一词法分析1.1 实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
1.2 实验要求1、待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
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)……1.3 算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
1、主程序示意图:主程序示意图如图1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};开始置初值调用扫描子程序输出单词二元组否输入串结束?是结束图1 主程序示意图(2)程序中需要用到的主要变量为syn,token和sum2、扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
扫描子程序主要部分流程如图2所示。
图2 扫描子程序流程图1.4 实验程序设计说明1、数据结构的设计先来看看WORD 结构的设计: typedef struct {int typenum; //用于存储该字符串的种别码; char *word; //用于存储字符串; }这个词法分析中,我们要将我们识别到的字符串输出他们,而且还要将他们的相应的种别码输出,因此我们得用一个结构体来将这两个属性放在一个结构体中。
开始变量初始化忽略空格是否文件结束?否返回是拼数拼字符串字母 Syn=11关键字?Syn=10否是Syn 为对应关键字的种别码对不同符给出相应的syn 值报错其他符号运算符界符等返回数字2、算法的设计首先将输入端的字符串读入然后进行前期的处理,如去掉空白符号。
之后在一个字符一个字符的进行处理,判断下一个字符串所属类型,然后给出相应类型的种别码,返回给主函数进行输出。
其中主要部分就是分类属性的判断以及判断之后不同属性种别码的赋值,这就是整个程序中的主要部分。
1.5 词法分析实现【使用C语言实现:】#include <stdio.h>#include <stdlib.h>#include <string.h>#include <windows.h>#define _KEY_WORD_END "waiting for your expanding" /*定义关键字结束标志*/ HANDLE gh_std_out; //标准输出设备句柄typedef struct /*单词二元组的结构,可以根据需要继续扩充*/{int typenum;char * word;} WORDS;char input[255]; /*输入缓冲区*/char token[255]="";/*单词缓冲区*/int p_input;/*输入缓冲区指针*/int p_token;/*单词缓冲区指针*/char ch; /*当前读入字符*/char* KEY_WORDS[]={"begin","if","then","while","do","end",_KEY_WORD_END};/*可扩充的关键字数组*/WORDS* scaner();/*词法扫描函数,获得一个单词*/void WriteKeyWord(char *str);/*高亮输出文字*/int main(){int over=1;WORDS* oneword=new WORDS;printf("Enter Your words(end with #):\n");scanf("%[^#]s",input);/*读入源程序字符串到缓冲区,以#结束,允许多行输入*/getchar();p_input=0;printf("Your words:\n%s\n",input);printf("The sequence as follow:\n( 字符\t, 种别码)\n");while(over<1000&&over!=-1){/*对源程序进行分析,直至结束符#*/oneword=scaner();/*获得一个新单词*/if(oneword->typenum<1000){printf("( ");WriteKeyWord(oneword->word);printf("\t,%5d )\n",oneword->typenum);/*打印种别码和单词自身的值*/ }over=oneword->typenum;}return 0;}/***************需要用到的自编函数参考实现*从输入缓冲区读取一个字符到ch中**************************/char m_getch(){ch=input[p_input];p_input=p_input+1;return (ch);}/***************去掉空白符**************/void getbc(){while(ch==' '||ch==10){ch=input[p_input];p_input=p_input+1;}}/***************拼接单词**************/void concat(){token[p_token]=ch;p_token=p_token+1;token[p_token]='\0';}/***************判断是否为字母**************/int letter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return 1;else return 0;}/***************判断是否为数字**************/int digit(){if(ch>='0'&&ch<='9')return 1;else return 0;}/***************检索关键字表格**************/int reserve(){int i=0;while(strcmp(KEY_WORDS[i],_KEY_WORD_END)){ if(!strcmp(KEY_WORDS[i],token)){return i+1;}i=i+1;}return 10;}/***************回退一个字符**************/void retract(){p_input=p_input-1;}/*****************数字转换成二进制****************/char* dtb(){/*Enter Your Code!*/return NULL;}/***************词法扫描函数**************/WORDS* scaner(){WORDS* myword=new WORDS;myword->typenum=10;myword->word="";p_token=0;m_getch();getbc();if(letter()){while(letter()||digit()){concat();m_getch();}retract();myword->typenum=reserve();myword->word=token;return(myword);}else if(digit()){while(digit()){concat();m_getch();}retract();myword->typenum=11;myword->word=token;return(myword);}else switch(ch){case '=': m_getch();if (ch=='='){myword->typenum=39;myword->word="==";return(myword);}retract();myword->typenum=21;myword->word="=";return(myword);break;case '+':myword->typenum=13;myword->word="+";return(myword);break;case '-':myword->typenum=14;myword->word="-";return(myword);break;case '*':myword->typenum=15;myword->word="*";return(myword);break;case '/':myword->typenum=16;myword->word="/";return(myword);break;case '(':myword->typenum=27;myword->word="(";return(myword);break;case ')':myword->typenum=28;myword->word=")";return(myword);break;case '[':myword->typenum=29;myword->word="[";return(myword);break;case ']':myword->typenum=30;myword->word="]";return(myword);break;case '{':myword->typenum=31;myword->word="{";return(myword);break;case '}':myword->typenum=32;myword->word="}";return(myword);break;case ',':myword->typenum=33;myword->word=",";return(myword);break;case ':':m_getch();if (ch=='='){myword->typenum=18;myword->word=":=";return(myword);}retract();myword->typenum=17;myword->word=":";return(myword);break;case ';':myword->typenum=26;myword->word=";";return(myword);break;case '>': m_getch();if (ch=='='){myword->typenum=24;myword->word=">=";return(myword);}retract();myword->typenum=23;myword->word=">";return(myword);break;case '<': m_getch();if (ch=='='){myword->typenum=22;myword->word="<=";return(myword);}retract();myword->typenum=20;myword->word="<";return(myword);break;case '!': m_getch();if (ch=='='){myword->typenum=21;myword->word="!=";return(myword);}retract();myword->typenum=-1;myword->word="ERROR";return(myword);break;case '\0':myword->typenum=1000;myword->word="OVER";return(myword);break;default:myword->typenum=-1;myword->word="ERROR";return(myword);}}/* 函数功能: 高亮显示指定字符串*/void WriteKeyWord(char *str){COORD pos;CONSOLE_SCREEN_BUFFER_INFO csbi;DWORD len; //指向变量的指针,用来存放字符的实际数目WORD att=FOREGROUND_GREEN | FOREGROUND_INTENSITY;gh_std_out = GetStdHandle(STD_OUTPUT_HANDLE); //获取标准输出设备句柄if (GetConsoleScreenBufferInfo(gh_std_out, &csbi)){pos.Y=csbi.dwCursorPosition.Y;pos.X=csbi.dwCursorPosition.X;}SetConsoleCursorPosition(gh_std_out,pos);printf("%s ",str);FillConsoleOutputAttribute(gh_std_out,att,strlen(str),pos,&len);}1.6 词法实验结果及结果分析输入begin x:=9: if x>9 then x:=2*x+1/3; end #程序输出序列的结果如下图3所示:图3 程序运行结果2 实验二语法分析2.1 实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。