编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、分界符四大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)

1.程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数之间的调用关系图(请分项逐一描述)

#define keywordSum  34

保留字数量

string keyword[keywordSum]

保留字

char singleword[20]

单分界符

char doubleword[10]

双分界符首字符

char escapeend[14]

转义字符尾字符

FILE *fin,*fout;

输入输出文件指针

std::map <int,string> f;

std::map <int,string> s;

f是标识符表,s是字符串表。

int cffx()

词法分析函数,无输入。输出0,一切正常,输出1,输入文件错误,输出2,输出文件错误。

string temp="";

当前识别单词。

isalpha(ch)|isalnum(ch)|isdigit(ch)

Ctype库函数,判断ch,isalpha英文字母,isalnum字母加数字,isdigit数字。

2.程序总体执行流程图

传不上去,不传了。。。

在代码中是不同部分,这里是为了简化流程图

3.程序源代码

#include<stdio.h>#include<string>#include<ctype.h>#include<string.h>#include<iostream>#include<map>#define keywordSum  34using namespace std;//下面定义保留,为简化程序,使用字符指针数组保存所有保留字。//如果想增加保留字,可继续添加,并修改保留字数目string keyword[keywordSum]= {"include","if","else","goto","switch","case","do","while","for","contiue","break","return","default","typedef","int","long","short","float","double","char","unsigned","signed","const","void","volatile","enum","struct","union","auto","static","extern","register","read","write"};//下面定义纯单分界符,如需要可添加char singleword[20]= {'(',')','{','}',';',',',':','[',']','#','\'','&'};//下面定义双分界符的首字符char doubleword[10]= {'>','<','=','!','+','-','*','%'};//下面定义转义字符的尾字符char escapeend[14]= {'a','b','f','n','r','t','v','\\','\'','\"','\?','O'};FILE *fin,*fout; //用于指向输入输出文件的指针string Scanin,Scanout;std::map <int,string> f;std::map <int,string> s;int cffx(){char ch;printf("请输入源程序文件名(包括路径):");cin >> Scanin;if((fin=fopen(Scanin.c_str(),"r"))==NULL) //判断输入文件名是否正确{printf("\n打开词法分析输入文件出错!\n");return(1);//输入文件出错返回错误代码1}printf("请输入词法分析输出文件名(包括路径):");cin >> Scanout;if((fout=fopen(Scanout.c_str(),"w"))==NULL) //判断输出文件名是否正确{printf("\n创建词法分析输出文件出错!\n");return(2); //输出文件出错返回错误代码2}int f_i=1,s_i=100;ch=getc(fin);string temp="";int i = keywordSum;while(ch!=EOF){while (ch==' '||ch=='\n'||ch=='\t')ch=getc(fin);if (ch==EOF)break;if (ch=='_'||isalpha(ch)){temp += ch;ch=getc(fin);while(ch=='_'||isalnum(ch)){temp += ch;ch=getc(fin);}int bl = 0;while((bl<keywordSum) && strcmp(temp.c_str(),keyword[bl].c_str()))bl++;if (bl<keywordSum)   //不是保留字,输出标识符{fprintf(fout,"%15d\t%s\n",bl+1,temp.c_str());  //输出标识符符号temp = "";}//printf("%03d\t%s\n",bl+1,temp);else //是保留字,输出保留字{fprintf(fout,"%15d\t%s\n",200,temp.c_str());  //输出保留字符号map<int,string> ff(f);int flag=1;while (!ff.empty()&&flag){if(ff.begin()->second.c_str()==temp)flag=0;ff.erase(ff.begin());}if(flag){f[f_i]= temp.c_str();f_i++;}//printf("%\n",i,temp);temp = "";}}else if(isdigit(ch)){int flag = 1;temp += ch;ch=getc(fin);while(isdigit(ch)||(ch=='.'&&flag)){if(ch=='.'&&flag){flag = 0;temp += ch;ch=getc(fin);}else{temp += ch;ch=getc(fin);}}while (ch==' '||ch=='\n'||ch=='\t'){temp += ch;ch=getc(fin);}if(strchr(doubleword,ch)>0||strchr(singleword,ch)>0||ch=='/'){if(flag)fprintf(fout,"%15s\t%s\n","INT",temp.c_str());elsefprintf(fout,"%15s\t%s\n","FLOAT",temp.c_str());}else{while(!(strchr(doubleword,ch)>0||strchr(singleword,ch)>0||ch=='/')){temp += ch;ch=getc(fin);}fprintf(fout,"%15s\t%s\n","ERROR",temp.c_str());}temp = "";}else if(strchr(singleword,ch)>0){temp+=ch;char* ll = singleword;int l = (strchr(singleword,ch))-ll;ch=getc(fin);//读下一个符号以便识别下一个单词fprintf(fout,"%15d\t%s\n",l+keywordSum+2,temp.c_str());  //输出单分界符符号temp="";}else if(strchr(doubleword,ch)>0){temp+=ch;char* ll = doubleword;int l = (strchr(doubleword,ch))-ll;char ch1;ch1=getc(fin);  //读下一个字符判断是否为双分界符if (ch1=='=')   //如果是=,组合双分界符{temp+=ch1;fprintf(fout,"%15d\t%s\n",l+keywordSum+2+30,temp.c_str());ch=getc(fin);  //读下一个符号以便识别下一个单词}else{fprintf(fout,"%15d\t%s\n",l+keywordSum+2+20,temp.c_str());  //输出单或双分界符符号ch = ch1;}temp="";}else if (ch=='/')    //注释处理{ch=getc(fin);  //读下一个字符if (ch=='/'){do   //删除注释{ch=getc(fin);}while (ch!='\n'&&ch!=EOF);ch=getc(fin);//读下一个符号以便识别下一个单词}else if(ch=='*')   //如果是*,则开始处理注释{char ch1;ch1 = getc(fin);do   //删除注释{ch=ch1;ch1=getc(fin);}while ((ch!='*' || ch1!='/')&&ch1!=EOF); //直到遇到注释结束符*/或文件尾ch=getc(fin);//读下一个符号以便识别下一个单词}else //不是*则处理单分界符/{temp+='/';fprintf(fout,"%15d\t%s\n",102,temp.c_str());  //输出单分界符/temp="";}}else if(ch=='\\'){temp+=ch;ch=getc(fin);if(strchr(escapeend,ch)>0){temp+=ch;ch=getc(fin);char* ll = escapeend;int l = (strchr(escapeend,ch))-ll;fprintf(fout,"%15d\t%s\n",l+keywordSum+2+40,temp.c_str());}else{fprintf(fout,"%15d\t%s\n",101,temp.c_str());}temp="";}else if(ch=='"'){char ch1;ch1=getc(fin);int flag = 0;while(ch1!='"'&&!flag){temp += ch1;if(ch1=='\n'){flag = 1;}ch1=getc(fin);}if(flag){fprintf(fout,"%15d\t%c\n",102,ch);fprintf(fout,"%15s\t%s\n","ERROR",temp.c_str());ch = ch1;}else if(ch1=='"'){fprintf(fout,"%15d\t%c\n",102,ch);fprintf(fout,"%15s\t%s\n","STRING",temp.c_str());s[s_i] = temp.c_str();s_i++;fprintf(fout,"%15d\t%c\n",102,ch);ch = getc(fin);}temp="";}else{temp += ch;fprintf(fout,"%15s\t%s\n","ERROR",temp.c_str());temp = "";ch=getc(fin);}}fprintf(fout,"%15s\n","标识表");map<int,string>::iterator it;it = f.begin();for (it; it != f.end(); it++)fprintf(fout,"%15d\t%s\n",it->first,it->second.c_str());fprintf(fout,"%15s\n","字符串表");for(int i=100; i<s_i; i++)fprintf(fout,"%15d\t%s\n",i,s[i].c_str());fclose(fin);//关闭输入输出文件fclose(fout);return 0;  //返回主程序}int main(){int es=0;es=cffx();//调词法分析if (es>0)printf("词法分析有错,编译停止!");elseprintf("词法分析成功!\n");}

