失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > SNL语言词法编译器----编译原理课程设计1

SNL语言词法编译器----编译原理课程设计1

时间:2019-09-04 18:37:26

相关推荐

SNL语言词法编译器----编译原理课程设计1

主要思路:从一个文件中,得到一个个的字符,然后对字符进行判断处理,在判断的时候会用到DFA(有限自动机)进行状态之间的转换。

得到的单词主要分为几种类型:标识符、保留字、数字、标点符号、将他们分别进行处理,整理后放在一个token序列中。

token主要由两个部分组成:1)类型 2)内容

程序用到的知识点:

1)C语言文件的读写

举例:

if ((fw = fopen("D:\\jg.txt", "w")) == NULL){printf("文件打开失败\n");exit(1);}else {....}

“w”参数部分是指文件的打开方式为只写

“r”只读

“w+”以读写打开方式打开文件,若无此文件,创建文件

“r+”以读写的方式打开文件,若无此文件,出错

*************************************************************************************************************************************************本代码中使用的文件处理函数:

fgetc(f); //其中f为文件类型指针

ungetc(ch,f);//此函数的作用是将文件类型的指针返回一个位置,char型变量ch,写入这个位置

fprintf(".....",.......); //将内容写入文件中

2)有限自动机的实现

主要是利用 if .....else.....语句进行状态之间的转换。

3)全局变量和容器的使用

容器的库include<vector>

申请一个库:vector<类型>名称

实验环境:VS

