博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简单词法分析器的实现
阅读量:7065 次
发布时间:2019-06-28

本文共 4543 字,大约阅读时间需要 15 分钟。

这是我们的一次编程作业,要求用C编写一个简单的词法分析器。要求如下:

编制一个单词获取程序,从文件输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、整数、小数、字符串、分隔符、运算符等七大类。并依次输出各个单词的内部编码及单词符号自身文本串(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。

注意:单词类型大小写不敏感(即不区分大小写)

 

1、词法规则

关键字: program、const、var、integer、decimal、string、procedure、begin、end 、if、then、else、while、do、call、read、write、not

单词类别:1

标识符: 字母或“_”打头的由字母、数字串或“_”组成的任意长度的符号串。

单词类别:2

整数:   数字串。

单词类别:3

小数:   数字串·数字串

单词类别:4

字符串: 由一对“”括起来的任意长度的符号串。注意:可以多行。

单词类别:5

分隔符: {、}、(、)、;、空格

单词类别:6

运算符: :=、=、<、<=、>、>=、+、-、*、/

单词类别:7

2、设计词法分析函数getToken( ),完成以下功能:

1)getToken( )每调用一次就分析出一个单词;

2)返回单词类别、单词自身文本串、单词在源文件中的行列号;

3、编写测试程序,反复调用函数getToken ( ),输出单词信息。


 

以下是代码实现:

 

注意的事项:

  1,">="这一类操作符要进行判断。

  2,小数的识别。为了简便,我把小数当成字符串进行处理,后续可以加上一个字符串转数字的程序,或者直接直接识别成小数。

  3,输入的源程序如何判断结束,我使用的是"#"字符进行判断,应该可以通过使用EOF进行识别吧。

  4,超前搜索指针要回退。

#include 
#include
#include
using namespace std;#define KW 1 //关键字#define ID 2 //标识符#define INT 3 //整数#define FLT 4 //小数#define STR 5 //字符串#define BRK 6 //分隔符#define OP 7 //操作符#define WordLen 100char prog[80],token[WordLen];char ch;int p,j,syn;int rowNum,lineNum;char *keyword[18] = {
"program","const","var","integer","decimal","string","procedure", "begin","end","if","then","else","while","do","call","read","write","not"};void getToken(){ for(int i = 0;i < WordLen;i++) token[i] = NULL; ch = prog[p++]; /*识别标识符或者变量名*/ if(ch >= 'a'&&ch <= 'z'||ch == '_'){ int i = 0; while((ch >= '0'&&ch <= '9')||(ch >= 'a'&&ch <= 'z')||ch == '_'){ token[i++] = ch; ch = prog[p++]; } token [i++] = '\0'; p--; syn = ID; for(int n = 0;n < 18 ;n++){ if(strcmp(token,keyword[n]) == 0){ syn = KW; break; } } } /*识别实数*/ else if(ch >= '0' && ch <= '9'){ bool isDouble = false; //是否是小数 j = 0; while(ch>='0'&&ch<='9'){ token[j++] = ch; ch = prog[p++]; } if(ch=='.'){ isDouble = true; token[j++] = ch; ch = prog[p++]; while((ch>='0' && ch<='9')){ token[j++] = ch; ch = prog[p++]; } } if(isDouble){ syn = FLT; } if(!isDouble){ syn = INT; } p--; } /*以下代码用于判断字符串*/ else if(ch == '\"'){ j = 0; token[j++] = ch; while(prog[p] != '\"'){ token[j ++] = prog[p++]; } token[j] = prog[p++]; //p--;此处p不回退,因为上个while判断语句没有进行超前搜索。 syn = STR; } /*以下代码用于判断运算符*/ else switch(ch){
//其他字符 case'<': j = 0; token[j++] = ch; ch = prog[p++]; if(ch == '='){ token[j++] = ch; syn = OP; } else{ p--; syn = OP; } break; case'>': j = 0; token[j++] = ch; ch = prog[p++]; if(ch == '='){ token[j] = ch; syn = OP; } else{ p--; syn = OP; } break; case':': j = 0; token[j++] = ch; ch = prog[p++]; if(ch == '='){ syn = OP; token[j++] = ch; } else { syn = -1; p--; } break; case '=':syn = OP;token[0] = ch;break; case '+':syn = OP;token[0] = ch;break; case '*':syn = OP;token[0] = ch;break; case '/':syn = OP;token[0] = ch;break; case '{
':syn = BRK;token[0] = ch;break; case '}':syn = BRK;token[0] = ch;break; case '(':syn = BRK;token[0] = ch;break; case ')':syn = BRK;token[0] = ch;break; case ';':syn = BRK;token[0] = ch;break; case ' ':syn = BRK;token[0] = ch;break; case '\n':syn = -2;rowNum = 0;break; case '#':syn = 0;break; default :syn = -1;break; }}int main(){ //freopen("D:\\compiler.txt","r",stdin); p = 0; lineNum = 1; gets(prog); for(int m = 0;m < sizeof(prog);m++){ if(prog[m] >= 'A'&&prog[m] <= 'Z'){ prog[m] = prog[m] - 'A' + 'a'; } } do { getToken(); rowNum++; switch(syn) { case 1: cout<
<<" "<
<<" "<<"("<
<<","<
<<")"<

 

转载于:https://www.cnblogs.com/ohxiaobai/p/4394384.html

你可能感兴趣的文章
Mac 平台下功能强大的Shimo软件使用指南
查看>>
永远不要对一个外行聊你的专业
查看>>
MySQL学习四部曲
查看>>
SCCM 2012 R2实战系列之一:SQL安装
查看>>
windows下安装memcached
查看>>
08R2-12R2基于访问权限的文件枚举
查看>>
Gartner:网络信息安全投入依然不在中国政企客户优先投入之列
查看>>
恢复误删除的ESXi服务器存储VMFS卷
查看>>
SFB 项目经验-22-如何查看存储的管理IP地址
查看>>
libevent入门教程:Echo Server based on libevent
查看>>
.NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
查看>>
一次服务器CPU占用率高的定位分析
查看>>
安装office2007 1706错误
查看>>
crontab中执行多条命令
查看>>
25 JavaScript的幻灯片用于在Web布局的精彩案例
查看>>
用C语言写的迅雷看看XV文件提取器及C语言源代码
查看>>
ccpuid:CPUID信息模块 V1.01版,支持GCC(兼容32位或64位的Windows/Linux)
查看>>
用dom4j操作XML文档(收集)
查看>>
WinForm实例源代码下载
查看>>
hdu 1829 A Bug's Life(并查集)
查看>>