zoukankan      html  css  js  c++  java
  • 编译原理系列 实验四语义分析与中间代码生成

    最后一次实验!

    实验四 语义分析与中间代码生成

    实验目的

    • 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。
    • 掌握目前普遍采用的语义分析方法──语法制导翻译技术。
    • 给出 PL/0 文法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。

    题目

    【问题描述】
    在实验二或实验三的表达式语法分析程序里,添加语义处理部分。 对于语法正确的表达式,输出其中间代码,用四元式序列表示;对于语法正确的算术表达式,输出其计算值。例如:当输入为2+35时,程序输出为17;当输入为a(b+c)时,程序输出为四元式:
    (+,b,c,t1)
    (,a,t1,t2)
    要求源程序能智能判断这两种情况,并输出相应结果。
    【输入形式】
    (1) PL/0算术表达式的语义计算。PL/0算术表达式,例如:2+3
    5作为输入。
    (2)PL/0表达式的中间代码表示。输入:PL/0表达式,例如: a*(b+c)。

    【输出形式】
    2+35作为输入时,输出为17
    a
    (b+c)作为输入时,输出为
    (+,b,c,t1)
    (*,a,t1,t2)

    源程序

    #include <iostream>
    #include<bits/stdc++.h>
    
    using namespace std;
    
    /**词法分析及其结果存储**/
    pair<string, string> lexRes[50]; // 词法分析结果,每个pair的first如"ident",second如"a"
    int lexI = 0; // lexRes的指针
    void lexical()
    /*词法分析:读入一行字符串,处理该字符串的词法分析结果至lexRes*/
    /*lexI终为lexRes的长度,即单词数*/
    {
        // 读入输入串
        string inputs; // 如,a*(b+c)
        cin >> inputs;
    
        // 初始化词典
        map<string,string> words;
        std::map<string,string>::iterator it;
        words["+"]="plus";
        words["-"]="minus";
        words["*"]="times";
        words["/"]="slash";
        words["="]="eql";
        words["("]="lparen";
        words[")"]="rparen";
    
        // 开始分析
        int insize=inputs.length();
        string word; // 输入符号,如"a"/"123"
        for(int i=0; i<insize; i++)
        {
            // 空白符跳过
            while(inputs[i] == ' ' || inputs[i] == '
    ')
                i++;
    
            // 标志符/基本字捕捉
            if(isalpha(inputs[i])){
                // 拿出一个标志符/基本字
                word = inputs[i++];
                while(isalpha(inputs[i]) || isdigit(inputs[i]))
                    word += inputs[i++];
                // 在map中找到相应的词性,并输出
                it = words.find(word);
                if(it != words.end())
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout << "(" << words[word] << "," << word << ")" << endl;
                else
                    lexRes[lexI++] = make_pair("ident", word);
                    // cout << "(ident" << "," << word << ")" << endl;
                i--;
            }
    
            // 常数
            else if(isdigit(inputs[i])){
                // 拿出常数
                word=inputs[i++];
                while(isdigit(inputs[i]))
                    word+=inputs[i++];
                lexRes[lexI++] = make_pair("number", word);
                //cout << "(number" << "," << word << ")" << endl;
                i--;
            }
    
            // <、<=号
            else if(inputs[i]=='<'){
                word=inputs[i++];
                if(inputs[i]=='>'){
                    word+=inputs[i];
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout << "(" << words[word] << "," << word << ")" << endl;
                }else if(inputs[i]=='='){
                    word+=inputs[i];
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout << "(" <<words[word] << "," << word << ")" << endl;
                }else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout << "(" << words[word] << "," << word << ")" << endl;
                }else{
                    //cout << "error!" << endl;
                }
                i--;
            }
    
            // >、>=
            else if(inputs[i]=='>'){
                word=inputs[i++];
                if(inputs[i]=='='){
                    word+=inputs[i];
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout<<"("<<words[word]<<","<<word<<")"<<endl;
                }else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout<<"("<<words[word]<<","<<word<<")"<<endl;
                }else{
                    //cout<<"error!"<<endl;
                }
                i--;
            }
    
            //:=
            else if(inputs[i]==':'){
                word=inputs[i++];
                if(inputs[i]=='='){
                    word+=inputs[i];
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout<<"("<<words[word]<<","<<word<<")"<<endl;
                }else{
                    //cout<<"error!"<<endl;
                }
                //i--;
            }
    
            //其他的基本字
            else{
                word=inputs[i];
                it=words.find(word);
                if(it!=words.end()){
                    lexRes[lexI++] = make_pair(words[word], word);
                    // cout<<"("<<words[word]<<","<<word<<")"<<endl;
                }else{
                    //cout<<"error!"<<endl;
                }
            }
        }
    
    }
    
    
    /**四元式相关,被调用**/
    struct quad{
        string result;
        string arg1;
        string arg2;
        string op;
    };
    struct quad quad[50]; // 四元式数组
    int quaI = 0; // 指向四元式的指针
    void emit(string op, string arg1, string arg2, string result)
    /*发射一行四元式*/
    {
        quad[quaI].op = op;
        quad[quaI].arg1 = arg1;
        quad[quaI].arg2 = arg2;
        quad[quaI].result = result;
        quaI++;
    }
    
    int tI = 1; // 记录当前是t1/t2...t几了
    string newT()
    /*产生一个t1/t2...*/
    {
        stringstream ss;
        ss << tI;
        string ti = "t" + ss.str();
        tI++;
        return ti;
    }
    
    
    /**非算数表达式的递归下降分析及四元式生成**/
    // 指针前进
    int sym=0; // 正在处理的单词
    void advance()
    {
        ++sym;
        if(sym > lexI){
            cout << "ERROR!sym指针越界";
            exit(0);
        }
    }
    string E();
    string T();
    string F();
    
    string F()
    /*因子分析*/
    {
        string arg;
        if(lexRes[sym].first == "ident"){
            arg = lexRes[sym].second;
            advance();
        }
        else if(lexRes[sym].first == "number"){
            arg = lexRes[sym].second;
            advance();
        }
        else if(lexRes[sym].first == "lparen"){
            advance();
            arg = E();
            if(lexRes[sym].first == "rparen"){
                advance();
            }
            else{
                cout << "ERROR!未能匹配右括号!语法错误
    ";
                exit(0);
            }
        }
        return arg;
    }
    
    string T()
    /*项分析*/
    {
        string op, arg1, arg2, result;
        arg1 = F();
        while(lexRes[sym].first == "times" || lexRes[sym].first == "slash"){
            op = lexRes[sym].second;
            advance();
            arg2 = F();
            result = newT();
            emit(op, arg1, arg2, result);
            arg1 = result;
        }
        return arg1;
    }
    
    string E()
    /*表达式分析*/
    {
        string op, arg1, arg2, result;
        if(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
            advance();
        }
        arg1 = T();
        while(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
            op = lexRes[sym].second;
            advance();
            arg2 = T();
            result = newT();
            emit(op, arg1, arg2, result);
            arg1 = result;
        }
        return arg1;
    }
    
    
    /**算数表达式的递归下降分析及四元式生成**/
    int E_();
    int T_();
    int F_();
    
    int F_()
    {
        int arg;
        if(lexRes[sym].first == "ident"){
            cout << "算数表达式含变量,无法计算
    ";
            exit(0);
        }
        else if(lexRes[sym].first == "number"){
            arg = atoi(lexRes[sym].second.c_str());
            advance();
        }
        else if(lexRes[sym].first == "lparen"){
            advance();
            arg = E_();
            if(lexRes[sym].first == "rparen"){
                advance();
            }
            else{
                cout << "ERROR!未能匹配右括号!语法错误
    ";
                exit(0);
            }
        }
        return arg;
    }
    
    int T_()
    /*项分析*/
    {
        string op;
        int arg1, arg2, result;
        arg1 = F_();
        while(lexRes[sym].first == "times" || lexRes[sym].first == "slash"){
            op = lexRes[sym].second;
            advance();
            arg2 = F_();
            if(op == "*"){
                result = arg1 * arg2;
                arg1 = result;
            }
            else{
                if(arg2 != 0){
                    result = arg1 / arg2;
                    arg1 = result;
                }
                else {
                    cout << "除数为0,出错!
    ";
                    exit(0);
                }
            }
        }
        return arg1;
    }
    
    int E_()
    /*表达式分析*/
    {
        string op;
        int arg1, arg2, result;
        if(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
            advance();
        }
        arg1 = T_();
        while(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
            op = lexRes[sym].second;
            advance();
            arg2 = T_();
            if(op == "+"){
                result = arg1 + arg2;
                arg1 = result;
            }
            else{
                result = arg1 - arg2;
                arg1 = result;
            }
        }
        return arg1;
    }
    
    int main()
    {
        lexical(); 
        if(lexRes[0].first == "number"){
            cout << E_();
        }
        else{
            E();
            for(int i=0; i<quaI; i++){
                cout<<'('<<quad[i].op<<','<<quad[i].arg1<<','<<quad[i].arg2<<','<<quad[i].result<<')'<<endl;
            }
        }
    
        return 0;
    }
    

    image.png
    image.png

  • 相关阅读:
    详解学习C#的方法和步骤
    将今天写进历史,即可得出现在的世界是数字的
    60秒,我们可以干什么?
    《每个人都会死,但我总以为自己不会》让我直面死亡
    介绍Ext JS 4.2的新特性的《深入浅出Ext JS》上市
    十一阅读攻略:和土豪做朋友,告别穷屌丝,迎接高富帅,成功逆袭!
    超低成本----音视频通讯+共享屏幕+电子白板
    Hbase split的三种方式和split的过程
    分布式数据库 HBase
    Sqoop-1.4.6.bin__hadoop-2.0.4-alpha 环境搭建
  • 原文地址:https://www.cnblogs.com/hesse-summer/p/12903005.html
Copyright © 2011-2022 走看看