4.输出的单词表(符号表)

测试数据为:

#include "stdio.h"int main()23.32.5623,321.23,lkjk{int a;float b,sum=0,ave,max=0;for(a=1;a<=10;a++){scanf("%f",&b);printf("The student's achievement is:%f\n",b);//dsfdsfdsfsdfsum+=b;if(b>max) max=b;}ave=sum/10;printf("The average score of these students is:%f\nThe highest scores of these students are:%f\n",ave,max);return 0;"dadasdassda"}/*fsdfdsfsdfsdfsdfsdfdsffdsfsfssfsdfds*/

输出文件:

45    #
              1    include
            102    "
         STRING    stdio.h
            102    "
             15    int
            200    main
             36    (
             37    )
          ERROR    23.32.5623
             41    ,
          FLOAT    321.23
             41    ,
            200    lkjk
             38    {
             15    int
            200    a
             40    ;
             18    float
            200    b
             41    ,
            200    sum
             58    =
            INT    0
             41    ,
            200    ave
             41    ,
            200    max
             58    =
            INT    0
             40    ;
              9    for
             36    (
            200    a
             58    =
            INT    1
             40    ;
            200    a
             67    <=
            INT    10
             40    ;
            200    a
             60    +
             60    +
             37    )
             38    {
            200    scanf
             36    (
            102    "
         STRING    %f
            102    "
             41    ,
             47    &
            200    b
             37    )
             40    ;
            200    printf
             36    (
            102    "
         STRING    The student's achievement is:%f\n
            102    "
             41    ,
            200    b
             37    )
             40    ;
            200    sum
             70    +=
            200    b
             40    ;
              2    if
             36    (
            200    b
             56    >
            200    max
             37    )
            200    max
             58    =
            200    b
             40    ;
             39    }
            200    ave
             58    =
            200    sum
            102    /
            INT    10
             40    ;
            200    printf
             36    (
            102    "
         STRING    The average score of these students is:%f\nThe highest scores of these students are:%f\n
            102    "
             41    ,
            200    ave
             41    ,
            200    max
             37    )
             40    ;
             12    return
            INT    0
             40    ;
            102    "
          ERROR    dadasdas

200    sda
            102    "
          ERROR

39    }
         标识表
              1    main
              2    lkjk
              3    a
              4    b
              5    sum
              6    ave
              7    max
              8    scanf
              9    printf
             10    sda
       字符串表
            100    stdio.h
            101    %f
            102    The student's achievement is:%f\n
            103    The average score of these students is:%f\nThe highest scores of these students are:%f\n

