编译原理--词法分析

程序流程图

代码实现

// BianYiYuanLi.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <vector>  
#include <string>  
#include <fstream>  
#include <iostream> 
#include <windows.h>

#define SOURCE_FILE_NAME "hello.txt"
#define OUT_FILE_NAME "out.txt"
#define TOKEN_FILE_NAME "token.txt"

#define WORD_NUMBER 68


#define ID 101
#define CONST_INT 102
#define CONST_DOUBLE 103
#define CONST_CHAR 104
#define CONST_BOOL 105

using namespace std;

//全局变量,关键字,全局变量,分界符,算术运算符,关系运算符,根据需要可以自行增加
static string word[] = {
	"auto",
	"break",
	"case",
	"char",
	"const",
	"continue",
	"default",
	"do",
	"double",
	"else",
	"enum",
	"extern",
	"float",
	"for",
	"goto",
	"if",
	"int",
	"long",
	"register",
	"return",
	"short",
	"signed",
	"sizeof",
	"static",
	"struct",
	"switch",
	"typedef",
	"union",
	"unsigned",
	"void",
	"volatile",
	"while",
	"+",
	"-",
	"++",
	"--",
	"*",
	"/",
	"<",
	"<=",
	">",
	">=",
	"=",
	"==",
	"!=",
	";",
	"(",
	")",
	"^",
	",",
	"\"",
	"\'",
	"#",
	"&",
	"&&",
	"|",
	"||",
	"%",
	"~",
	"<<",
	">>",
	"[",
	"]",
	"{",
	"}",
	"\\",
	".",
	"\?",
	":",
	"!"
};

int readFile(IN LPCSTR fileName, IN string& sourceStr) {
	//打开源文件
	ifstream sourceFile(fileName);
	//如果打开失败则退出
	if (!sourceFile.is_open())
	{
		cout << "未成功打开文件" << endl;
		sourceFile.close();
		return -1;
	}
	//临时string
	string temp;
	while (getline(sourceFile, temp))
	{
		sourceStr.append(temp);
		sourceStr += '\n';
	}
	return 0;
}

int saveFile(IN LPCSTR fileName,IN string& sourceStr) {
	//打开输出文件
	ofstream outFile(fileName, ofstream::app);
	//换行
	outFile << endl;
	//输入流
	outFile << sourceStr;
	//关闭文件流
	outFile.close();
	return 0;
}

int filterResource(IN string& sourceStr) {
	string temp;
	for (string::iterator it = sourceStr.begin(); it != sourceStr.end(); it++) {

		//若为单行注释“//”,则去除注释后面的东西,直至遇到回车换行
		if (*it == '/' && *(it + 1) == '/')
		{
			while (*it != '\n')
			{
				it++;//向后扫描
			}
		}
		//若为多行注释“/* 。。。*/”则去除该内容
		if (*it == '/' && *(it + 1) == '*')
		{
			it += 2;
			while (*it != '*' || *(it + 1) != '/')
			{
				it++;//继续扫描
				if (it == sourceStr.end())
				{
					cout << "注释出错,没有找到 */,程序结束!!!\n" << endl;
					exit(0);
				}
			}
			it += 2;//跨过“*/”
		}
		/*若出现无用字符,则过滤;否则加载*/
		if (*it != '\n' && *it != '\t' && *it != '\v' && *it != '\r')
		{
			temp += *it;
		}
	}
	saveFile(OUT_FILE_NAME,temp);
	temp.clear();
	return 0;
}

//判断是否是字母
bool isLetter(char letter)
{
	//C语言允许下划线也为标识符的一部分可以放在首部或其他地方
	if (letter >= 'a'&&letter <= 'z' || letter >= 'A'&&letter <= 'Z' || letter == '_')
	{
		return true;
	}
	else
	{
		return false;
	}
}

//判断是否为数字
bool isDigit(char digit)
{
	if (digit >= '0'&&digit <= '9')
	{
		return true;
	}
	else
	{
		return false;
	}
}

void keywordOrLabelProc(string::iterator& it) {

}

