编译原理实验一:单词的词法分析程序设计

编译原理实验一:单词的词法分析程序设计

(注:这是我第一次尝试写博客,也是为了对自己的学习生活的一种记录,写的如果有不好的地方请大家帮忙提出来,我会坚持写下去哒!)

1.1实验内容

目的:

  • 通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

要求:

  • 选择常用高级程序设计语言(如 PL/0语言)的源程序作为词法分析对象。
  • 根据教学要求和学生具体情况,从PL/0语言中选取它的一个适当大小的子集,可以选取一类典型单词,也可以尽可能使各种类型的单词都能兼顾到。其基本要求是:设计出给定程序设计语言的词法规则,以文本文件形式输入源程序,并对源程序从左到右进行扫描,对组成源程序的字符串拼接成为单词;并把其转换成属性字输出到文件中。

1.2实验分析

(刚接触这个实验的时候我觉得是很抽象的东西,可能当时对编译原理的学习也不是很精,但写完之后我发现,这对编译原理的学习还是很有好处的)

经过思考我们可以知道,高级程序设计语言的单词分为如下五类:关键字、标识符、运算符、无符号数、界限符。而本次实验的要求——构造词法分析程序,其主要就是对上述五类单词的识别,说的更详细一点呢,就是该程序要对源程序的一个个字符进行分析,识别出该字符或字符串是属于哪一类的单词,并将结果以二元式的形式输出,以便后续的语法分析等工作。

(好像也没有什么好说的了,那就放两张流程图叭)

总体流程图:
编译原理实验一:单词的词法分析程序设计_第1张图片
无符号数设计流程图:
编译原理实验一:单词的词法分析程序设计_第2张图片

(好了下面就展示一下代码啦,不过在验收的时候发现自己的代码有不足的地方,刚开始的时候思路没想好,导致在进行词法分析的过程中,刚开始对源程序进行预处理的时候,我把所有的空格都去除了,虽然这样在这个小实验中还是能够完成所需要的功能的,但是是一种不好的想法,大家在这部分可以自己思考完善)

1.3实验代码

关键字、界限符、运算符的定义

void Adefine(){
     
	//关键字
	keyword["begin"] = "begin";
	keyword["call"] = "call";
	keyword["const"] = "const";
	keyword["do"] = "do";
	keyword["end"] = "end";
	keyword["if"] = "if"; 
	keyword["odd"] = "odd";
	keyword["procedure"] = "procedure";
	keyword["read"] = "read";
	keyword["var"] = "var";
	keyword["while"] = "while";
	keyword["write"] = "write";
	keyword["then"] = "then";
	//运算符
	keyword["+"] = "plus";
	keyword["-"] = "minus";
	keyword["*"] = "mul";
	keyword["/"] = "div";
	keyword["="] = "eql";
	keyword["<>"] = "neq";
	keyword["<"] = "less";
	keyword[">"] = "greater";
	keyword["<="] = "leq";
	keyword[">="] = "geq";
	keyword[":="] = "becomes";
	//界限符
	keyword["("] = "lparen";
	keyword[")"] = "rparen";
	keyword["["] = "lmiddlebracket";
	keyword["]"] = "rmiddlebracket";
	keyword[","] = "comma";
	keyword[";"] = "semicolon";
	keyword["."] = "period";
}

常数的识别

			int p = 0, j = 0, e = 1;
			word = str[i++];
			while (isdigit(str[i])) {
     
				word += str[i++];
			}
			if (str[i] == '.') {
     
				word += str[i++];
				if (isdigit(str[i])) {
     
					word += str[i++];
					while (isdigit(str[i])) {
     
						word += str[i++];
					}
					if (str[i] == 'e') {
     
						word += str[i++];
						if (str[i] == '-'||((str[i]!='-')&&(str[i]!='+'))) {
     
							word += str[i++];
							if (isdigit(str[i])) {
     
								word += str[i++];
								while (isdigit(str[i])) {
     
									word += str[i++];
								}
								Anode[m].name = "number";
								Anode[m++].word1 = word;
							}
							else {
     
								cout << "error!输入的常数部分错误!e后面应为正数或负数!请检查!	" << endl;
								break;
							}
						}
						else {
     
							word += str[i++];
						}
					}
					else {
     
						Anode[m].name = "number";
						Anode[m++].word1 = word;
					}
				}
				else {
     
					cout << "error!输入的常数部分错误!小数点符号后面应为数字!请检查!" << endl;
					break;
				}
			}
			else if (str[i] == 'e') {
     
				word += str[i++];
				if (str[i] == '-' || ((str[i] != '-') && (str[i] != '+'))) {
     
					word += str[i++];
					if (isdigit(str[i])) {
     
						word += str[i++];
						while (isdigit(str[i])) {
     
							word += str[i++];
						}
						Anode[m].name = "number";
						Anode[m++].word1 = word;
					}
					else {
     
						cout << "error!输入的常数部分错误!e后面应为正数或负数!请检查!" << endl;
						break;
					}
				}
				else {
     
					word += str[i++];
				}
			}
			else if (isalpha(str[i])) {
     
				cout << word<<str[i]<<"标识符错误!" << endl;
				break;
			}
			else {
     
				Anode[m].name = "number";
				Anode[m++].word1 = word;
			}
			i--;

对标识符的识别

			word = str[i];
			i++;
			while (isalpha(str[i]) || isdigit(str[i])) {
     
				word += str[i];
				i++;
			}
			iter = keyword.find(word);
			//判断是否为关键字
			if (iter != keyword.end()) {
     
				Anode[m].name = keyword[word];
				Anode[m].word1 = word;
				m++;
			}
			//否则为标识符
			else {
     
				Anode[m].name = "ident";
				Anode[m].word1 = word;
				m++;
			}
			i--;

这里仅仅给出的是部分的代码,欢迎大家指出问题和不足,我们一起进步。

你可能感兴趣的:(编译原理,程序设计)