5.实验总结

通过本次实验,我掌握了c++中map的基本使用,对DFA的用处的理解更深了,设计了两个小时,编程时间三个小时,其中调试两个小时(主要是测试用例的对比)。

遇到的难题:词法分析的具体范畴(1.什么是词法分析做的,什么是语法分析做的,2.每个单词属于什么的范畴)。

比如stdio.h,它如果属于标识符就应该在标识符中加入点(.)的判断,但标识符不应该有点,解决:加一个string类型,将stdio.h、双引号内的字符统一识别为字符串,由语法进行处理。

比如23.32.2335,它不应该是一个float类型,它应该报错。解决思路:应读到再界符停止,使用flag,允许至多一个小数点,当有两个及以上小数点或有其他字符时输出错误。

分界符的定义,我将分界符分为了单双两种,单分界符中不包含双分界符的首符,双分界符没有尾符将直接输出首符并输出首符对应的code值。

字符串中转义字符是否需要进行转换,我当前只做了非字符串的转义字符处理。如果需要转化,转义字符处理是一个独立的模块,可以直接在字符串处理中使用。

编译原理 词法分析实验 流程图传不上去,不传了相关推荐

  1. c++实现编译原理词法分析实验(含代码)

    c++实现编译原理词法分析实验(含代码) 一.实验目的: 通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解.并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法. ...

  2. 编译原理词法分析实验

    目录 实验内容描述 实验设计 输入输出形式 样例输入和样例输出 实验设计原理(步骤) 主要函数和辅助函数 核心代码截图 实验结果 可以找我代做,包满分.QQ1975728171可以写完整实验报告 实验 ...

  3. [编译原理]词法分析实验之基于 DFA 的单词识别

    Spring-_-Bear 的 CSDN 博客导航 问题描述: 基于 DFA 的单词识别问题的一种描述是:编写一个程序,输入一个确定的有穷自动机(DFA),使用该 DFA 识别单词. 基本要求: 设置 ...

  4. 编译原理词法分析程序设计

    编译原理词法分析程序设计 1.   课程设计目的: 结合讲授内容,设计与实现一个简单词法分析器,通过设计编制调试一个具体的词法分析程序,加深对词法分析程序的功能及实现方法的理解.并掌握在对程序设计语言 ...

  5. 【SEUSE】编译原理 - 词法分析器实验报告

    [SEU&SE]编译原理 - 词法分析器实验报告 README 一. 实验目的 二. 实验环境 1. 开发环境: 2. 运行环境 三. 实验内容 1. 主要内容 2. 主要功能 3. 种别码 ...

  6. c语言的适当大小的子集,编译原理上机实验报告

    编译原理上机实验报告,编制C语言子集的词法分析程序,编制递归下降法的语法分析程序 编译技术上机实验题目 实验一 一.题目 编制C语言子集的词法分析程序 二.目的 通过设计.编制.调试一个具体的词法分析 ...

  7. 《编译原理》实验教学大纲

    <编译原理>实验教学大纲 课程编号: 773033 课程名称:编译原理 英文名称:Compiler Principle 课程类型: 模块课 学 时:5 学 分:4 适用对象: 软件开发各专 ...

  8. 编译原理 词法分析 算符优先分析法

    编译原理 词法分析 算符优先分析法 实验目的 加深对语法分析器工作工程的理解,加强对算符优先分析法实现语法分析程序的掌握:能够采用一种编程语言实现简单的语法分析程序:能够使用自己辨析的分析程序对简单的 ...

  9. c 语言编写编译原理语义分析实验,北邮 编译原理 语义分析实验报告

    <北邮 编译原理 语义分析实验报告>由会员分享,可在线阅读,更多相关<北邮 编译原理 语义分析实验报告(14页珍藏版)>请在人人文库网上搜索. 1.编译原理第六章 语义分析目 ...

  10. 编译原理:实验一练习

    编译原理:实验一练习 词法分析器 编译原理实验报告 上面的第一个链接中的词法分析器有一点问题,修改后的代码如下: #include "string.h"#include " ...

