利用c++进行程序词法分析
一、实验目的
实现简单的词法分析程序;
能够使编写的分析程序对简单的程序段进行词法分析
二、实验软硬件要求
相关软件:VC++2010 或者Dev-Cpp,推荐VC++2019
操作系统:windows操作系统
三、实验要求
1. 对单词的构词规则有明确的定义;
2. 编写的分析程序能够正确识别源程序中的单词符号,包括:标识符、关键字、常见运算符、分隔符、整数、小数、单行注释,字符常数,字符串常数;
3. 识别出的单词以<种别码,值>的形式输出或保存;
4. *对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;(由于时间、精力受限,暂不解决)
5. *识别科学计数法数据,多行注释
四、实验内容
自定义一种程序设计语言,或者选择已有的一种高级语言,利用状态转换图编制它的词法分析程序。词法分析程序的实现可以采用任何一种编程工具。
五、实验步骤(程序代码,运行结果等)
//头文件
#include <iostream>
#include <map>
#include <algorithm>
#include <string>#include <fstream>
#include <sstream>
#include <iostream>
#include <stdlib.h>using namespace std;
string instr;//输入符号串
int index;//当前输入符号读入字符的位置
char character;//全局变量字符,存放最新读入的字符
string token;//字符数组,存放已读入的字符序列
const int len = 100;
string Reserve[len];//保留字表
string Boundary[2*len];//界符
string Operator[3 * len];//运算符
struct Binary {Binary(int c,string v="-") {category = c;value = v;}//使用自定义构造函数就能够单独初始化某些变量,而不需要全部变量必须整体赋值。int category; //种别码string value;//值
};
void init_Reserve() {//构造保留字表的函数Reserve[1] = "main";Reserve[2] = "int";Reserve[3] = "if";Reserve[4] = "else";Reserve[5] = "while";Reserve[6] = "for";Reserve[7] = "read";Reserve[8] = "write";Reserve[9] = "bool";Reserve[10] = "break";Reserve[11] = "case";Reserve[12] = "catch";Reserve[13] = "char";Reserve[14] = "class";Reserve[15] = "const";Reserve[16] = "continue";Reserve[17] = "default";Reserve[18] = "delete";Reserve[19] = "do";Reserve[20] = "double";Reserve[21] = "enum";Reserve[22] = "false";Reserve[23] = "true";Reserve[24] = "float";Reserve[25] = "friend";Reserve[26] = "goto";Reserve[27] = "inline";Reserve[28] = "long";Reserve[29] = "new";Reserve[30] = "private";Reserve[31] = "protected";Reserve[32] = "public";Reserve[33] = "return";Reserve[34] = "short";Reserve[35] = "signed";Reserve[36] = "sizeof";Reserve[37] = "static";Reserve[38] = "struct";Reserve[39] = "switch";Reserve[40] = "this";Reserve[41] = "try";Reserve[42] = "typedef";Reserve[43] = "unsigned";Reserve[44] = "using";Reserve[45] = "virtual";Reserve[46] = "void";Reserve[47] = "include";Reserve[48] = "iostream";Reserve[49] = "namespace";Reserve[50] = "std";
}
void init_Operator() {//初始化运算符表Operator[210] = "+";Operator[211] = "-";Operator[212] = "*";Operator[213] = "/";Operator[214] = "<";Operator[215] = "<=";Operator[216] = ">";Operator[217] = ">=";Operator[218] = "!=";Operator[219] = "==";Operator[220] = "=";
}
void init_Boundary() {//界符表初始化Boundary[121] = "(";Boundary[122] = ")";Boundary[123] = ",";Boundary[124] = ";";Boundary[125] = "{";Boundary[126] = "}";Boundary[127] = "#";Boundary[128] = "\'";Boundary[129] = "\"";Boundary[130] = "//";Boundary[131] = "/*";Boundary[132] = "*/";
}
bool isWs(){if(character==' ' || character == '\t' || character =='\n'||character=='\f'||character=='\v'||character=='\0')//已进行补充cfreturn true;elsereturn false;
}
bool isOperator(){//运算符表for(int i=210;i<=220;i++)if(Operator[i][0]==character)return true;return false;
}
bool isBoundary(){//界符表for(int i=121;i<=132;i++)if(Boundary[i][0]==character)return true;return false;
}
void getChar() {//读入一个字符character = instr[index++];
}
void getnbc() {//读入非空白字符while (isWs()) {getChar();//读取空格、tab、换行cf}
}
void concat() {//连接字符串token = token + character;
}bool letter() {//判断是否为字母if ((character >= 'A'&&character <= 'Z') || (character >= 'a'&&character <= 'z'))return true;return false;
}
bool hex(){if ((character >= 'A'&&character <= 'F')||(character >= 'a'&&character <= 'f')|| (character >= '0'&&character <= '9'))return true;return false;
}
bool digit() {//判断是否为数字if (character >= '0'&&character <= '9')return true;return false;
}
void retract(){//回退字符的函数character = ' ';index--;
}
int reserve() {//匹配保留字符for (int i = 0; i < len; i++)if (Reserve[i] == token)return i;return -1;
}int operator1() {//匹配运算符for (int i = 210; i <= 220; i++)if (Operator[i]==token)return i;return -1;
}int boundary() {//匹配界符表for (int i = 121; i <= 132; i++)if (Boundary[i] == token)return i;return -1;
}int digit1() {//匹配整数或浮点型int i=0;while (token[i] != '\0'){if (token[i] == '.')return 800;i++;}return 400;
}bool findstring(string str1,string str2)
{int i = 0;string str3="";for (i = 0; str1[i+1] != '\0'; i++){str3 = str1[i] + str1[i + 1] ;if (str3 == str2){return true;}str3 = "";}return false;
}
Binary error() {cout << token << "\t-->\t该单词不合法" << endl;return Binary(0,"-");
}
//词法分析函数,逐个识别单词
Binary LexAnalyze() {token = "";getChar();getnbc(); //读取到第一个非空白的字符string val;int num = -1;switch (character) {case'a':case'b':case'c':case'd':case'e':case'f':case'g':case'h':case'i':case'j':case'k':case'l':case'm':case'n':case'o':case'p':case'q':case'r':case's':case't':case'u':case'v':case'w':case'x':case'y':case'z':case'A':case'B':case'C':case'D':case'E':case'F':case'G':case'H':case'I':case'J':case'K':case'L':case'M':case'N':case'O':case'P':case'Q':case'R':case'S':case'T':case'U':case'V':case'W':case'X':case'Y':case'Z'://识别关键字、标识符 concat();//追加到token末尾getChar();//读取下一个字符while (letter() || digit()) {//为字母或数字concat();//追加到token末尾getChar();//读取下一个字符}retract();//回退一个字符num = reserve();//查看保留字表,判断是否匹配if (num != -1) {return Binary(num,token);//找到关键字 }else {return Binary(700, token);//不是关键字,那就是标识符 }break;case'*':concat();//追加到token末尾num = operator1();return Binary(num, token);break;case'<':case'>':case'=':case'!':case'+':case'-':case'/'://识别运算符concat();//追加到token末尾getChar();//读取下一个字符if (character == '=')concat(); else retract();num = operator1();//判断单行注释if (token == "/" ){getChar();if (character == '/'){concat();num = boundary();getChar();while (character != '\n'){concat();getChar();}retract();}}//判断多行注释if (token == "/"){if (character == '*'){bool a = true;concat();num = boundary();getChar();string token2 = "*/";while (a) {while (character != '*'&& isWs()){getChar();concat();}getChar();if (character == '/'){concat();a = false;break;}else retract();}}}return Binary(num, token);break;case'(':case')':case',':case';':case'{':case'}':case'#':concat();if (isBoundary()){num = boundary();return Binary(num, token);}break;case '\'':concat();getChar();if(character>='a'&&character<='z'|| character>='A'&& character<='Z')concat();else if (character == '\\'){concat();getChar();if (character == 'n' || character == 't' || character == 'r' || character == '0' || character == '\'' || character == '\"'|| character == '\\'){concat();}}getChar();if (character == '\''){concat();return Binary(500, token);}else retract();num = boundary();return Binary(num, token);break;case '"'://识别字符串常量concat();getChar();while (character != '"'){concat();getChar();}concat();return Binary(600, token);break;case'0'://识别十六进制concat();getChar();if (character == 'x'){concat();getChar();while (hex()){concat();getChar();}retract();return Binary(160, token);}else {while (digit()) {//为数字concat();//追加到token末尾getChar();//读取下一个字符}//识别小数if (character == '.'){concat();getChar();while (digit()){concat();//追加到token末尾getChar();//读取下一个字符}if (character == 'e'){concat();getChar();while (digit()){concat();//追加到token末尾getChar();//读取下一个字符}}}retract();//回退一个字符num = digit1();//查看保留字表,判断是否匹配return Binary(num, token);//找到关键字 }break;case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9'://识别常数单词concat();//追加到token末尾getChar();//读取下一个字符while (digit()) {//为数字concat();//追加到token末尾getChar();//读取下一个字符}//识别小数if (character == '.'){concat();getChar();while (digit()){concat();//追加到token末尾getChar();//读取下一个字符}if (character == 'e'||character=='E'){concat();getChar();while (digit()){concat();//追加到token末尾getChar();//读取下一个字符}}}retract();//回退一个字符num = digit1();//查看保留字表,判断是否匹配return Binary(num, token);//找到关键字 break;case '\\'://识别转义字符concat();getChar();if (character == 'n' || character == 't' || character == 'r' || character == '0'|| character == '\''|| character == '\"'|| character == '\\'){concat();return Binary(500, token);}else {retract();num = boundary();return Binary(num, token);}break;default://遇到无法识别的字符,提示错误信息 concat();return error();}
}
void show_table() {cout << "=================="<<"保留字"<<"==================" << endl;cout << "保留字符\t类别编码" << endl;for (int i = 0; i < len; i++) {if (Reserve[i] != "") {if(Reserve[i].size()>=8)cout << Reserve[i] << "\t" << i << endl;elsecout << Reserve[i] << "\t\t" << i << endl;}}cout << "\n==================" << "界符" << "==================" << endl;cout << "界符\t\t类别编码" << endl;for (int i = 0; i < 2 * len; i++) {if (Boundary[i] != "") {cout << Boundary[i] << "\t\t" << i << endl;}}cout << "\n==================" << "运算符" << "==================" << endl;cout << "运算符\t\t类别编码" << endl;for (int i = 0; i < 3 * len; i++) {if (Operator[i] != "") {cout << Operator[i] << "\t\t" << i << endl;}}
}
//从文件读入到string里
string readFileIntoString(char * filename)
{ifstream ifile(filename);//读文件类的对象,并直接打开//将文件读入到ostringstream对象buf中ostringstream buf;char ch;while(buf&&ifile.get(ch))buf.put(ch);//返回与流对象buf关联的字符串return buf.str();
}int main() {init_Reserve();//保留字表初始化init_Boundary();//界符表初始化init_Operator();//运算符表初始化index = 0;character = ' ';token = "";//文件名char fn1[] = "a.txt";char* fn=fn1;//CONST CHAR类型的值不能用于初始化CHAR类型的实体.cfstring str;str=readFileIntoString(fn);instr = str;cout <<instr<<endl;//输出符号串//识别二元组初始化Binary word(0,"-");//循环进行词法分析直到识别所有单词符号cout << "\n------------------------识别结果------------------------" << endl;while (index < instr.size()) {word=LexAnalyze();if (word.category != 0) {cout << "识别单词:\t(" << word.category << "," << word.value << ")" << endl;}//种别码,值}//展示构造的各种词汇表cout << "\n------------------------词汇表展示------------------------\n" << endl;show_table();system("pause");return 0;
}
程序可以实现标识符、关键字、常见运算符、分隔符、整数、十六进制数、小数、单行注释,多行注释,字符常数,字符串常数、科学计数法数据的识别。
测试文本
/*
飞行荷兰人
*///测试程序1*/
void main()
{0;int a12d=3.6e2;a=3.14;b=576;c=0182976;01234 +056;0+45;d=0xa48d+092;e+=1;int b="hello";a++;sum=a+b;//求两个数之和if(a >b+c)a='a';elsea='\n';
}
测试结果
由于打印出来的篇幅过长,就节选几个比较有代表性的。
利用c++进行程序词法分析相关推荐
- 小程序在wxml里转数字_2020年利用名片小程序开启数字化营销的方法
数字营销是什么意思?所谓数字营销,就是指借助于互联网.电脑通信技术和数字交互式媒体来实现营销目标的一种营销方式.数字营销将尽可能地利用先进的计算机网络技术,以更有效.省钱地谋求新的市场的开拓和新的消费 ...
- [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)...
[.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...
- 利用栈进行程序的括号匹配
利用栈进行程序的括号匹配 程序代码: /** fanchen.cpp : 定义控制台应用程序的入口点.**/#include "stdafx.h" #include <ios ...
- 用C语言用指针怎么算通用定积分,C语言:利用指针编写程序,用梯形法计算给定的定积分实例...
题目要求 利用指针编写程序,用梯形法计算下列公式中的定积分: 参考代码 首先说明一下指针的用处:因为所传递的参数均为数字,并不需要使用指针提高效率,故这里使用指针指向函数. 请注意calc()函数中的 ...
- 指针法算中点坐标c语言,C语言:利用指针编写程序,用梯形法计算给定的定积分实例...
题目要求 利用指针编写程序,用梯形法计算下列公式中的定积分: 参考代码 首先说明一下指针的用处:因为所传递的参数均为数字,并不需要使用指针提高效率,故这里使用指针指向函数. 请注意calc()函数中的 ...
- 利用Pin分析程序的动态行为特征
在程序设计和优化过程中,我们通常希望能有工具帮助我们分析热点代码.覆盖率.内存泄露等这些特性,对多线程程序还希望能分析并发性.竞争和死锁等等.但这些特征通常在静态编译时很难获取,而且往往只能在运行时才 ...
- C语言:利用指针编写程序,用梯形法计算给定的定积分
题目来源:大工慕课 链接 作者:Caleb Sung 题目要求 利用指针编写程序,用梯形法计算下列公式中的定积分: ∫100(x3+12x+1)dx ∫ 0 10 ( x 3 + 1 2 x + 1 ...
- win10c语言关机,技术员win10系统如何利用Shutdown.exe程序定时关机?
我们在使用电脑的时候,有时候需要离开,但是电脑上还有一些操作未完成,如果说能够在这些操作完成后电脑就自动关机是最好的,对此我们可以使用Windows系统中的定时关机功能来实现.下面一起来看看在U深度w ...
- 河南分销小程序开发|分销系统|如何利用分销小程序快速裂变?
社交流量可以说是所有流量获取方式中成本最低的,小程序发展到现在,它本身已经有了巨大的流量爆发力.很多企业抓住这一次的难得的机遇,利用裂变和社群,为企业争取了更多的红利. 除了以上的方法,小程序还有什么 ...
最新文章
- com.android.phone已停止 vivo,oppo,vivo应用程序终止通知不在android fcm中出...
- 交换机基础设置之vtp管理vlan设置
- SAP Pricing的access sequence是如何在循环被处理的
- 解决 VS2019 中.net core WPF 暂时无法使用 Designer 的临时方法
- 转:Node.js和testacular的安装与配置
- 拥塞控制中的开环和闭环控制
- 【linux系统编程】剖析shell运行原理
- 通过json动态创建控制器
- 一句话总结重构、重载、重写
- Android MVP开发模式及Retrofit + RxJava封装
- 全文搜索引擎 Elasticsearch 安装
- 科来网络分析系统2010v7.3.1.2436 激活注册汉化方法
- 环境规制指数,两种测算方法,整理好的面板数据
- 教你一步一步用VPS
- 在固定宽高内显示固定数量的最大正方形
- windows无法完成安装若要在此计算机,windows无法完成安装.若要在此
- linux下编译和安装log4cxx,RedHat如何安装log4cxx日志库
- Python多进程和多线程的使用场景
- liunx下查看tomcat占用的端口号
- 家庭光纤宽带连接示意图
热门文章
- 教你一招如何快速生成微信小程序
- 当初”再小的个体也有自己的品牌“的愿望实现了吗?
- Python中Toplevel
- SDIO wifi Marvell8801/Marvell88w8801 介绍(三) ---- Marvell8801/Marvell88w8801寄存器介绍
- 浅谈电子配线架智能布线管理系统(二)
- 《达利之梦》推出APP,带你走进VR超现实画作
- hihocoder 1272 买零食
- java 过滤http请求头_JAVAWEB开发实现对请求头、请求参数的过滤
- 大数据、趋势与黑天鹅
- 液晶面板价格上涨,中国面板获益巨大,对中国制造产生深远影响