编译原理-词法分析

实验内容

通过对PL/0词法分析程序(GETSYM)的分析,并在此基础上按照附录A中给出的PL/0语言的语法描述,编写一个PL/0语言的词法分析程序。此程序应具有如下功能:
输入为字符串(待进行词法分析的源程序),输出为单词串,即由(单词、类别)所组成的二元组序列。
有一定检查错误的能力,例如发现2A这类不能作为单词的字符串。

实验代码如下:

#include <bits/stdc++.h>
using namespace std;

bool key_words(string s)//关键字
{
    static vector<string> keyVec = { "main", "int", "float", "double", "char",
        "if", "then","else", "switch", "case", "break", "continue", "while",
        "do", "for" ,"#include","using","namespace","std","return"};
    vector<string>::iterator result = find(keyVec.begin(), keyVec.end(),s);
    if (result != keyVec.end())
        return true;
    else return false;
}
bool ident(string s)//标识符
{
    if (!key_words(s))//标识符不能是关键字
    {
        if ((s[0] >= 'a'&&s[0] <= 'z') || (s[0] >= 'A'&&s[0] <= 'Z'))//是字母
        {
            for (int i = 1; i < s.length(); i++)
            {
                if ((s[i] >= 'a'&&s[i] <= 'z') || (s[i] >= 'A'&&s[i] <= 'Z')
                    || (s[i] >= '0'&&s[i] <= '9'))
                    continue;
                else return false;
            }
            return true;
        }
        return false;
    }
    return false;
}

bool digit(string s)//整数
{
    if (s[0] >= '0'&&s[0] <= '9')
    {
        for (int i = 1; i < s.length(); ++i)
            if (s[i] >= '0'&&s[i] <= '9')
                continue;
            else return false;
        return true;
    }
    return false;
}

bool points(string s)//小数
{
    if (s[0] >= '0'&&s[0] <= '9')
    {
        for (int i = 1; i < s.length(); ++i)
            if ((s[i] >= '0'&&s[i] <= '9')||s[i]=='.')
                continue;
            else return false;
        return true;
    }
    return false;
}

bool is_operator(string s)//运算符
{
    static vector<string> opeVec = { "=","+","-","*","/","<","<=","==","!=",
        ">",">=",";","(",")","?",":",",","+=","-=" };
    vector<string>::iterator result = find(opeVec.begin(), opeVec.end(), s);
    if (result != opeVec.end())
        return true;
    else return false;
}

bool is_operator(char c)//运算符
{
    static vector<char> opeVec = { '=','+','-','*','/','<','>',';','(',')','?',':',',' };
    vector<char>::iterator result = find(opeVec.begin(), opeVec.end(), c);
    if (result != opeVec.end())
        return true;
    else return false;
}

string result(string s)//根据传入的参数s产生对应的输出
{
    //标识符
    if (ident(s))
        return "(标识符,"+s+")";

    //关键字
    if (key_words(s))
        return "(关键字,"+s+")";

    //整型常量
    if (digit(s))
        return "(整数,"+s+")";

    //小数
    if (points(s))
        return "(小数,"+s+")";

    //运算符
    static map<string, string> opeMap;
    opeMap["="] = "(等号,=)";
    opeMap["<"] = "(小于号,<)";
    opeMap["<="] = "(小于等于号,<=)";
    opeMap["+="] = "(加等于号,+=)";
    opeMap["-="] = "(减等于号,-=)";
    opeMap["=="] = "(赋值运算符,==)";
    opeMap["!="] = "(不等于号,!=)";
    opeMap[">"] = "(大于号,>)";
    opeMap[">="] = "(大于等于号,>=)";
    opeMap[";"] = "(分号,;)";
    opeMap["+"] = "(加号,+)";
    opeMap["("] = "(左括号,( )";
    opeMap["-"] = "(减号,-)";
    opeMap[")"] = "(右括号,) )";
    opeMap[">"] = "(大于号,>)";
    opeMap["*"] = "(星号,*)";
    opeMap["?"] = "(问号,?)";
    opeMap["/"] = "(除号,/)";
    opeMap[":"] = "(冒号,:)";
    opeMap[","] = "(逗号,,)";
    if (is_operator(s))
        return opeMap[s];
    return "Error";
}