最新文章

  1. 快速理解JavaScript面向对象编程—原型
  2. Eclipse Collections:让Java Streams更上一层楼
  3. Error: No controllers detected :问题解决
  4. lambda 和 std::function
  5. system流怎么判断为空_并行流ParallelStream中隐藏的陷阱
  6. android 拨打电话与发送短信
  7. WPF:DataGrid可过滤、多语言
  8. delphi 监控文件变化_监控Linux文件变化,防止系统被黑
  9. 【Espruino】NO.06 关键是你的仆人(继续)
  10. 实战BootStrap:利用BootStrap制作全平台响应式站点
  11. 基于python微信群聊机器人开题报告
  12. 音频处理工具 GoldWave / Cool Edit Pro
  13. 回顾微生物学的发展——我们在哪里,我们要去哪里?
  14. 程序人生 | 春风得意马蹄疾,一日看尽长安花
  15. jsp/java智能井盖管理系统
  16. 某博数据挖掘:使用Scrapy构建自定义数据采集提取洞察信息
  17. 如何让笔记获得更多曝光量?小红书曝光机制是怎样的
  18. 基于Ubuntu的esp32编程学习(https://www.bilibili.com/video/BV1wV4y1G7Vk?p=22vd_source=c89885f80e65caacb539e)
  19. xp下对dinput8.dll 游戏键盘输入的模拟 非函数hook
  20. 如何策划新闻稿,低成本实现品牌影响力增长

热门文章

  1. nginx 的基本概念
  2. python爬取淘宝数据遇见的坑
  3. 【JavaScript】 一万字 JavaScript 笔记(详细讲解 + 代码演示 + 图解)
  4. java在线客服系统_JSP在线客服系统
  5. jQuery动画效果
  6. vue禁用浏览器后退
  7. zen cart template zencart模板修改
  8. ◎◎首都机场大巴最新路线时刻表◎◎
  9. NERO刻录ISO镜像图解教程
  10. 基于MATLAB机器视觉技术的水果分级研究进展