编译原理课程即将结束,开始了在校中最麻烦的实验,编译实验......同在一个系,其他班的编译实验分成好几块,简短的文法,
完成一些小功能,就我们班的老师,撂下一句话:参考书本,把编译器实现了,可以一组两人分工合作。
源代码连接:http://download.csdn.net/download/supersmart_dong/10224159
词法分析流程图:
 
首先要做的第一步就是写数据结构以及完成单词表。词法分析的任务就是将一段程序代码,分割单词,把单词信息写出来。
例如在代码: while A<2 do A:=A+1;  中进行词法分析得出来结果,(while,关键字) (A,标识符) (<,算符)(2,整数) (do,关键字) (A,标识符)
(:=,算符) (A,标识符)(+,算符) (1,整数) (;,界符) 将代码中单词一个个的取出来进行分析便是词法分析的任务。输出内容是符号表文件和
token文件。
单词表如下图:

单词

编码

单词

编码

单词

编码

单词

编码

end

1

or

11

21

:=

31

begin

2

program

12

22

=

32

bool

3

real

13

+

23

<=

33

do

4

then

14

-

24

<

34

else

5

true

15

*

25

<>

35

end

6

var

16

/

26

>

36

false

7

while

17

.

27

>=

37

if

8

标识符

18

28

integer

9

整数

19

:

29

not

10

实数

20

30

