编译原理之基于自动机的词法分析器的设计与实现

一、实验目的

设计与实现一个词法分析器,加深对词法分析原理的理解。

二、实验内容

需要实现的功能:

1)输入:源程序字符串,源程序存储在文本文件中(编码格式ANSI),文件名作为命令行参数输入;

2)输出:输出token序列到标准输出设备。

三、实验要求

语言的词法:

1、关键字

main

if then else

while do

repeat until

for from to step

switch of case default

return

integer real char bool

and or not mod

read write

所有关键字都是小写。

2、专用符号

运算符包括:=、+、-、*、/、<、<=、>、>=、!=

分隔符包括:,、;、:,{、}、[、]、(、)

3、其它标记ID和NUM

通过以下正规式定义其它标记:

ID ® letter(letter | digit)*

NUM ® digit digit*

Letter ® a | ... | z | A | ... | Z

Digit ® 0|...|9

4、空白格由空格、制表符和换行符组成

空白一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。

四、实验设计

五、奉上代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

string code;

unordered_map<string, int> word = {
{"main",1}, {"if",2}, {"then",3}, {"while",4},{"do",5},{"static",6},{"ID",25},{"NUM",26},{"+",27},
{"-",28},{"*",29},{"/",30},{":",31},{":=",32},{"<",33},{"<>",34},{"<=",35},{">",36},{">=",37},{"=",38},
{"default",39},{"define",40},{";",41},{"(",42},{")",43},{"{",44},{"}",45},{"int",7},{"double",8},{"struct",9},{"break",10},
{"else",11},{"long",12},{"switch",13},{"case",14},{"typedef",15},{"char",16},{"return",17},{"const",18},
{"float",19},{"short",20},{"continue",21},{"for",22},{"void",23},{"sizeof",24},{"#",0}	
};

map<string,int> token; 

void wordAnalysis(){
	
	int s=0;
	
	while(s<code.length()){
		
		//去除空格、制表符、和换行符
		if(code[s]==' '||code[s]=='\n'||code[s]=='\t'){ 
			s++;	
			continue;
		}
		
		if(code[s]=='/'&&s+1<code.length()&&code[s+1]=='/'){
			//去除单行注释
			s+=2;
			
			while(s<code.length()&&code[s]!='\n'){
				s++;
			}
			
			continue;
		}
		
		if(code[s]=='/'&&s+1<code.length()&&code[s+1]=='*'){
			//去除多行注释
			s+=3;
			
			while(s<code.length()&&(code[s-1]!='*'||code[s]!='/')){
				s++;
			}
			
			continue;
		}
		
		if(isalpha(code[s])||code[s]=='_'){
			//识别标识符和关键字
			string temp;
			temp+=code[s];
			
			s++;
			
			while(s<code.length()&&(isalpha(code[s])||code[s]=='_'||isdigit(code[s]))){
				temp+=code[s];
				s++;				
			}
			
			if(word.count(temp))
			token[temp]=word[temp];
			else
			token[temp]=word["ID"];
			
			continue;
		}
		
		if(isdigit(code[s])){
			
			string temp;
			temp+=code[s];
			//识别普通数字
			s++;
			
			while(s<code.length()&&isdigit(code[s])){
				temp+=code[s];
				s++;
			}
			
			if (s < code.length() && code[s] == '.') {
                temp += code[s];  // 识别浮点数
                s++;

                while (s < code.length() && isdigit(code[s])) {
                    temp += code[s];
                    s++;
                }

                token[temp] = word["NUM"]; 
            }
			
			else if(s<code.length()&&(isalpha(code[s])||code[s]=='_')){
				//识别错误的以数字开头的标识符
				temp+=code[s];
				s++;
				
				while(s<code.length()&&(isalpha(code[s])||code[s]=='_'||isdigit(code[s]))){
					temp+=code[s];
					s++;				
				}
					
				token[temp]=-1;
			}else{
				token[temp]=word["NUM"];
			}
			
			continue;
		}
		
		string temp(1,code[s]);
        if (word.count(temp)) {
            // 检查双字符操作符
            if ((temp == ":" || temp == "<" || temp == ">") && s + 1 < code.length()) {
                string twoChar = temp + code[s + 1];
                if (word.count(twoChar)) {
                    token[twoChar] = word[twoChar];
                    s += 2; // 跳过两个字符
                    continue;
                }
            }

            token[temp] = word[temp];
            s++; // 跳过单字符
        } else {
        	token[temp]=-1;
            s++; 
        }		
			
	}
}

int main(){
	
	ifstream file("C:\\Users\\24775\\Desktop\\test.txt");
	
	if(!file){
		cout<<"file read error!"<<endl;
	}
	
	string line;
	//文件读取
	while(getline(file, line)){
		code+=line;
		code+='\n';
	}
	
	cout<<code;
	
	file.close();
	
	wordAnalysis();
	//打印词法分析后的token
	for(auto i : token){
		if(i.second!=-1)
		cout<<"token: "<<i.first<<" "<<"syn: "<<i.second<<endl;
		else
		cout<<"token: "<<i.first<<" "<<"Invalid Token !!!"<<endl;
	}

	return 0;
}

测试代码:

输出结果:

相关推荐
序属秋秋秋8 小时前
《Linux系统编程之进程环境》【环境变量】
linux·运维·服务器·c语言·c++·操作系统·系统编程
Aileen_0v08 小时前
【Gemini3.0的国内use教程】
android·人工智能·算法·开源·mariadb
CoderYanger8 小时前
C.滑动窗口——1423. 可获得的最大点数
java·开发语言·算法·leetcode·1024程序员节
乌萨奇也要立志学C++8 小时前
【洛谷】二分查找专题 告别二分死循环!模板 + 细节 + 实战
c++·算法
Rock_yzh8 小时前
LeetCode算法刷题——128. 最长连续序列
数据结构·c++·算法·哈希算法
WolfGang0073218 小时前
代码随想录算法训练营Day32 | 518.零钱兑换II、377. 组合总和 Ⅳ、70. 爬楼梯(进阶)
算法
wheeldown8 小时前
【Rokid+CXR-M】基于Rokid CXR-M SDK的博物馆AR导览系统开发全解析
c++·人工智能·ar
利刃大大9 小时前
【c++中间件】语音识别SDK && 二次封装
开发语言·c++·中间件·语音识别
晨非辰9 小时前
C++ 波澜壮阔 40 年:从基础I/O到函数重载与引用的完整构建
运维·c++·人工智能·后端·python·深度学习·c++40周年
艾莉丝努力练剑12 小时前
【C++:C++11】C++11新特性深度解析:从可变参数模板到Lambda表达式
c++·stl·c++11·lambda·可变模版参数