#include <stdio.h>#include <stdlib.h>#include <iostream>#include <vector>#include <string>using namespace std;//定义两个表,分别为标识符表和常量表,为全局vector<string>bta;vector<string>cta;int error = 0;//定义一个全局变量用来保存是否这个文件存在词法问题//定义TOKEN结构class Token{public:Token(string str, int i) //构造函数{type = str;id = i;};~Token() {};string type;int id;};class Scan {public:bool reservedLookup(string str);//判断是是否为保留字Token* scanner(FILE *f);int addbta(string str);//查表,若表中含有该标识符返回标识符的id,//否则将该标识符加入表中int addcta(string str);bool Isother(char a);//判断是否为字母和数字以外其他的bool Isletter(char a);bool Isnumber(char a);};bool Scan::reservedLookup(string str) {printf("%s\n", str.c_str());string ta[21] ={ "begin","integer","char","program","array","of","record","end","var","proceduce","if","then","else","fi","while","do","endwh","read","write","return","type" };for (int i = 0; i < 21; i++) {if (str == ta[i]) {cout << "为保留字";printf("%s\n", str.c_str());return true;}}return false;}int Scan::addbta(string str) {for (int i = 0; i < bta.size(); i++) {if (str == bta[i])return i;}//没找到,加入bta.push_back(str);return bta.size() - 1;}int Scan::addcta(string str) {for (int i = 0; i < cta.size(); i++) {if (str == cta[i])return i;}cta.push_back(str);return cta.size() - 1;}bool Scan::Isother(char a) {if (a >= 'A'&&a <= 'Z')return false;if (a >= 'a'&& a <= 'z')return false;if (a >= '0'&& a <= '9')return false;return true;}bool Scan::Isletter(char a) {if (a >= 'A' && a <= 'Z')return true;if (a >= 'a'&& a <='z')return true;return false;}bool Scan::Isnumber(char a) {if (a >= '0' && a <= '9')return true;return false;}Token * Scan::scanner(FILE * f) //用来返回一个Token,然后将其加入到序列中,直到不产生{char ch;string str = "";//初始为空串Token * t = NULL;ch = fgetc(f);if (ch != EOF) {while (ch == ' ' || ch == '\n' || ch == '\t') {ch = fgetc(f);}//去掉所有的空格//根据第一个字母判断各种状态if (Isletter(ch)) //如果第一个字母为英文字母{cout << "进入标识符状态" << endl;str = str + ch;ch = fgetc(f);while (Isletter(ch) || Isnumber(ch)) {cout << "再次进入" << endl;str = str + ch;ch = fgetc(f);}if (Isother(ch)) //再次读入的不是一个字符或者数字{cout << "判断为其他的字符串" << endl;//将指针返回一个ungetc(ch,f);//判断是否为关键字if (reservedLookup(str)) {//如果是保留字,生成一个新的tokenprintf("%s\n", str.c_str());t = new Token(str, -2);return t;}else{//如果为标识符int id = addbta(str);printf("%s\n", str.c_str());t = new Token("标识符", id);return t;}}}if (Isnumber(ch)) {cout << "进入数字状态" << endl;//如果第一个字符为一个数字str = str + ch;ch = fgetc(f);while (Isnumber(ch)){str = str + ch;ch = fgetc(f);}if (Isother(ch)) {ungetc(ch, f);int id = addcta(str);t = new Token("数字", id);printf("%s\n", str.c_str());return t;}}if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' ||ch == ')' || ch == ';' || ch == '[' || ch == ']' || ch == '='){cout << "进入运算符号状态" << endl;str += ch;t = new Token(str, -1);printf("%s\n", str.c_str());return t;}if(ch == ':'){cout << "进入:号状态" << endl;str = str + ch;ch = fgetc(f);if (ch == '=') {str = str + ch;t = new Token(str, -1);printf("%s\n", str.c_str());return t;}else {printf("非法符号 %c \n", ch);error = 1;return NULL;}}if (ch == '{') //注释部分的处理{cout << "进入注释处理状态" << endl;while (ch != '}') {ch = fgetc(f);}t = new Token("zhushi", -4);return t;}if (ch == '.') {cout << "进入数组下届判断状态" << endl;str = str + ch;ch = fgetc(f);if (ch == '.') {str = str + ch;t = new Token("数组下限符", -1);printf("%s\n", str.c_str());return t;}else{return NULL;}}if (ch == ',') {cout << "进入逗号判断状态" << endl;str = str + ch;ch = fgetc(f);if (Isnumber(ch) || Isletter(ch)) {ungetc(ch, f);t = new Token(str, -1);printf("%s\n", str.c_str());return t;}else{str = str + ch;printf("非法符号 %s \n", str);error = 1;return NULL;}}printf("非法符号 %c \n", ch);error = 1;return NULL;}else{return NULL;}}int main(void) {FILE *fp;if ((fp = fopen("D:\\ce.txt", "r")) == NULL) {printf("文件打开失败\n");exit(1);}/*char a;a = fgetc(fp);printf("%c\n", a);cout << "ceshi shifouleyi " << endl;*/Scan * scan = new Scan();vector<Token>t;//本容器用来存储所有的Token序列//申请第一个节点Token *token = NULL;while ((token = scan->scanner(fp))!= NULL){t.push_back(*token);token = NULL;}//关闭文件fclose(fp);//将得到的list中的内容写到一个新的文件中,这个文件由程序生成。需要调用函数int i = 0;//判断是是否有错误if (error == 1) {cout << "有错误" << endl;}else{//第一步打印标识符表printf("打印标识符表\n");for (i; i < bta.size(); i++){printf("%d---%s\n", i, bta[i].c_str());}printf("打印数字表\n");for (i = 0; i < cta.size(); i++){printf("%d---%s\n", i, cta[i].c_str());}printf("打印所有的Token序列\n");for (i = 0; i < t.size(); i++){printf("%d---%s---%d\n", i, t[i].type.c_str(), t[i].id);}}//将所得到的及结果放到一个文件中进行存储//这里需要进行文件的写操作FILE *fw;if ((fw = fopen("D:\\jg.txt", "w")) == NULL){printf("文件打开失败\n");exit(1);}else {for (i = 0; i < t.size(); i++){if (t[i].type != "zhushi") {fprintf(fw, "[%s]---[%d]\n", t[i].type.c_str(), t[i].id);}}}fclose(fw);system("pause");return 0;}

在编写程序过程中遇到的问题:

1.C语言中string类型的输出:

在采用printf或者cout<<进行输出的时候都会出现乱码的现象,但是利用字符串调用.c_str()函数该现象就会消失

原因:printf函数是针对char*的,故要正确显示,通过c_str()返回首地址。

2)VS在使用文件打开或者关闭的时候会出现unsafe错误

处理办法:右键工程名----->属性---->C/C++----->预处理器------>预处理器定义---->在右边的输入框中加入_CRT_SECURE_NO_WARNINGS 然后点击保存。

3)C++中可以使用流的方式读取文件的内容,以getline函数读内容,举例如下:

#include <fstream>char buffer[256];fstream ex("D:\\ce.txt");//注意这个地方一定要是两个\\,否则是识别不出来的if (!ex.is_open()) {cout << "文件打开失败" << endl;exit(0);}while (!ex.eof()) {ex.getline(buffer, 13);cout << buffer << endl;}

4.字符串可以利用+号直接在后面追加 ,或者可以利用append函数(该函数也是将字符加入当当前字串的尾部)

本文章参考资料:/kyt511/article/details/46490845

/zyrblog/p/6885922.html

如果觉得《SNL语言词法编译器----编译原理课程设计1》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。