编译原理——词法分析
来源:互联网 发布:cf咪咕刷枪软件 编辑:程序博客网 时间:2024/06/14 21:33
词法分析程序设计
题目
Description
设一语言的关键词、运算符、分界符的个数与单词如下:
struct { int number; string str[10]; }keywords={3,"int","main","return"} ; //关键词struct { int number; string str[10]; }operators ={5,"+","*","=","+=","*="}; //运算符struct { int number; string str[10]; }boundaries ={6,"(",")","{","}",",",";"} ; //分界符struct { int number; string str[100];}identifieres={0}; //标识符struct { int number; string str[100];}Unsigned_integer={0}; //无符号整数
以上类号分别为1~5,序号从0开始;
标识符是字母开头的字母数字串;
常量为无符号整数;
用C++设计一程序实现词法分析。
Input
输入一程序,结束符用”#”
Output
输出单词数对:<类号,序号>。
输出标识符表,用空格分隔;
输出无符号整数表,用空格分隔
Sample Input
main(){ int a=2,b=3; return 2*b+a;}#
Sample Output
<1,1><3,0><3,1><3,2><1,0><4,0><2,2><5,0><3,4><4,1><2,2><5,1><3,5><1,2><5,0><2,1><4,1><2,0><4,0><3,5><3,3>identifieres:a bUnsigned_integer:2 3
解析
词法分析是编译的第一阶段,它的主要任务是扫描输入字符流,产生用于语法分析的词法记号序列。简单的来说,就是通过将字符流翻译成词法记号流。可以看作将一个英文句子划分成一个个单词。
上面的题目是一个简单的词法分析的程序设计题目,只需通过扫描输入的字符串,判断其中字符是否组成符合要求的词法记号,输出对应的类号和序号即可。
解决
#include <iostream> #include <string>#include <vector>using namespace std;// 关键字keyword、operate、boundary的初始化string keyword[3] = {"int", "main", "return"};string operate[5] = {"+", "*", "=", "+=", "*="};string boundary[6] = {"(", ")", "{", "}", ",", ";"};// 用于存储标识符和无符号整数vector<string> identifieres;vector<string> integer;// 函数isIn()主要用于判断字符串temp是否在标识符/无符号整数中,避免temp重复出现在标识符/无符号整数int isIn(string temp, vector<string> in) { int s = in.size(); for (int i = 0; i < s; i++) { if (temp == in[i]) { // 返回temp的index,便于输出其序号 return i; } } // 若temp未在in里面,返回-1作为一个判断 return -1;}// 函数dealString()对输入的字符串进行处理,输出相应的<类号,序号>,并将标识符和无符号整数进行记录void dealString(string temp) { int len = temp.length(); // 循环遍历字符串 for (int i = 0; i < len; i++) { // 由于分界符是单个字节组成,所以先判断temp[i]是否为分界符 if (temp[i] == '(' || temp[i] == ')' || temp[i] == '{' || temp[i] == '}' || temp[i] == ',' || temp[i] == ';') { // 处理boundary,分界符的类号为3 if (temp[i] == '(') cout << "<3,0>"; if (temp[i] == ')') cout << "<3,1>"; if (temp[i] == '{') cout << "<3,2>"; if (temp[i] == '}') cout << "<3,3>"; if (temp[i] == ',') cout << "<3,4>"; if (temp[i] == ';') cout << "<3,5>"; } else if (temp[i] == '+' || temp[i] == '*' || temp[i] == '=') { // 处理operator,运算符的类号为2 if (temp[i + 1] != '=') { if (temp[i] == '+') cout << "<2,0>"; if (temp[i] == '*') cout << "<2,1>"; if (temp[i] == '=') cout << "<2,2>"; } else { if (temp[i] == '+') cout << "<2,3>"; if (temp[i] == '*') cout << "<2,4>"; } } else if (temp[i] >= 'a' && temp[i] <= 'z') { // 区分关键字和标识符 string sub = ""; sub += temp[i]; bool key = false; for(int k = i + 1; k < len; k++) { // 根据标识符的定义:字母+数字组成的字符串,构造子字符串,判断其为关键字还是标识符 if (temp[k] >= 'a' && temp[k] <= 'z') { sub += temp[k]; } else if (temp[k] >= '0' && temp[k] <= '9') { sub += temp[k]; } else { break; } // 关键字的判定,关键字的类号为1 if (sub.length() == 3 && sub == "int") { cout << "<1,0>"; key = true; break; } else if (sub.length() == 4 && sub == "main") { cout << "<1,1>"; key = true; break; } else if (sub.length() == 6 && sub == "return") { cout << "<1,2>"; key = true; break; } } // 该子字符串为标识符,标识符的类号为4 if (!key) { // 判断该标识符是否在之前出现过 int index = isIn(sub, identifieres); if (index == -1) { // 第一次出现,将该标识符添加到identifieres中 identifieres.push_back(sub); cout << "<4," << identifieres.size() - 1 << ">"; } else { // 之前出现过,直接输出其序号 cout << "<4," << index << ">"; } } // 直接跳过组成该标识符/关键字的字符 i += sub.length() - 1; } else if (temp[i] >= '0' && temp[i] <= '9') { // 处理无符号整数,无符号整数的类号为5 string sub = ""; sub += temp[i]; for(int k = i + 1; k < len; k++) { // 无符号整数只由数字组成 if (temp[k] >= '0' && temp[k] <= '9') { sub += temp[i]; } else { break; } } // 判断该无符号整数是否在之前出现过 int index = isIn(sub, integer); if (index == -1) { // 第一次出现,将该无符号整数添加到integer中 integer.push_back(sub); cout << "<5," << integer.size() - 1 << ">"; } else { // 之前出现过,直接输出其序号 cout << "<5," << index << ">"; } } else if (temp[i] == ' ') { // 遇到空格不处理,但是用cin读入输入字符串的话会自动忽略空格 continue; } }}int main() { string temp; int len; bool isEnd = false; while (!isEnd) { cin >> temp; size_t t = temp.find("#"); // 若temp中有“#”,那么t不为空,而“#”是终结输入的标志 if (t != string::npos) { temp = temp.substr(0, t); isEnd = true; } dealString(temp); } cout << endl; // 输出字符串中的标识符 cout << "identifieres:"; for (int i = 0; i < identifieres.size(); i++) { cout << identifieres[i] << " "; } // 输出字符串中的无符号整数 cout << "\nUnsigned_integer:"; for (int i = 0; i < integer.size(); i++) { cout << integer[i] << " "; } cout << endl; return 0;}
阅读全文
0 0
- 编译原理——词法分析
- 编译原理 词法分析
- 编译原理词法分析
- 编译原理 词法分析
- 编译原理词法分析
- 编译原理词法分析
- 编译原理词法分析
- 编译原理 词法分析
- 编译原理--词法分析
- 【编译原理】词法分析
- 编译原理-词法分析
- 编译原理词法分析
- 编译原理—词法分析器
- 编译原理实验一——简单词法分析
- 哈工大编译原理实验1——词法分析
- 编译原理——词法分析(1)
- 编译原理实验----词法分析
- 编译原理词法分析程序
- 1040. 有几个PAT(25)
- redis学习笔记二(常规操作)
- 数据结构实验之图论八:欧拉回路
- 正在进行的激光雷达“世界大战”中,Axetomahawk先行一步
- 12月6日
- 编译原理——词法分析
- Java调用jama实现矩阵运算
- 数据结构实验之图论十:判断给定图是否存在合法拓扑序列
- Spring MVC自定义数据绑定--HandlerMethodArgumentResolver
- Java之二元运算
- 【每日一题(14)】函数F(x) HRBUST
- linux-命令sed 使用技巧
- Django-模型
- 安卓简易理财