词法分析 赵凯
湖北大学本科课程
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
基于C语言的词法分析器
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
目
姓 名 赵凯 学 号 2009221104210008 专业
年级 09计科一班 指导教师 孙斌
称 讲师 职
20112年 11月 22日
目 录
引言..........................................................................3
第一章 概述................................................................4
设计的基本原理 ......................................................4 1.1设计
2.1单词符号分类..........................................................4
2.2输出格式与存储格式................. ..................................4
第三章 程序设计......................... ..................................6
3.1结构思路............................. .................................6
3.2模块设计与分析....................... .................................6
第四章 测试程序........................... ................................7
4.1测试程序............................. .................................7
4.2分析结果............................. .................................7
4.3存储结构............................. .................................8
第五章 小结................................................................8
参考文献......................................................................8
附录 词法设计程序清单......................... ..........................9
基于C语言词法分析器的设计
摘要
文章首先对编译原理进行概括的介绍,第一章主要是描写设计内容及设计要
求,第二章介绍设计的基本原理,第三章对程序设计的总体方案及各模块设计做
了介绍,第四章对程序进行测试,最后对文章基进行总结与展望。
关键词:编译原理 词法分析器 关键字 标识符 常数 运算符 界限符
引言:
《编译原理》是国内外各高等院校计算机科学技术类专业,特别是计算机软件专业的一门重要专业课程。该课程系统地向学生介绍编译程序的结构、工作
流程
快递问题件怎么处理流程河南自建厂房流程下载关于规范招聘需求审批流程制作流程表下载邮件下载流程设计
及编译程序各组成部分的设计原理和实现技术。由于该课程理论性和实践性都比较强,内容较为抽象复杂,涉及到大量的软件设计算法,因此,一直是一门比较难学的课程。为了使学生更好地理解和掌握编译技术的基本概念、基本原理和实现方法,实践环节非常重要,只有通过上机进行程序设计,才能使学生对比较抽象的教学内容产生具体的感性认识,增强学生综合分析问题、解决问题的能力,并对提高学生软件设计水平大有益处。
编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。词法分析(英语:lexical analysis)是计算机科学中将字符序列转换为单词(Token)序列的过程。进行语法分析的程序或者函数被称为词法分析器(Lexical analyzer简称Lexer),也叫扫描器(Scanner)。词法分析器一般以函数的形式存在,供语法分析器调用。
词法分析阶段是编译过程的第一个阶段,是编译的基础。这个阶段的任务是从左到右一个字符接着一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。词法分析程序实现这个任务。词法分析程序可以使用Lex等工具自动生成。词法分析是所有分析优化的基础,涉及的知识较少,比如状态转换图等,易于实现。本次课程设计程序设计语言是C语言。
第一章:概述
1.1设计(5) 常量
2.2输出格式与存储格式 输出格式:
(种别编码,单词符号)
结构如下图1
图1
存储格式:
(种别编码,单词符号)
结构如下图
2
图2
备注:关键词每个都有一个编码,标识符统一用以各种别编码识别,常数、运
算符以及界限符各有一个种别编码识别。
第三章:程序设计
3.1结构思路
定义相关的变量和数据结构。关键字作为特殊标识符处理,把它们预先安排在
一张
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能
查到匹配的单词,则该单词为关键字,否则为一般标识符。特殊定义其他运算符
以及界限符。把每个种类都归为一起。
3.2模块设计与分析
void options(); //菜单
void analyse(); //分析结果显示
void getch(char ch); //读取为字母
void getnum(char ch); //读取为数字
void getspace(char ch); //读取空格、跳格、回车、换行等等(包
括界限符) void getelse(char ch); //其他类型字符
struct keywords //关键字结构体
{
char name[10];
int num;
};
struct relation //运算符、关系运算符结构体
{
char name[4];
int num;
};
struct keywords test[18]={
{"main",1},{"if",2},{"int",3},{"for"
;,4},{"while",5},{"do",6},
{"retuen",7},{"break",8},{"continue",9},{&quo
t;stdio.h",10},
{"include",11},{"case",12},{"float",13},{"s
witch",14},
{"void",15},{"else",16},{"for",17}
};
struct relation relation[18]={
{"#",40},{"+",41},{"-",42},{"*",43
},{"/",44},{"=",45},{">",46},
{"<",47},{">=",48},{"<=",49},{"=
=",50},{"!",51},{"%",52},{"&",53},
{"&&",54},{"|",55},{"||",56},{"
;!=",58}
};
struct value //处理变量的结构体
{
int type;
int no;
char str[20];
}value[10];
int variable(char str[10]); //变量处理
char ch=‘1’;
char str[10];
int k=0,i=0;
char sourcefile[30]; //源文件名
char objectfile[30]; //目标文件名
FILE *fp,*hp;
int count=-1;
int flag=-1;
第四章:测试程序
4.1测试程序
#include<stdio.h>
#include <iostream.h>
#include<string.h>
using namespace std;
string
key[17]={"begin","end","if","then",&
quot;else","while","write","read","do
",
"call","const","char","until","pr
ocedure","repeat","void"};
main()
{
int a=21;
char h="heart";
}
4.2分析结果
分析结果如图
3
图3
4.3存储结构
存储结构如图
4
图4
第五章:小结
词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号,通过本实验的完成,更加加深了对词法分析的理解。
参考文献:
黄文奇 许如初. 《近世计算理论导引:NP难度问题的背景、前景及其求解算法研究》. 科学出版社 2004
吕国英. 《算法设计与分析》 清华大学出版社 2009
杨路明. 《C语言程序设计
教程
人力资源管理pdf成真迷上我教程下载西门子数控教程protel99se入门教程fi6130z安装使用教程
》. 北京邮电大学出版社. 2003
李春葆 尹为民等. 《数据结构教程(第3版)》. 清华大学出版社 2009
《编译原理》(第二版),作者:何炎祥,李晓燕,王汉飞
《编译原理课程辅导》,作者:王生原,吕映芝,张素琴
附录:
词法设计程序清单如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct keywords //关键字结构体
{
char name[10]; int num;
};
struct relation //运算符、关系运算符结构体
{
char name[4];
int num;
};
struct keywords test[18]={
{"main",1},{"if",2},{"int",3},{"for",4},{"while",5},{"do",6},
{"retuen",7},{"break",8},{"continue",9},{"stdio.h",10},
{"include",11},{"case",12},{"float",13},{"switch",14},
{"void",15},{"else",16},{"for",17}
};
struct relation relation[18]={
{"#",40},{"+",41},{"-",42},{"*",43},{"/",44},{"=",45},{">",46},
{"<",47},{">=",48},{"<=",49},{"==",50},{"!",51},{"%",52},{"&",53},
{"&&",54},{"|",55},{"||",56},{"!=",58}
};
struct value //处理变量的结构体
{
int type;
int no;
char str[20];
}value[10];
void options(); //菜单
void analyse(); //分析结果显示
void getch(char ch); //读取为字母
void getnum(char ch); //读取为数字
void getspace(char ch); //读取空格、跳格、回车、换行等等(包
括界限符) void getelse(char ch); //其他类型字符
int variable(char str[10]); //变量处理
char ch=‘1’;
char str[10];
int k=0,i=0;
char sourcefile[30]; //源文件名 char objectfile[30]; //目标文件名 FILE *fp,*hp;
int count=-1;
int flag=-1; //标志
int main(int argc,char *argv[])
{
} int choice; options(); //显示菜单 printf("输入进行词法分析的源文
件名:"); scanf("%s",sourcefile); printf("\n输入分析结果存
入的文件名:"); scanf("%s",objectfile); printf("\n");
):"); //printf("\n输入选项:"); printf("请输入选择项(1或者2
scanf("%d",&choice); for(; ;) { } switch(choice) { case
1: analyse(); break; case 2: } exit(1); break; break; return 0;
void options()
{
printf("***************************\n"); printf("***"); printf(" 《词法分析器》"); printf(" ***\n"); printf("***"); printf(" 1.分析结果:"); printf("
***\n");
}
printf("***"); printf(" 2.退出程序:"); printf("
***\n"); printf("***************************\n");
void analyse()
{
if((fp=fopen(sourcefile,"r"))==NULL) //读取文件 { printf("
读文件打开错误~\n"); exit(1); }
if((hp=fopen(objectfile,"w"))==NULL) //写入文件
{ printf("写入文件打开错误~\n"); exit(1); } while(ch!=EOF)
//判断是否到文件结尾 { ch=fgetc(fp); //读取磁盘字
符串
if(((ch>=‘a’)&&(ch<=‘z’))||((ch>=‘A’)&&(ch<=‘Z’))) { getch(ch); } else if((ch>=‘0’)&&(ch<=‘9’)) //如
果读取的是数字 { getnum(ch); }
else
if((ch==‘ ‘)||(ch==‘\r’)||(ch==‘\n’)||(ch==‘\t’))
{ getspace(ch); } else //其他情况
{ getelse(ch); } k=0; //单个字符标志 str[k]=‘\0’; }; fclose(fp); //关闭读文
件 fclose(hp); //关闭写文件
printf("\n");
}
void getch(char ch)
{
for(; ;)
{
str[k]=ch;
str[++k]=‘\0’;
ch=fgetc(fp);
if( !(( (ch>=‘a’) && (ch<=‘z’) ) || ( (ch>=‘A’)
&& (ch<=‘Z’) (ch<=‘9’) )||ch==‘.’))
{
fseek(fp,-1L,1);
for(i=0;i<11;i++)
{
if(strcmp(str,test[i].name)==0) //测试是否为保留字 {
printf("( %d,%s )\n",test[i].num,test[i].name);
fprintf(hp,"( %d,%s )\n",test[i].num,test[i].name); k=0;
flag=1;
value[count+1].type=test[i].num;
break;
}
}
if(k!=0) //否则为变量
{
int tem;
tem=variable(str);
printf("( 20,%s ) \n",str);
fprintf(hp,"( 20,%d )\n",tem);
break;
}
break;
}
}
}
void getnum(char ch)
{
for(; ;)
{
str[k]=ch; ) || ( (ch>=‘0’) &&
} str[++k]=‘\0’; ch=fgetc(fp); if( !((ch>=‘0’) && (ch<=‘9’)) )
{ fseek(fp,-1L,1); } printf("( 30,%s ) \n",str);
fprintf(hp,"( 30,%s )\n",str); break;
}
void getspace(char ch) //判断时候是空格、跳格、回车、换行等等 {
for(; ;)
{
ch=fgetc(fp); //检测读取字符
if(!((ch==‘ ‘)||(ch==‘\n’)||(ch==‘\t’)||(ch==‘\r’))) { fseek(fp,-1L,1); break;
}
}
}
void getelse(char ch) //其他字符,包括界限符
{
switch(ch) { case ‘.’: printf("( 60, . )\n");
fprintf(hp,"( 60,. )\n"); break; case ‘#’: printf("( 40, # )\n"); fprintf(hp,"( 40,# )\n"); break; case ‘,’: if(flag==1)
value[count+1].type=value[count].type; printf("( 61, , )\n"); fprintf(hp,"( 61,, )\n"); break; case ‘;’:
flag=0; value[count+1].type=2; printf("( 62, ; )\n"); fprintf(hp,"( 62,; )\n"); break; printf("( 63, { )\n"); fprintf(hp,"( 63,{ )\n"); break; printf("( 64, } )\n"); fprintf(hp,"( 64,} )\n"); case ‘{‘: case ‘}’: break; case ‘(‘: printf("( 65, ( )\n"); fprintf(hp,"( 65,( )\n"); break; case ‘)’:
printf("( 66, ) )\n"); fprintf(hp,"( 66,) )\n"); break; case ‘+’:
printf("( 41, + )\n"); fprintf(hp,"( 41,+ )\n"); break; case ‘-’: printf("( 42, - )\n"); fprintf(hp,"( 42,- )\n"); break; case ‘*’: printf("( 43, * )\n"); fprintf(hp,"( 43,* )\n"); break; case ‘/’: printf("( 44, / )\n"); fprintf(hp,"( 44,/ )\n"); break; case ‘=‘: str[k]=ch; str[++k]=‘\0’; ch=fgetc(fp); if(ch!=‘=‘)
{ fseek(fp,-1L,1);
printf("( 45, = )\n"); fprintf(hp,"( 45,= )\n"); } else if(ch==‘=‘) { printf("( 50, = )\n");
fprintf(hp,"( 50,= )\n"); } break; case ‘>’: str[k]=ch;
str[++k]=‘\0’; ch=fgetc(fp); if(ch!=‘=‘) { } else if(ch==‘=‘) { } printf("( 48, > )\n"); fprintf(hp,"( 48,> )\n"); fseek(fp,-1L,1); printf("( 46, > )\n");
fprintf(hp,"( 46,> )\n"); break; case ‘<’:
str[k]=ch; str[++k]=‘\0’; ch=fgetc(fp); if(ch!=‘=‘) { } fseek(fp,-1L,1);
printf("( 47, < )\n"); fprintf(hp,"( 47,0 )\n"); else if(ch==‘=‘) { printf("( 49,0 )\n");
fprintf(hp,"( 49,0 )\n"); } break; case ‘!’:
str[k]=ch; str[++k]=‘\0’; ch=fgetc(fp); if(ch!=‘=‘) { } fseek(fp,-1L,1);
printf("( 51, != )\n"); fprintf(hp,"( 51,!= )\n"); else if(ch==‘=‘) { printf("( 58, != )\n");
fprintf(hp,"( 58,0 )\n"); } break; case ‘%’:
printf("( 52, % )\n"); fprintf(hp,"( 52,% )\n"); break; case ‘&’: str[k]=ch; str[++k]=‘\0’; ch=fgetc(fp); if(ch!=‘&’)
{ fseek(fp,-1L,1); printf("( 53, & )\n");
fprintf(hp,"( 53,& )\n"); } else if(ch==‘&’)
{ printf("( 54, && )\n");
fprintf(hp,"( 54,&& )\n"); } break; case ‘|’:
str[k]=ch; str[++k]=‘\0’; ch=fgetc(fp); if(ch!=‘|’) {
} fseek(fp,-1L,1); printf("( 55, | )\n");
fprintf(hp,"( 55,0 )\n"); } else if(ch==‘||’) { printf("( 56, || )\n"); fprintf(hp,"( 56,|| )\n"); } break;
}
int variable(char str[10]) {
}
int j; for(j=0;j<count+1;j++) if(strcmp(str,value[j].str)==0) break; if(j<count+1) return (value[j].type*100+value[j].no); else { count++; } if(flag==-1) value[count].type=20; for(int i=0;i<9;i++) value[count].str[i]=str[i]; value[count].no=count+1; return (value[count].type*100+value[count].no);