单词表可以用一维对象数组实现,根据编码或者数组索引来判断该单词是不是关键字还是算符或界符。
之后写一些判断的函数,判断是否是关键字,是否是数字,是否是算符,是否是界符
然后按照流程来,读取文件,一个字符一个字符的读,如果读到第i=0个字符是字母,则读第i+1个,一直读到不是字母或数字为止,
将这i个字符构成一个单词,查询是不是关键字,如果不是则为标识符。如果读到的第i=0个字符是数字,则继续读第i+1个,一直读到不是
字母或数字为止。判断这单词是不是数字(浮点数,整数),如果读到第i=0字符既不是字母也不是数字,则读取下一个字符(记为变量A)和下
两个字符(记为变量B),判断这A或B中有没有算符,判断A是不是界符,如果都不是则为非法字符。像这样读完整个程序结束输出符号表文件。
#include<iostream> #include<string> #include<fstream> #include <cassert> using namespace std; struct WordToken { string name; int code; }; struct WordSymble { string name; // int code; string type; int addr = -1; //符号表位置 int linenum; //行号 }; struct symble { int number; //序号 string type; //类型 string name; //名字 }; #pragma region 单词表 WordToken keyword[] = { { "and", 1 }, { "begin", 2 }, { "bool", 3 }, { "do", 4 }, { "else", 5 }, { "end", 6 }, { "false", 7 }, { "if", 8 }, { "integer", 9 }, { "not", 10 }, { "or", 11 }, { "program", 12 }, { "real", 13 }, { "then", 14 }, { "true", 15 }, { "var", 16 }, { "while", 17 } }; WordToken operatorword[] = { { "+", 23 }, { "-", 24 }, { "*", 25 }, { "/", 26 }, { ">", 31 }, { ":=", 38 }, { "=", 32 }, { "<=", 33 }, { "<", 34 }, { "<>", 35 }, { ">", 36 }, { ">=", 37 } }; WordToken delimeter[] = { { "(", 21 }, { ")", 22 }, { ".", 27 }, { ",", 28 }, { ":", 29 }, { ";", 30 } }; #pragma endregion int iskeyword(string s)//关键字 { int i = 0; if (s != "") { if (((s[0] >= 'A') && (s[0] <= 'Z')) || ((s[0] >= 'a') && (s[0] <= 'z'))) { while (i<17) { if (keyword[i].name == s) { return keyword[i].code; } i++; } return 18; //标识符 } } return -1; } int isoperator(string s)//算符 { int i = 0; if (s != "") { while (i<12) { if (s == operatorword[i].name) { return operatorword[i].code; break; } i++; } } return -1; } int isdelimeter(string s)//界符 { int i = 0; if (s != "") { while (i<6) { if (s == delimeter[i].name) { return delimeter[i].code; break; } i++; } } return -1; } int isdight(string &s, int n)//整数 { int i = 0; int j = 0; string ss; bool a = true; string wrong; while (i< s.length()) { if (j <= 1 && a) { if (s[i] == '.') { j++; } if (((s[i] >= 'A') && (s[i] <= 'Z')) || ((s[i] >= 'a') && (s[i] <= 'z'))) { a = false; } i++; } else { for (int k = 0; k < i - 1; k++) { ss += s[k]; s = ss; } for (int k = i - 1; k < s.length(); k++) { wrong += s[k]; } break; } } if (j == 2 || !a) { cout << "错误行号为" << n + 1 << " "; cout << "错误内容为" << wrong << " "; cout << "错误类型为" << "错误单词" << endl; } if (j == 0) { return 19; } else if (j >= 1) { return 20; } return -1; } int length = 0; extern int line = 0; string word; string text; int k = 0; //wordSysmble个数 1开始 int l = 0; string alltext[100]; WordSymble wss[1000]; symble fuhaobiao[1000]; void get_token() //生成符号表和token { for (; alltext[line] != ""; line++) { text = alltext[line]; length = text.length(); for (int i = 0; i < length; i++) { if (text[i] != ' ') { word = ""; if (((text[i] >= 'A') && (text[i] <= 'Z')) || ((text[i] >= 'a') && (text[i] <= 'z'))) { while (((text[i] >= 'A') && (text[i] <= 'Z')) || ((text[i] >= 'a') && (text[i] <= 'z')) || ((text[i] >= 48) && (text[i] <= 57))) { word += text[i]; i++; } i--; if (iskeyword(word) != -1) { if (iskeyword(word) == 18) { wss[k].name = word; wss[k].code = iskeyword(word); wss[k].type = "标识符"; wss[k].addr = l; wss[k].linenum = line; fuhaobiao[l].name = word; fuhaobiao[l].type = "标识符"; fuhaobiao[l].number = l; l++; k++; } else { wss[k].name = word; wss[k].code = iskeyword(word); wss[k].type = "关键字"; wss[k].linenum = line; k++; } } } else if ((text[i] >= 48) && (text[i] <= 57)) { while (((text[i] >= 48) && (text[i] <= 57)) || (text[i] == '.') || ((text[i] >= 'A') && (text[i] <= 'Z')) || ((text[i] >= 'a') && (text[i] <= 'z'))) { word += text[i]; i++; } i--; int a = isdight(word, line); if (a == 19) { wss[k].name = word; wss[k].code = 19; wss[k].type = "整数"; wss[k].addr = l; wss[k].linenum = line; fuhaobiao[l].name = word; fuhaobiao[l].type = "整数"; fuhaobiao[l].number = l; l++; k++; } else if (a == 20) { wss[k].name = word; wss[k].code = 20; wss[k].type = "浮点数"; wss[k].addr = l; wss[k].linenum = line; fuhaobiao[l].name = word; fuhaobiao[l].type = "浮点数"; fuhaobiao[l].number = l; l++; k++; } } else { word += text[i]; string ss = word; ss += text[i + 1]; if (isoperator(ss) != -1) { word += text[i + 1]; i = i + 1; wss[k].name = word; wss[k].code = isoperator(word); wss[k].type = "算符"; wss[k].linenum = line; k++; } else if (isdelimeter(word) != -1) { wss[k].name = word; wss[k].code = isdelimeter(word); wss[k].type = "界符"; wss[k].linenum = line; k++; } else if (isoperator(word) != -1) { wss[k].name = word; wss[k].code = isoperator(word); wss[k].type = "算符"; wss[k].linenum = line; k++; } else { wss[k].name = word; wss[k].code = 100; wss[k].type = "非法字符"; wss[k].linenum = line; k++; } } } } } } void readtext(string file) { ifstream infile; infile.open(file.data()); //将文件流对象与文件连接起来 assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行 int i = 0; string s; while (getline(infile, s)) { alltext[i] += s; i++; } infile.close(); } void printReadtext(string url = "D: / a.txt") { readtext(url); cout << "程序如下:" << endl; for (int i = 0; alltext[i] != ""; i++) { cout << alltext[i] << endl; } cout << endl; cout << "下面进行词法分析" << endl; cout << endl; get_token(); } void printTokenResult() { int j = 0; cout << endl; while (wss[j].name != "") { cout << "(" << wss[j].name << "," << wss[j].code << "," << wss[j].type << "," << wss[j].addr << "," << wss[j].linenum << ")" << endl; j++; } j = 0; cout << endl; cout << "符号表为" << endl; while (fuhaobiao[j].name != "") { cout << "(" << fuhaobiao[j].number << "," << fuhaobiao[j].name << "," << fuhaobiao[j].type << ")" << endl; j++; } cout << endl; } 
部分输出结果如图所示:

