一、 实验目的

设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、 实验要求

2.1 待分析的简单的词法
(1)关键字:
  • begin if then while do end
  • 所有的关键字都是小写。
(2)运算符和界符
  • : = + - * / < <= <> > >= = ; ( ) #
(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:
  • ID = letter (letter | digit)*
  • NUM = digit digit*
(4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:

表2.1 各种单词符号对应的种别码

单词符号 种别码 单词符号 种别码
begin 1 17
if 2 := 18
then 3 < 20
while 4 <> 21
do 5 <= 22
end 6 > 23
lettet(letter / digit)* 10 >= 24
dight dight* 11 = 25
+ 13 26
14 ( 27
* 15 ) 28
/ 16 # 0
2.3 词法分析程序的功能:

输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:

  • syn为单词种别码;
  • token为存放的单词自身字符串;
  • sum为整型常数;
  • 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:
    (1,begin)(10,x)(18,:=)(11,9)(26, ; )(2,if)……

设计思路:

Judge函数
1.对所给的单词(字符数组)做出判断:

  • 关键字,运算符和界符,标识符(ID),整型常数(SUM):

2.读到的字符串处理方法:
首先判断传入参数的第一个字符,分以下几种情况:

  • 字母开头:判断是否为关键字,是则返回,不是则为标识符
  • 数字开头的判断是否全为数字 是则处理后返回十进制数字大小,不是则返回错误
  • 其他情况直接和运算符表做对比 是则返回运算符,不是则返回错误

3.判断后返回种别码
main()函数

  • 读取文件(待分析的源代码)
  • 从文件中取出一个个独立的单词(以分隔符为界限)
  • 把单词作为参数调用Judge() 返回值对应的种别码
  • 用上述得到的种别码和单词为参数调用print函数,输出结果到文件

Print函数:参数为单词和种别码

  • 写文件模式为追加写(每次在文件末尾写,不覆原有内容)(ios::app)

代码实现:

#include<iostream>
#include <fstream>using namespace std;const int symbolNum =29;
char syn[symbolNum+1][10] { "#","begin","if","then","while","do","end","","","","token","sum","","+","-","*","/" ,":" ,":=","" ,"<" ,"<>" ,"<=" ,">" ,">=" ,"=" ,";" ,"(" ,")" ,"Error!!!"
};char* GetToken() {ifstream In("输入.txt");char* A = new char[10];for (int i = 0; i < 10; i++)A[i] = '\0';In >> A;//cout << "\n读入" << A << endl;In.close();return A;
}bool IsLetter(char a) {if ((a >= 'a' && a <= 'z')|| (a >= 'A' && a <= 'Z'))return 1;else return 0;
}bool IsDigit(char a) {if (a >= '0' && a <= '9')return 1;else return 0;
}int Judge(char Token[]) {char beg = Token[0];if (IsLetter(beg)) {//字母开头for (int i = 0; Token[i] != '\0'; i++)if (!IsDigit(Token[i]) && !IsLetter(Token[i]))return symbolNum;//返回错误for (int i = 0; i < 7; i++) {if (beg == syn[i][0]) {for (int j = 0; Token[j] != '\0'&& syn[i][j] != '\0'; j++) {//for (int j = 0; ; j++) {if (Token[j + 1] != syn[i][j + 1])return 10;//是标识符}return i;//是关键字}}return 10;//是标识符}else if (IsDigit(beg)) {//数字开头for (int i = 0; Token[i] != '\0'; i++) {if (!IsDigit(Token[i]))return symbolNum;//返回错误(数字开头不全为数字)}return 11;//是数字}else {//符号开头if (beg == '#' && Token[1] == '\0')return 0;for (int i = 13; i < symbolNum; i++) {if (beg == syn[i][0]) {bool flag = 1;for (int j = 0; Token[j] != '\0' && syn[i][j] != '\0'; j++) {//for (int j = 0; ; j++) {if (Token[j + 1] != syn[i][j + 1]) {flag = 0;break;}}if(flag)return i;//是运算符}}return symbolNum;//返回错误}
}void C_Print(int id, char* Token) {//输出到文件ofstream Out;Out.open("输出.txt", ios::app);if (id == symbolNum) Out << "Error  ";Out << "(" << id << ",";for (int i = 0; Token[i] != '\0'; i++)Out << Token[i];Out << ")" << endl;Out.close();//以下为输出到控制台if (id == symbolNum)cout << "Error  ";cout << "(" << id << ",";for (int i = 0; Token[i] != '\0'; i++)cout << Token[i];cout << ")" << endl;
}int main() {ifstream In("输入.txt");ofstream Out("输出.txt", ios::trunc);//清除之前的内容while (!In.eof()) {char* A = new char[10];for (int i = 0; i < 10; i++)A[i] = '\0';In >> A;int id = Judge(A);C_Print(id, A); }In.close();//char* T = GetToken();//  int id = Judge(T);//   C_Print(id, T);
}

文件:输出.txt 的内容(随便写的,测试用)

if ( a > 0 )while ( a >= 9 ) :a = a - 1 ;
#
else { if ( b < 987 ) :b ++ ;
} end

输出结果:

//from 输出.txt(2,if)
(27,()
(10,a)
(23,>)
(11,0)
(28,))
(4,while)
(27,()
(10,a)
(24,>=)
(11,9)
(28,))
(17,:)
(10,a)
(25,=)
(10,a)
(14,-)
(11,1)
(26,;)
(0,#)
(10,else)
Error  (29,{)
(2,if)
(27,()
(10,b)
(20,<)
(11,987)
(28,))
(17,:)
(10,b)
Error  (29,++)
(26,;)
Error  (29,})
(6,end)
(19,)

类 Pascal语言词法分析实验(简易版)相关推荐

  1. 基于Python实现的类Pascal语言的词法分析和语法分析器

    类Pascal语言的语法分析器 功能 使用Python实现的类Pascal语言的词法分析和语法分析器. 语法分析实现的功能有: 利用文法推导式构造LR(1)分析表 使用LR(1)分析表对输入的Toke ...

  2. 用类PASCAL语言//实现链表(线性表)

    //用类PASCAL语言//实现链表(线性表) (线性表)顺序结构线性表LA与LB的结点关键字为整数.LA与LB的元素按非递减有序,线性表空间足够大.试用类PASCAL语言给出一种高效算法,将LB中元 ...

  3. 用go语言撸一个简易版的区块链

    用go撸一个简易版的区块链 引言 这个最初的版本时多年以前学习go的时候,自己撸的一个简易版本的区块链.不过麻雀虽小,五脏俱全.通过这个代码你了解区块链内部的大概运行机制时没有问题的. 比特币底层区块 ...

  4. 生产力提升! 自己动手自定义Visual Studio 2019的 类创建模板,制作简易版Vsix安装包...

    序言 最近一直在开发 webApi 接口,为了方便我采用了反Restful风格开发,90%的接口均采用post方式,小部分查询采用Get方式,接口的入参和出参定义每次都需要手动创建2个类,心不累手累, ...

  5. 生产力提升! 自己动手自定义Visual Studio 2019的 类创建模板,制作简易版Vsix安装包

    目录 序言 1.visual studio 扩展 2.建立vs扩展项目 2.建立自己的项模板项目 3.配置vsix包 4. 安装 5.使用 6.体验很好 序言 最近一直在开发 webApi 接口,为了 ...

  6. C语言飞机大战简易版(包含两种界面)

    以下两种代码均适用于初学者: 先上第一种粗糙的代码,讲解都在代码中了. #include<stdio.h> #include<stdlib.h> #include<con ...

  7. 用Java语言,写一个植物大战僵尸简易版!

    前言 有谁没玩过植物大战僵尸吗? 小灰的一位读者,用Java语言开发了自己的植物大战僵尸游戏.虽然系统相对简单,但是麻雀虽小五脏俱全,对游戏开发感兴趣的小伙伴可以学习一下哦~~ 游戏设计 植物大战僵尸 ...

  8. 用 Java 语言,写一个植物大战僵尸简易版!

    作者 | 林Lychee 来源 | 程序员小灰 前言 有谁没玩过植物大战僵尸吗? 小灰的一位读者,用Java语言开发了自己的植物大战僵尸游戏.虽然系统相对简单,但是麻雀虽小五脏俱全,对游戏开发感兴趣的 ...

  9. c语言按给定成绩查询,C语言学生成绩管理系统(简易版)

    #include #include #include int readstudents(struct students stu[]); //读取学生信息 int readsexcode(struct ...

最新文章

  1. C/C++中static关键字用法汇总
  2. python监控mysql数据改变_python3小脚本-监控服务器性能并插入mysql数据库
  3. python显示控制台行情_python命令行查看股票基本行情数据
  4. JavaScript定时器原理及高级使用
  5. ACM入门之【约数】
  6. php lmpl,tjx-cold: 用于根据配置模板,快速生成controller,service,serviceimpl 代码
  7. java实现数字(摘要)签名,生成签名文件,防止文件被人篡改内容,分析和实现
  8. 华为鸿蒙OS合作方,华为发布鸿蒙OS元服务,超300家应用合作伙伴加入
  9. java基础JDK的安装和环境变量的配置
  10. 韩国拟监管加密相关国际汇款,以限制资金流向海外
  11. bat中的[%~dp0]使用
  12. eclipse 点击 ctrl+鼠标左键看不了源码问题解决
  13. NLPIR的语义分析系统
  14. domino生成Excel图表
  15. 大整数除一相对较小的数
  16. python读取文件夹下所有图片并重命名_python 对文件夹下图片 批量重命名
  17. [Bug] Spring相关bug收集
  18. 道与术 渠道以及通信方式的架构设计
  19. Radio RDS简介
  20. 计算机网络基础课后习题,《计算机网络技术基础》课后习题参考答案

热门文章

  1. 大话西游2接收服务器信息失败,新大话西游2 点开始游戏就提示接收服务器数据失败...
  2. html定位 知乎,从零开始:python实现爬取知乎热榜(随缘更新完善)
  3. oracle 公有、私有同义词
  4. 电子器件系列七:看门狗
  5. linux mount 指定用户名,mount命令怎么用?Linux版mount命令完全使用手册
  6. 《Python测试开发技术栈—巴哥职场进化记》—初来乍到,请多关照
  7. [Unity Mirror] 入门
  8. 7.21 给张孝祥老师的第一封信
  9. 鸿蒙系统吃鸡用转区吗,“吃鸡”转区系统正式开放报名,共4条通道,按先后顺序发放!...
  10. Github每日精选:超6k星的开源神器,一键还原百年老电影、黑白旧照片本色