编译原理系列 实验四语义分析与中间代码生成

Posted hesse-summer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理系列 实验四语义分析与中间代码生成相关的知识,希望对你有一定的参考价值。

最后一次实验!

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

实验目的

  • 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。
  • 掌握目前普遍采用的语义分析方法──语法制导翻译技术。
  • 给出 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;
}

技术图片
技术图片

以上是关于编译原理系列 实验四语义分析与中间代码生成的主要内容,如果未能解决你的问题,请参考以下文章

编译原理—语义分析语法制导翻译翻译模式中间代码生成

六万字长文!让你懂透编译原理——第七章 语义分析和中间代码产生

编译原理复习总结-耗子尾汁

编译原理复习总结-耗子尾汁

编译原理

编译原理 模块二