zoukankan      html  css  js  c++  java
  • 词法分析器 (c++实现) 简单实现

    参考种别码

    勿抄,请不要限制你的想象力。

    改进之处:遇到不能识别的应该继续往后识别,功能未完善。
    思路:看代码就懂了;
    Talk is cheap. Show me the code.

    #include <bits/stdc++.h>//万用头文件
    using namespace std;
    //——————————全局变量——————————
    struct Keyword
    {
    	string token;
    	int syn;
    }Key[13];
    
    int syn,tag=1;//种别码,标记
    string token;
    int i = 0;//全局变量作为下标
    //————————————————————————————
    
    bool judletter(char ch)//判断字符
    {
    	if (ch>='A'&& ch<='Z'|| ch >= 'a'&& ch <= 'z')
    		return 1;
    	else
    		return 0;
    }
    
    bool judnum(char num)//判断数字
    {
    	if (num>='0'&&num<='9')
    		return 1;
    	else
    		return 0;
    }
    
    int scan(string input)//对单个字符块进行扫描
    {
    	if (input[i]==' ')//空格
    	{
    		syn = -2;
    		i++;
    		return syn;
    	}
    	token = "";//NULL默认为0,不为空
    
    	if (judnum(input[i]))//数字开头
    	{
    		int sum = 0;
    		while (judnum(input[i]))
    		{
    			sum = 10 * sum + (input[i] - '0');
    			i++;
    			syn = 20;
    		}
    		token += to_string(sum);
    		return syn;
    	}
    	if (judletter(input[i]))//字母开头可能为1、标识符 2、关键字
    	{
    		while (judletter(input[i])||judnum( input[i]))
    		{
    			token += input[i];
    			i++;
    		}
    		syn = 10;//标识符(e.g.变量、常量)
    		for (int j = 1; j <= 12; j++)//
    		{
    			if (token == Key[j].token)
    			{
    				syn = Key[j].syn;
    				return syn;
    			}
    		}
    		return syn;
    	}
    	else //符号
    	{
    		token = "";
    		switch (input[i]) {
    		case'=':
    			syn = 21;
    			i++;
    			token = "=";
    			if (input[i]=='=')
    			{
    				syn = 39;
    				i++;
    				token = "==";
    			}
    			return syn;
    			break;//多余,习惯case+break
    		case '+':
    			syn = 22;
    			i++;
    			token = "+";
    			return syn;
    		case'-':
    			syn = 23;
    			i++;
    			token = "-";
    			return syn;
    		case'*':
    			syn = 24;
    			i++;
    			token = "*";
    			return syn;
    		case'/':
    			syn = 25;
    			i++;
    			token = "/";
    			return syn;
    		case'(':
    			syn = 26;
    			i++;
    			token = "(";
    			return syn;
    		case')':
    			syn = 27;
    			i++;
    			token = ")";
    			return syn;
    		case'[':
    			syn = 28;
    			i++;
    			token = "[";
    			return syn;
    		case']':
    			syn = 29;
    			i++;
    			token = "]";
    			return syn;
    		case'{':
    			syn = 30;
    			i++;
    			token = "{";
    			return syn;
    		case'}':
    			syn = 31;
    			i++;
    			token = "}";
    			return syn;
    		case',':
    			syn = 32;
    			i++;
    			token = ",";
    			return syn;
    		case':':
    			syn = 33;
    			i++;
    			token = ":";
    			return syn;
    		case';':
    			syn = 34;
    			i++;
    			token = ";";
    			return syn;
    		case'>':
    			syn = 35;
    			i++;
    			token = ">";
    			if (input[i] == '=')
    			{
    				syn = 37;
    				i++;
    				token = ">=";
    			}
    			return syn;
    		case'<':
    			syn = 36;
    			i++;
    			token = "<";
    			if (input[i] == '=')
    			{
    				syn = 38;
    				i++;
    				token = "<=";
    			}
    			return syn;
    		case'!':
    			syn = -1;//若只有一个!则报错
    			i++;
    			if (input[i] == '=')
    			{
    				syn = 40;
    				i++;
    				token = "!=";
    			}
    			return syn;
    
    		case'"'://此处仍需改进 ,"也应该作为一个单独单词符号,拥有种别码
    			syn = -1;
    			token += input[i];
    			i++;
    			while (input[i] != '"')
    			{
    				if (input[i] == '#')
    				{
    					tag = 0;
    					break;
    				}
    				else
    				{
    					token += input[i];
    					i++;
    				}
    			}
    			//————————————
    			if (tag)
    			{
    				token += input[i];
    				i++;
    				syn = 50;
    				return syn;
    			}
    			else
    			{
    				syn = -3;
    				return syn;
    			}
    		case '#':
    			syn = 0;
    			return syn;
    			break;
    
    		default:
    			syn = -1;
    			return syn;
    			break;
    		}
    	}
    
    }
    
    void initial()//初始化保留字
    {
    	Key[1] = { "main",1 };
    	Key[2] = { "int",2 };
    	Key[3] = { "char",3 };
    	Key[4] = { "if",4 };
    	Key[5] = { "else",5 };
    	Key[6] = { "for",6 };
    	Key[7] = { "while",7 };
    	Key[8] = { "return",8 };
    	Key[9] = { "void",9 };
    	Key[10] = { "STRING",50 };
    	Key[11] = { "ID",10 };
    	Key[12] = { "INT",20 };
    }
    
    string input()//读取本地文件,code.txt位于本项目cpp存放地,若更改位置则需输入相应地址,
    //注:window的地址和代码地址两个地址符相反/
    {
    	//把全部文件读取放入string a中
    	ifstream in("code.txt", ios::in);
    	istreambuf_iterator<char> beg(in), end;
    	string a(beg, end);//或者string a;a.assign(beg,end);
    	in.close();
    	return a;
    }
    
    void output(string a)//输出,循环在此实现
    {
    	cout << "(种别码,token/sum)" << endl;
    	int syn;
    	do
    	{
    		syn = scan(a);
    		switch (syn)
    		{
    		case -1:
    			cout << "error 非法字符" << endl;
    			syn = 0;
    			break;
    		case -2:
    			break;
    		case -3:
    			cout << "语法错误(引号不全)" << endl;
    			syn = 0;
    		default:
    			cout << "(" << syn << "," << token << ")" << endl;
    		}
    	} while (syn!=0);
    }
    
    int main()
    {
    	initial();//初始化
    	string a = input();//读取文件置入字符串a中,样例把换行读成/n
    	//cout << "请输入以#结尾的字符串" << endl;
    	/*若想cmd内输入,则把input()那一行换成下面这些;
    	string a;
    	//getline(cin,a);
    	*/
    	cout << "读取到的字符串为:" << a << endl;
    	output(a);
    	return 0;
    }
    
    
  • 相关阅读:
    Windows上使用“LogView”打开大文件
    windows CMD命令查看局域网内所有主机名及IP
    解决Sqlserver 2008 R2在创建登录名出错"此版本的 Microsoft Windows 不支持 MUST_CHANGE 选项。 (Microsoft SQL Server,错误: 15195)"
    解决 ASP.NET 编辑错误"CS0006: 未能找到元数据文件C:WINDOWSassemblyGAC_32System.EnterpriseServices2.0.0.0__b03f5f7f11d50a3aSystem.EnterpriseServices.dll"
    ASP 未结束的字符串常量
    Godaddy ssl续费更新问题总结
    [转]How to query posts filtered by custom field values
    SqlServer 在查询结果中如何过滤掉重复数据
    [UE4]C++的const类成员函数
    [UE4]C++三种继承方式
  • 原文地址:https://www.cnblogs.com/gidear/p/14198340.html
Copyright © 2011-2022 走看看