编译原理比较复杂的词法分析器 含代码

实验报告二

词法分析

一、总体设计思想

1)实验目的:

设计编制并调试一个词法分析程序,加深对构造词法分析器的原

理和技术的理解与应用。

2)实验具体要求:

针对计算机高级程序语言——C 语言子语言,运用恰当的词法分析技术线路,设计和实现C 语言子语言的词法分析器。

编程语言:C 语言/JAV A 语言 平台选择:Linux/Windows 技术线路( 任选其一)

⏹ 正规式→NFA →DFA →min DFA→程序设计 ⏹ 正规文法→NFA →DFA →min DFA→程序设计 词法分析器程序输出形式,参见◤输出形式设计◢ 具有出错处理功能

C 语言子语言词法描述——涉及的单词类如下:

(1)关键字

main if else while do for int void char

(2)运算符和界符

注:#为结束标志符,详见◤程序框架◢

(3)标识符

正规式:ID=letter(letter|digit)*

(4)整型常数

正规式:NUM= digit(digit)*

3)词法分析器构造原理:

词法分析器就是根据语言的此法规则构造出识别其单词的有限自动机,它是一个数学模型,先给出识别各类单词的状态转换图,再将各类单词的状态转换图的初始状态合并成一个唯一的初状态;然后化简并调整冲突的状态编号;最后再将有限自动机变成一个可行的词法分析器。

二、种别码表设计及其在计算机中存放表示

1)单词种别码设计:

单 词 种 别 码 对 照 表

2)输出形式设计:

词法分析器的输入是源程序字符串,输出是对应的单词串。每个单词按照二元组(种别码,单词符号本身)格式输出。

例如:假设源程序为

则词法分析器对应输出的结果是:

三、词法分析程序详细设计

1)算法构造思想:

依据建立的识别单词的DFA ,设计算法,其框架如下。其中, ① syn 存放单词的种别码;

② token 存放符合C 语言子语言词法规则的单词; ③ sum 存放整型常量的单词。 ④ Prog 存放所有输入的字符。

⑤ isSignal 判断是否带正负号(0不带,1负号,2正号)。 ⑥ isDecimal 判断是否是小数。 ⑦ isExp 判断是否是指数。

2)主要模块算法的框图描述:

四、 主要代码

#include #include #include

char prog[80]; //存放所有输入字符

char token[32]; //② token 存放符合C 语言子语言词法规则的单词; char ch; //单个字符

int syn,p,m,n; // ① syn存放单词的种别码 double sum; //③ sum存放整型常量的单词。 int count;

int isSignal; //是否带正负号(0不带,1负号,2正号) int isDecimal; //是否是小数 double decimal; //小数 int isExp; //是否是指数 int index; //指数幂 int isNegative; //是否带负号 double temp; int temp2; int repeat; void scanner();

char *rwtab[9]={"main", "if", "else", "while", "do", "for" , "int" , "char" , "void"}; void main() { p=0; count=0; isDecimal=0; index=0; repeat=0;

printf("\nplease input a range of data, with the end of #:\n"); do{

ch=getchar(); prog[p++]=ch;

}while(ch!='#'); //输入以#号键结束 p=0; do{

scanner(); //扫描,单词 switch(syn) { case 11:

if(isDecimal==0)

{

//加了1个强制类型转换 printf("(%d,%d) ",syn,(int)sum); break; }

else if(isExp==1) {

printf("(%d,%e) ",syn,sum); isExp=0; isDecimal=0; break; }

else if(isDecimal==1) {

printf("(%d,%f) ",syn,sum); isDecimal=0; break; } case -1:

printf("输入错误:") printf(" \n ");

break; default:

printf("(%d,%s) ",syn,token); } }while(syn!=0); getchar(); }

