合工大 编译原理 实验1

用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
在这里插入图片描述

#include <iostream>
#include <string.h>
#include <vector>
#include <utility>
using namespace std;
string key[] = { "if", "while", "for", "else","then","do","return" };     //第一类 关键词
char boundary[] = { '[',']',')','(',';' };         //第二类 分节符
char acc[] = { '+','-','*','/'};                   //第三类 算数运算符
string relation[] = { ">=","<=" ,">","<","=","==" }; //第四类 关系运算符
                                                     //第五类常数 第六类标识符
vector<string> ident;  //变量保存
//结果保存
vector<string> word;
vector<pair<int, string>> attribute;
vector<string> type;
vector<pair<int, int>> loc;

bool isDigtal(char a) {
	if (a >= '0' && a <= '9')
		return true;
	else return false;
}

bool isLetter(char a) {
	if (a >= 'a' && a <= 'z')
		return true;
	else return false;
}

bool isChe(char a) {
	if (a == '\n')
		return true;
	else return false;
}

bool isKey(string s) {
	for (int i = 0; i < 7; i++) {
		if (strcmp(s.c_str(), key[i].c_str()) == 0) {
			return true;
		}
	}
	return false;
}
bool isBound(char a) {
	for (int i = 0; i < 5; i++) {
		if (a == boundary[i]) {
			return true;
		}
	}
	return false;
}
bool isAcc(char a) {
	for (int i = 0; i < 4; i++) {
		if (a == acc[i]) {
			return true;
		}
	}
	return false;
}
void LexicalAnalysis(string s) {
	int row = 1, col = 1;
	int len = s.length();
	int i = 0;
	while (i < len) {
		if (isLetter(s[i])) {
			string tmp = "";
			while (isDigtal(s[i]) || isLetter(s[i])) {
				tmp += s[i];
				i++;
			}
			if (isKey(tmp)) {
				word.push_back(tmp);
				attribute.push_back(make_pair(1, tmp));
				type.push_back("关键字");
				loc.push_back(make_pair(row, col));
				col++;
			}
			else {
				int flag = 0;
				for (int j = 0; j < ident.size(); j++) {
					if (strcmp(tmp.c_str(), ident[j].c_str()) == 0) {
						flag = 1;
					}
				}
				if (!flag) {
					ident.push_back(tmp);
				}
				word.push_back(tmp);
				attribute.push_back(make_pair(6, tmp));
				type.push_back("标识符");
				loc.push_back(make_pair(row, col));
				col++;
			}
		}
		else if (isChe(s[i])) {
			row++;
			col = 1;
			i++;
		}
		else if (isDigtal(s[i])) {
			string tmp = "";
			while (isDigtal(s[i])) {
				tmp += s[i];
				i++;
			}
			if (isBound(s[i]) || s[i] == ' ') {
				word.push_back(tmp);
				attribute.push_back(make_pair(5, tmp));
				type.push_back("常数");
				loc.push_back(make_pair(row, col));
				col++;
			}
			else {
				while (isLetter(s[i]) || isDigtal(s[i])) {
					tmp += s[i];
					i++;
				}
				word.push_back(tmp);
				attribute.push_back(make_pair(7, tmp));
				type.push_back("ERROR");
				loc.push_back(make_pair(row, col));
				col++;
			}
		}
		else if (isBound(s[i])) {
			string tmp = "";
			tmp += s[i];
			word.push_back(tmp);
			attribute.push_back(make_pair(2, tmp));
			type.push_back("分界符");
			loc.push_back(make_pair(row, col));
			col++;
			i++;
		}
		else if (s[i] == '>' || s[i] == '<' || s[i] == '=') {
			string tmp = "";
			tmp += s[i];
			i++;
			if  (s[i] == '=') {
				tmp += s[i];
				i++;
			}
			word.push_back(tmp);
			attribute.push_back(make_pair(4, tmp));
			type.push_back("关系运算符");
			loc.push_back(make_pair(row, col));
			col++;
		}
		else if (isAcc(s[i])) {
			string tmp = "";
			tmp += s[i];
			i++;
			if (isLetter(s[i]) || isDigtal(s[i])) {
				word.push_back(tmp);
				attribute.push_back(make_pair(3, tmp));
				type.push_back("算数运算符");
				loc.push_back(make_pair(row, col));
				col++;
			}
			else {
				while (s[i] != ' ' && !isBound(s[i])) {
					tmp += s[i];
					i++;
				}
				word.push_back(tmp);
				attribute.push_back(make_pair(7, tmp));
				type.push_back("ERROR");
				loc.push_back(make_pair(row, col));
				col++;
			}
		}
		else if (s[i] == ' ' || s[i] == '\n') {
		i++;
		}
		else {
			string tmp = "";
			while (s[i] != ' ' && !isBound(s[i])) {
				tmp += s[i];
				i++;
			}
			word.push_back(tmp);
			attribute.push_back(make_pair(7, tmp));
			type.push_back("ERROR");
			loc.push_back(make_pair(row, col));
			col++;
		}
	}
}
int main() {
	string s = "if i=0 then n++;\na<=b3%);\n342342;\njfksjf+jgf3;dfsf459834jifsdjfw;";
	cout << s << endl;
	LexicalAnalysis(s);

	for (int i = 0; i < word.size(); i++) {
		cout << word[i] << "  (" << attribute[i].first << "," << attribute[i].second << ")  " << type[i] << "  (" << loc[i].first << "," << loc[i].second <<")"<< endl;
	}
	return 0;
}
  • 11
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
哈尔滨工业大学威海编译原理实验是指学生在编译原理课程中进行的实践性学习活动。通过该实验,学生们能够深入了解编译原理的基本概念和原理,并通过实际操作来加深对编译器的理解。 实验内容主要包括以下几个方面:词法分析、语法分析、语义分析和中间代码生成。在词法分析部分,学生需要根据给定的文法和词法规则,编写词法分析器,将输入的源代码分解成一个个的单词符号。在语法分析部分,学生需要设计并实现一个语法分析器,对分解出来的单词符号进行分析,判断其是否符合语法规则。在语义分析部分,学生需要对上一步得到的语法树进行静态分析,检查语义错误并进行相应的处理。在中间代码生成部分,学生需要将语法树转化成中间代码,为后续的优化和目标代码生成做好准备。 为了完成这个编译原理实验,学生通常需要利用计算机编程语言如C++或Java等实现所需的算法和数据结构,并进行调试和测试。此外,学生还需要熟悉相关的编译工具和库,如Lex和Yacc等。通过实践操作,学生们能够更好地理解编译器的工作原理,并培养自己的编程和分析能力。 总之,哈尔滨工业大学威海编译原理实验是一个培养学生编译器设计和实现能力的重要实践环节,通过实验,学生们能够将课堂理论知识转化为实际应用能力,并为以后的研究和职业发展奠定坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值