编译实验(一)词法分析相关推荐

  1. 编译原理实验:词法分析

    编译原理实验:词法分析 1. 实验题目:词法分析 实验目的 实验内容 实验要求 输入输出 2. 设计思想 3.算法流程 4. 源程序 5. 调试数据 1. 实验题目:词法分析 实验目的 根据PL/0语 ...

  2. 编译实验(三)目标代码生成

    通过词法分析,语法分析,语义分析,最后产生了四元式.而代码生成则是通过四元式来完成.我们先从简单开始做起. 编译实验项目下载链接:http://download.csdn.net/download/s ...

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

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

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

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

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

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

  6. c语言词法分析程序实验报告,实验一词法分析程序设计与实现

    实验一 词法分析程序设计与实现 一.实验目的: 加深对词法分析器的工作过程的理解:加强对词法分析方法的掌握:能够采用一种编程语言实现简单的词法分析程序:能够使用自己编写的分析程序对简单的程序段进行词法 ...

  7. 编译linux源码报错,记录一次Linux内核源码编译实验

    记录一次Linux内核源码编译实验 文章目录 记录一次Linux内核源码编译实验 0. 实验环境 1. 选择.下载内核源码 2. 安装必要的依赖软件以及性能要求 3. 解压.配置和编译内核源码 3.1 ...

  8. 编译原理画出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 ...

  9. 编译实验1--词法分析

    实验一 词法分析程序 目的和内容 实验目的:通过完成词法分析程序,了解词法分析的过程. 实验内容:用C/C++实现对Pascal的子集程序设计语言的词法识别程序. 实验要求:将该语言的源程序,也就是相 ...

最新文章

  1. 全球公有云巨头:亚马逊 AWS
  2. Java获取当前路径和读取文件
  3. [shiro] - 怎样使用shiro?
  4. C#委托及事件 详解(讲得比较透彻)
  5. 2021-03-12 Python基础核心概念 变量和简单数据类型
  6. BZOJ 1296 粉刷匠(分组背包套DP)
  7. PaddlePaddle开源平台的应用
  8. C语言计算总成绩和平均成绩
  9. 四大经典大数据应用案例解析
  10. html艺术字在线制作,超全的免费图标字体(在线图标字体制作)
  11. mt950报文解析_MT9**报文学习
  12. OpenCV python 轮廓的极值点
  13. 线性代数知识点总结——矩阵乘法、矩阵运算与性质、矩阵微积分
  14. 文件上传漏洞---Web渗透学习
  15. 将MYS_SAM9X5改为dataflash启动
  16. 四步教你用网站源码建站
  17. java天眼培训_Java天眼大型分布式跟踪系统 附带源码_IT教程网
  18. 如何在 R 中计算 Cramer V
  19. 【103期分享】4款小清新PPT模板免费下载
  20. 【注意】加密与解密工具新年大礼包2007光盘提供下载

热门文章

  1. 企业级 SpringBoot 教程 (十七)上传文件
  2. vue2.0 子组件和父组件之间的传值
  3. RESTful API版本控制策略
  4. 使用SSH执行远程登录
  5. spring对JDBC的支持
  6. SpringBatch 读取xml文件(StaxEventItemReader)用法(十三)
  7. 【收藏】wsl2 出现 Vmmem内存占用过大问题解决
  8. linux centos查看CPU型号及物理CPU个数
  9. JavaFX控件ID:设置Label文本内容代码示例
  10. 【好文收藏】k8s中Pod 无法正常解析域名:部署 DNS 调试工具排查