void scanner() {

sum=0; decimal=0; m=0;

for(n=0;n

ch=prog[p++]; //从prog 中读出一个字符到ch 中 while(ch==' ') //跳过空字符(无效输入) ch=prog[p++];

if(((ch>='a')&&(ch='A')&&(ch

while(((ch>='a')&&(ch='A')&&(ch='0')&&(ch

token[m++]=ch; //ch=>token ch=prog[p++]; //读下一个字符 }

token[m++]='\0'; p--; //回退一格 syn=10;

//如果是"main", "if", "else", "while", "do", "for" , "int" , "char" , "void"标识符中的一个

for(n=0;n

if(strcmp(token,rwtab[n])==0) {

syn=n+1; break; } }

else if((ch>='0')&&(ch

if(isSignal==1) {

//token[m++]='-'; }

while((ch>='0')&&(ch

sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的 ch=prog[p++]; } if(ch=='.') {

isDecimal=1; ch=prog[p++];

count=0; //之前忘了清零,123.123+123.123#两个浮点数就无法识别 while((ch>='0')&&(ch

//pow(x,y)计算x 的y 次幂 temp=(ch-'0')*pow(0.1,++count); decimal=decimal+temp; //AddToDec(); ch=prog[p++]; }

sum=sum+decimal; }

if(ch=='e'||ch=='E') {

isExp=1; ch=prog[p++]; if(ch=='-') {

isNegative=1; ch=prog[p++]; }

while((ch>='0')&&(ch

//指数

index=index*10+ch-'0'; ch=prog[p++]; } //10的幂

//123e3代表123*10(3)

//sum=sum*pow(10,index);是错误的 if(isNegative)

sum=sum*pow(0.1,index); else

sum=sum*pow(10,index); }

if(isSignal==1) {

sum=-sum; isSignal=0; } p--; syn=11; }

else switch(ch) {

case '

token[m++]=ch;

ch=prog[p++];

if(ch=='=')

{

syn=22;

token[m++]=ch;

}

else

{

syn=20;

p--;

}

break;

case '>':

m=0;

token[m++]=ch;

ch=prog[p++];

if(ch=='=')

{

syn=24;

token[m++]=ch;

}

else

{

syn=23;

p--;

}

break;

case ':':

syn=17; token[m++]=ch;

break;

case '+':

temp2=prog[p];

token[m++]=ch;

if((temp2>='0')&&(temp2

{

isSignal=2; //isSignal正数

ch=prog[p++];

repeat=0;

goto IsNum;

}

if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) //如果重复出现符号,才将后边的+,-视为正负号

{

repeat=1;

//ch=prog[p++];

}

syn=13;

break;

case '-':

temp2=prog[p];

token[m++]=ch;

if((temp2>='0')&&(temp2

{

isSignal=1;

ch=prog[p++]; //读“-”下一个字符

repeat=0;

goto IsNum; //转到数字的识别

}

if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) //如果重复出现符号,才将后边的+,-视为正负号

{

repeat=1; //预言会重复

//ch=prog[p++]; //读下一个字符

}

syn=14;

break;

case '*':

temp2=prog[p];

token[m++]=ch;

syn=15;

break;

case '/':

syn=16;

token[m++]=ch;

break;

case '=':

syn=18;

token[m++]=ch;

break;

case ';':

syn=26;

token[m++]=ch;

break;

case '(':

temp2=prog[p];

token[m++]=ch;

syn=27;

break;

case '{':

temp2=prog[p];

token[m++]=ch;

syn=12;

break;

case '}':

temp2=prog[p];

token[m++]=ch;

syn=19;

break;

case ')':

syn=28;

token[m++]=ch;

break;

case'#':

syn=0;

token[m++]=ch;

break;

default:

syn=-1;

}

}

五、测试结果

1)字符串输入测试:

2)小数输入测试:

六、设计体会与收获

通过此次试验,使我对词法分析器有了更加深入的了解,也使我对编译原理这门课程产生了浓厚的兴趣,虽然在实验过程中遇到了不少的困难,但是在同学以及老师共同的帮助下,都基本一一解决,使我懂得了团队精神的重要性。同时通过本次的实验,使我重新学习了C 语言编程方法,知识也得到了相应的扩展,思考问题的方式也能够变得多样化和灵活化。总的来说,本学期编译原理课程的实验让我受益匪浅。


相关文章

  • 编译原理课程设计报告
  • 南京航空航天大学 编译原理课程设计 题目一个PASCAL语言子集(PL/0)编译器的设计与实现 专业 班 号 学号 姓名 指导老师 答辩日期2014年1月 1设计的题目 一个PASCAL语言子集(PL/0)编译器的设计与实现 2课程设计的要 ...

  • 编译原理试题及答案
  • 历年试题及答案 一. (每项选择2分,共20分)选择题 1.将编译程序分成若干个"遍"是为了_b__. a. 提高程序的执行效率 b. 使程序的结构更加清晰 c. 利用有限的机器内存并提高机器的执行效率 d. 利用有限的 ...

  • 编译原理课程设计
  • 宁波大红鹰学院 信息工程学院 课程设计报告 课程名称 编译原理 基于LL(1)法的条件语实验名称 句语法语义分析程序 姓名 学号 专业 班级 地点 教师 目 录 一.系统需求分析------------------------------- ...

  • 词法分析小结
  • 词法分析是编译器工作的第一阶段,它的工作就是从输入(源代码)中取得token,以作为parser(语法分析)的输入,一般在词法分析阶段都会把一些无用的空白字符(white space,即空格、tab和换行)以及注释剔除,以降低下一步分析的复 ...

  • 漏洞自动挖掘技术研究进展
  • 总第231期2009年第1期 计算机与数字工程 Computer&DigitalEngineering Vol-37No.1 100 漏洞自动挖掘技术研究进展 高峻徐志大李健 (中南计算机通信研究所武汉430074) 摘要漏洞利用的 ...

  • 广工2014编译原理课程设计报告
  • 课 程 设 计 课程名称 编译原理 题目名称 PL/0编译器的扩充 学生学院 计算机学院 专业班级 计算机科学与技术12(4) 学 号 3112005901 学生姓名 柏石先 指导教师 李杨 2014 年 12 月 28日 一. 实验目的与 ...

  • 编译原理作业
  • 编译原理作业 作业1:输出CL,GCC 词法分析,语法分析,语义分析的结果 即通过参数控制,分步完成编译过程. 答案: 一. gcc 编译过程分为四段:预处理.编译.汇编.链接 预处理: gcc-Ehello.c-ohello.i ● 参数 ...

  • 编译原理的发展史
  • 编译器与编译工具概述 摘要: 编译器是将便于人编写,阅读,维护的高级计算机语言翻译为计算机能解读.运行的低阶机器语言的程序.编译是从源代码(通常为高阶语言)到能直接被计算机或虚拟机执行的目标代码(通常为低阶语言或机器语言)的翻译过程. 一. ...

  • 用自动化理论研究公文流转流程问题
  • ●冯坚福 用自动化理论研究公文流转流程问题 [摘要] 随着网络技术和办公自动化技术的发展,公文流转系统成为电子政务的基础和重要组成部分.但在公文流转系统的流程用户自定义上,存在着两个极端:小型系统的流程定义过于机械,适应性不强:大型系统的流 ...

© 2024 范文参考网 | 联系我们 webmaster# 12000.net.cn