int main()
{
    string file = ("C:\\test.txt");
    ifstream input(file);

    ofstream output("C:\\Result.txt",ofstream::app);
    //先将testData.txt内容拷贝到Result.txt中
    string copy;

    getline(input, copy, '\0');
    cout<< copy << endl;//测试是否正确

    //此时input已经指到了文件尾,为了后面的读取,需要关闭再打开
    input.close();
    input.open(file);

    output << "原数据:\n";
    output << copy;
    output << "处理后结果:\n";

    string str;
    string words;

    cout << "处理后结果:\n";
    int l=0;//计算行数
    while (getline(input, str)) //读取文件每一次读取一行,遇到EOF结束
    {
        l++;
        //从输入流中获取单词,需要用到输入流对象,即istringstream
        istringstream strCin(str);
        string s;
        while (strCin >> words)
        {
            //关键字肯定是单独作为一个单词的
            if (key_words(words))
            {
                s = result(words);
                cout <<"Line "<<l<<":"<< s << endl;
                output <<"Line "<<l<<":"<< s << endl;
                continue;
            }

            //对单词进行扫描,肯定是标识符,运算符,逗号分号,数字等等混合在一起的单词
            vector<int> index = {0};
            vector<string> mulWords;//将words分解为多个单词
            for (int i = 0; i < words.length(); i++)
            {

                //运算符有两位的,比如"<=",">=","==","!=","-=","+="
                if ((i < words.length() - 1) && is_operator(words[i]) && is_operator(words[i + 1]))
                {
                    //但是要注意只有以上6种两位运算符,比如+-,))就不是,但是))还是要输出),)
                    if (string(words.begin() + i, words.begin() + i + 2) == "<=" ||
                        string(words.begin() + i, words.begin() + i + 2) == ">=" ||
                        string(words.begin() + i, words.begin() + i + 2) == "==" ||
                        string(words.begin() + i, words.begin() + i + 2) == "-=" ||
                        string(words.begin() + i, words.begin() + i + 2) == "+=" ||
                        string(words.begin() + i, words.begin() + i + 2) == "!=")
                    {
                        index.push_back(i);
                        index.push_back(i + 2);
                        ++i;
                    }
                    else if (is_operator(words[i]))
                    {
                        if (find(index.begin(), index.end(), i) == index.end())
                            index.push_back(i);
                        if (find(index.begin(), index.end(), i + 1) == index.end())
                            index.push_back(i + 1);

                    }
                }
                //逗号,运算符作为分隔
                 else if (is_operator(words[i]))
                {
                    if (find(index.begin(), index.end(), i) == index.end())
                    //比如遇到"a,b"这里下标0和1将a分开,1到2将逗号分开,2到3将b分开
                        index.push_back(i);
                    if (find(index.begin(), index.end(), i+1) == index.end())
                        index.push_back(i + 1);
                }

            }
            for (int i = 0; i < index.size()-1; i++)
            {
                string rel;
                //比如遇到"<=",需要提取”<=“
                rel=result(string(words.begin() + index[i], words.begin() + index[i + 1]));

                output <<"Line "<<l<<":"<< rel << endl;
                cout <<"Line "<<l<<":"<< rel<<endl;
            }
        }
    }
    output << endl;
    output.close();
    input.close();
    system("pause");
    return 0;
}

实验结果:

测试数据:
#include < iostream >
using namespace std;
int main(){
int 2b, a = 10;
double b = -20.9;
if(a<=b)
a+=b;
else
a=34b+5;
return a;
}

输出数据:
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值