typedef struct TokenItem {
	int number;
	string word;
}TokenItem, *PTokenItem;

void scanner(string& sourceStr) {
	vector<TokenItem> token;

	string temp;
	bool isKeyWord = false;

	//遍历所有字符
	for (string::iterator it = sourceStr.begin(); it != sourceStr.end();)
	{
		if (isLetter(*it))
		{
			//关键字和标记符分析程序
			while (isLetter(*it) || isDigit(*it)) {
				temp += *it;
				it++;
			}
			for (int i = 0; i < WORD_NUMBER; i++)
			{
				if (word[i] == temp) {

					isKeyWord = true;

					TokenItem tokenItem;

					tokenItem.number = i;
					tokenItem.word = temp;

					token.push_back(tokenItem);
					temp.clear();
				}
			}
			//如果不是关键字,则是标记符
			if (!isKeyWord)
			{
				TokenItem tokenItem;

				tokenItem.number = ID;
				tokenItem.word = temp;

				token.push_back(tokenItem);
				temp.clear();
			}

			temp.clear();
			isKeyWord = false;
		}
		else if (isDigit(*it))
		{
			int constType = CONST_INT;

			//常数分析程序
			while (isDigit(*it))
			{
				temp += *it;
				it++;
			}

			if (((*it == '.') && (isDigit(*(it + 1)))))
			{
				constType = CONST_DOUBLE;

				temp += *it;
				it++;
				while (isDigit(*it))
				{
					temp += *it;
					it++;
				}
			}

			TokenItem tokenItem;

			tokenItem.number = constType;
			tokenItem.word = temp;

			token.push_back(tokenItem);
			temp.clear();
		}else if (*it == '+' || *it == '-' || *it == '*' || *it == '/' || *it == ';' || *it == '(' || *it == ')' || *it == '^'
			|| *it == ',' || *it == '\"' || *it == '\'' || *it == '~' || *it == '#' || *it == '%' || *it == '['
			|| *it == ']' || *it == '{' || *it == '}' || *it == '\\' || *it == '.' || *it == '\?' || *it == ':')
		{
			//其他单词分析程序

			string str;
			if (*(it + 1) != '+'&&*(it + 1) != '-'&&*(it + 1) != '='&&*(it + 1) != '&'&&*(it + 1) != '|'&&*(it + 1) != '<'&&*(it + 1) != '>')
			{
				//先判断一个字符的算术运算符和关系云算法
				str += *it;
				for (int i = 0; i < WORD_NUMBER; i++) {
					if (word[i] == str)
					{
						TokenItem tokenItem;

						tokenItem.number = i;
						tokenItem.word = str;

						token.push_back(tokenItem);
					}
				}
			}
			else {
				str += *it;
				str += *(it + 1);
				for (int i = 0; i < WORD_NUMBER; i++) {
					if (word[i] == str)
					{
						TokenItem tokenItem;

						tokenItem.number = i;
						tokenItem.word = str;

						token.push_back(tokenItem);
					}
				}
				it++;
			}
			it++;
			str.clear();
		}
		else {
			it++;
		}
	}

	//输出单词的内部表示
	string saveStr;
	for (TokenItem t : token)
	{
		saveStr += to_string(t.number);
		saveStr += '\t';
		saveStr += t.word;
		saveStr += '\n';
		cout << t.number << " " << t.word << endl;
	}
	//保存token
	saveFile(TOKEN_FILE_NAME, saveStr);
	saveStr.clear();
}

int main()
{
	//存放源文件的string
	string sourceStr;
	//读取源文件
	readFile(SOURCE_FILE_NAME, sourceStr);
	//添加结束标记
	sourceStr += '$';
	//过滤无用的注释
	filterResource(sourceStr);

	sourceStr.clear();
	readFile(OUT_FILE_NAME, sourceStr);

	//saveFile(sourceStr);
	scanner(sourceStr);

	sourceStr.clear();

	return 0;
}

源文件hello.txt

输出去注释文件out.txt

输出token文件,token.txt

项目源文件:https://download.csdn.net/download/a1013642808/10483013

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

至尊小毛毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值