这是关于编译原理的第一篇文章。

本科阶段的教学与实际操作存在一些脱节的现象。比如词法编辑器你可以完全在不知道什么nfadfa啊之类东西情况下强行摸索出来,而书上和上课讲的却是各种状态转换之类的东西。还要去背因为考试得考。这样堪称上课与书面考试是一套东西,写代码的时候可能是另一套东西。(可能老师认为代码这种东西学生自学就好)。(当然造成这种结论很有可能是本人知识有限的缘故)

介绍:构造一个自定义的小型语言的词法分析程序,程序要求能从文件输入的源程序中对输入的字符串流进行词法分析。

单词种类与词法规则

1 标识符:首字符为字母或下划线,其后由字母、数字或下划线组成;

            注:标识符长度不能超过20个字符。

2 无符号整数:由十进制数字组成的一个序列。首位数字不能为0;

注:无符号整数不带正负号。

③ 保留字:procedure、def、if、else、while、call、begin、end、and、or

            注:保留字不区分大小写。

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

⑤ 双目运算符:<=、  >=、  <>、  ==

⑥  界符:      (   )    ,;

⑦  注释:单行注释和多行注释(注释语法同C语言)。

注:这个词法的规则将会继续在之后的语法等环节沿用。

环境:普通win10,c++语言 直接任意IDE编译运行即可

关于本程序的说明:解析相同目录下的code.txt文件,被分析的代码写在那个文本文件里就好。

#include<iostream>
#include<fstream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>using namespace std;int aa;// fseek的时候用来接着的
string  word="";
string  reserved_word[11];//保留
char buffer;//每次读进来的一个字符
int num=0;//每个单词中当前字符的位置
int line=1; //行数
int row=1; //列数,就是每行的第几个
bool flag; //文件是否结束了
int flag2;//单词的类型//设置保留字
void set_reserve()
{reserved_word[1]="procedure";reserved_word[2]="def";reserved_word[3]="if";reserved_word[4]="else";reserved_word[5]="while";reserved_word[6]="call";reserved_word[7]="begin";reserved_word[8]="end";reserved_word[9]="and";reserved_word[10]="or";
}//看这个字是不是字母
bool judge_word(char x)
{if(x>='a' && x<='z' || x>='A' && x<='Z' ){return true;}else return false;
}//看这个字是不是数字
bool judge_number(char x)
{if(x>='0' && x<='9'){return true;}else return false;
}//看这个字符是不是界符
bool judge_jiefu(char x)
{if(x=='('||x==')'||x==','||x==';'){return true;}else return false;
}//加减乘
bool judge_yunsuanfu1(char x)
{if(x=='+'||x=='-'||x=='*'){return true;}else return false;
}//等于 赋值,大于小于 大于等于,小于等于,大于小于
bool judge_yunsuannfu2(char x)
{if(x=='='|| x=='>'||x=='<'){return true;}else return false;
}//这个最大的函数的总体作用是从文件里读一个单词
int scan(FILE *fp)
{buffer=fgetc(fp);if(feof(fp)){flag=0;return 0;}//cout<<buffer;else if(buffer==' '){row++;return 0;}else if(buffer=='\n'){line++;row=1;return 0;}//如果是字母开头或'_' 看关键字还是普通单词else if(judge_word(buffer) || buffer=='_'){word+=buffer;row++;while((buffer=fgetc(fp)) && (judge_word(buffer) || judge_number(buffer) || buffer=='_')){word+=buffer;row++;}if(feof(fp)){flag=0;return 1;}//这个函数的意义是 因为保留字不区分大小写 要把大写字母全变成小写再比较string temp=word;for(int j=0;j<temp.length();j++){if(temp[j]>='A' && temp[j]<='Z'){temp[j]+=32;}}for(int i=1;i<=10;i++){if(temp==reserved_word[i]){aa=fseek(fp,-1,SEEK_CUR);return 3;}}aa=fseek(fp,-1,SEEK_CUR);return 1;}//开始是加减乘 一定是类型4else if(judge_yunsuanfu1(buffer)){word+=buffer;row++;return 4;}//开始是数字就一定是数字else if(judge_number(buffer)){word+=buffer;row++;while((buffer=fgetc(fp)) && judge_number(buffer)){word+=buffer;row++;}if(feof(fp)){flag=0;return 2;}aa=fseek(fp,-1,SEEK_CUR);return 2;}//检验界符else if(judge_jiefu(buffer)){word+=buffer;row++;return 6;}//检验 <=、  >=、  <>、  == =、 <、>else if(judge_yunsuannfu2(buffer)){row++;word+=buffer;if(buffer=='<')   //为了检验题目中的<> <={buffer=fgetc(fp);if(buffer=='>' || buffer=='='){word+=buffer;row++;return 5;}}//检验  >= ==else{buffer=fgetc(fp);if(buffer=='='){word+=buffer;row++;return 5;}}if(feof(fp)){flag=0;}aa=fseek(fp,-1,SEEK_CUR);return 4;}//首字符是/ 有可能是除号 也有可能是注释else if(buffer=='/'){row++;word+=buffer;buffer=fgetc(fp);//这种情况是除号if(buffer!='*' && buffer !='/'){aa=fseek(fp,-1,SEEK_CUR);return 4;}// 这一行剩下的全被注释了if(buffer=='/'){word.clear();while((buffer=fgetc(fp)) && buffer!='\n' &&!feof(fp)){//真的什么也没有做}if(feof(fp)){flag=0;return 0;}else{aa=fseek(fp,-1,SEEK_CUR);}line++;row=1;return 0;}if(buffer=='*'){bool flag5=1;while(flag5){word.clear();buffer=fgetc(fp);row++;if(buffer=='\n'){line++;row=1;}if(buffer!='*')continue;else {buffer=fgetc(fp);row++;if(buffer=='\n'){line++;row=1;}if(buffer=='/'){flag5=0;}else continue;}if(feof(fp)){flag=0;return 0;}}}}else {word+=buffer;row++;return -1;}
}int main()
{set_reserve();//设置保留字cout<<"introduction"<<endl;cout<<"open "<<"code.txt"<<endl;cout<<"press any key"<<endl;system("pause");flag=1;//ifstream a("需要解析的源代码.txt");FILE *fp;if(!(fp=fopen("code.txt","r"))){cout<<"not found the file or other error "<<endl;flag=0;}while(flag==1){//flag2 返回的类型flag2=scan(fp);//反复调用函数提取单词if(flag2==1){cout<<"type:1 identifier      "<<"line "<<line<<" row "<<row-word.length()<<"  "<<word<<endl;if(word.length()>20)cout<<"ERROR Identifier length cannot exceed 20 characters"<<endl;word.clear();}else if(flag2==3){cout<<"type:3 reserved word   "<<"line "<<line<<" row "<<row-word.length()<<"  "<<word<<endl;word.clear();}else if(flag2==4){cout<<"type:4 unary_operator  "<<"line "<<line<<" row "<<row-1<<"  "<<word<<endl;word.clear();}else if(flag2==2){cout<<"type:2 positive number "<<"line "<<line<<" row "<<row-word.length()<<"  "<<word<<endl;if(word[0]=='0')cout<<"ERROR: The first digit cannot be 0!"<<endl;word.clear();}else if(flag2==6){cout<<"type:6 Separator       "<<"line "<<line<<" row "<<row-1<<"  "<<word<<endl;word.clear();}else if(flag2==5){cout<<"type:6 double_operator "<<"line "<<line<<" row "<<row-2<<"  "<<word<<endl;word.clear();}//非法字符else if(flag2==-1){cout<<"Illegal character      "<<"line "<<line<<" row "<<row-1<<"  "<<word<<endl;word.clear();}}int a=fclose(fp);cout<<"press e to close"<<endl;char end;while(cin>>end && end!='e'){cout<<"只有e可以关闭"<<endl;}return 0;
}

