编译原理——词法分析

来源:互联网 发布: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;}