关于代码的分析:

比较困难的地方是反而是文本文件的操作了,本人没有找到关于c++这方面的资料,直接使用了C语言的函数。

而在字符出处理方面又采用了比较省事的string类,导致代码里面c与c++杂糅的情况出现,也说不清是好还是不好了。

这个题目最有技术含量的是这个回退操作

fseek(fp,-1,SEEK_CUR);

 系统总体设计

设置全局变量flag=1,为了读完文本文件,主函数设置一个while(flag)死循环,无限的调用“读一个单词”的功能。

如果读单词的时候文件结束,将flag=0(这个实在都一个单词的函数中实现的,这是这个代码中最大的函数,其实读单词的时候在许多中情况下会遇到文件结束的情况)。

关键数据结构说明

(这些都是全局变量) string word 保存读到的这一个单词,int type 这个词的类型。Line row,表示当前读到的文本文件的位置,调用读单词的功能是会控制这两个变量,(每读了一个字符行就+1,读到一个换行就列+1,行=0)。

关键函数功能说明

 唯一一个最关键的函数就是intscan(FILE *fp) 这个最大的函数的总体作用是从文件里读一个单词,返回值是单词类型。接下来是一些小函数,为了大函数写起来方便。

这是测试数据(被分析的文本文件的内容)

说明,实验测试数据就是一个文件,里面包含了所有种类要求的单词,并且可以提示单词的错误(数字开头是0,字符串过长,非法字符等),2种注释(单行,多行)都可以被跳过。

如图:程序的运行方法:编译之后把需要分析的代码写在同目录下的code.txt里面,运行exe就可以。

这篇文章到这里了,本人认为本次最关键这行代码代表的“回退一个字符”的过程了,剩下的大量代码全是体力劳动。

fseek(fp,-1,SEEK_CUR);

之后还会有语法和中间代码生成等,正在重新敲代码和整理(或者说学也行)中。本篇文章到这里结束谢谢。

编译原理(1)词法分析程序(C++实现)相关推荐

  1. 编译原理中词法分析的递归下降分析法实例--能被5整除的二进制数---c语言实现

    一.前言 又到了一周一度的编译原理实验课,一次实验课上完了,又是大学生必备技能-写实验报告.行了,废话不多说,我直接展现,如何实现编译原理中词法分析的递归下降分析法实例–能被5整除的二进制数的思路.作 ...

  2. 编译原理画出c语言中注释的转化图,编译原理节词法分析DFANFA及其转换.ppt

    编译原理节词法分析DFANFA及其转换 Step4 寻找可合并状态 ε ε 0 1 2 0 5 0 1 6 1 3 4 7 ε ε 0 8 9 1 1 0 10 11 0 0 1 1 1 0 12 1 ...

  3. 编译原理中词法分析--部分实现

    一.前言 某属于在校大学生,几天前老师布置了一个编译原理作业,将词法分析–部分实现,头疼,众所周之,编译原理是计算机专业中最令人头疼的课程,听懂已经很不容易了,TMD让我用C语言实现 ,头大.经过几个 ...

  4. 编译原理 C-Minus词法分析(FLEX)

    C–源代码词法分析 文章目录 C--源代码词法分析 一.实现目标 二.C-Minus语法 三.Flex Flex简介 Flex正则表达式 Flex安装与使用 Flex文件编写 定义 规则 用户代码 四 ...

  5. 编译原理——java 词法分析【有穷自动机实现】

    编译原理--实验1 实验要求 1) 基于词法规则设计词法分析器(20分) 画出确定的有穷自动机(确定化),并提供必要的文字说明.提交状态转换图.doc 2) 词法分析程序的编程实现(80分) (1) ...

  6. 【编译原理】词法分析程序设计(lex)

    编译原理与技术实验一 实验目的: 掌握词法分析程序的设计与实现方法 掌握词法分析的工作内容 实验环境: (1)VMware Workstation 15 Player 虚拟机 (2)Ubuntu 18 ...

  7. 编译原理:词法分析概述

    //放暑假了,大三了.开学就要学编译原理.微机原理.操作系统三门大课qnq //true true beginning 词法分析概述 首先搞清楚词法分析在编译程序中的位置以及作用: 源程序 经过词法分 ...

  8. [编译原理学习]词法分析

    此前一直没能系统完整地学过编译原理,只有很粗浅的理解,虽然其实对工作里的任务也没啥影响,但总觉得缺了一大块知识,加上对所谓程序员三大浪漫(编译器,操作系统,图形学)的向往,所以最近跟着网易云课堂推出的 ...

  9. 编译原理之词法分析、语法分析、语义分析,【精炼总结】

    词法分析和词法分析程序 词法分析阶段是编译过程的第一个阶段.这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号).词法分析 ...

  10. 编译原理:词法分析实验报告

    词法分析实验报告 文章目录 词法分析实验报告 一.实验目的 二.实验原理 三.实验要求 四.实验步骤(利用Java语言来进行词法分析) ① 待分析的语言词法 ② 单词符号对应的种别码 ③ 词法分析程序 ...

最新文章

  1. hdu 5092 线裁剪(纵向连线最小和+输出路径)
  2. Git学习系列之Git的功能特性(从一般开发者的角度和主开发者的角度来剖析)...
  3. “策小编数洞”开工啦,欢迎来唠两块钱儿的
  4. 怎么利用Excel统计各分数段的人数?(亲测sum函数可用)
  5. [转]在Winform(C#)中使用Flash控件
  6. 用ADO.NET的ExecuteScalar方法返回单一值-资讯动态
  7. SRA 练习:解释 CRUD 矩阵方法,并从上面 “用于化学品跟踪管理系统的 CRUDL 矩阵示例”图中找出被遗漏的需求,并解释是如何找的?
  8. Bootstrap表单控件的尺寸
  9. LeetCode(700)——二叉搜索树中的搜索(JavaScript)
  10. python_day24_class_类_继承
  11. win7 64 php5ts.dll,windows7 64位 php5.3安装php_mongo.dll方法
  12. kubernetes中port、target port、node port的对比分析,以及kube-proxy代理
  13. 版权符号模糊解决办法
  14. android - DeviceOwner: Trying to set device owner but device is already provisioned
  15. python中数字加引号和不加引号的区别_高考完小白自学Python,不太懂print语句中一个加引号,一个不加?...
  16. Frequent values POJ - 3368(线段树)
  17. python压缩_Python札记 -- 文件压缩
  18. oracle找回删除的表
  19. 国家非专业等级计算机考试大纲,非计算机专业最新计算机等级考试大纲与试卷.doc...
  20. 【搬运】射手播放器下载字幕存储位置及修改方法

热门文章

  1. 计算机网络与无线通信系统学习1:计算机通信网概述
  2. 计算机小知识——键盘三颗灯含义
  3. 笔记本电脑网络图标丢失解决流程
  4. 微信开发者工具黑屏/打不开解决办法
  5. 整体压缩跟分开压缩哪个更小_2020年新能效发布,美的空调哪个系列好?美的空调推荐...
  6. AutoCAD二次开发多段线分割、添加顶点
  7. docker 创建redis容器
  8. JAVA编写QQ登录界面
  9. 自写:斤与公斤的转化
  10. Silverlight 2学习教程(四)