1. 程式人生 > 其它 >P - 簡單的程式碼生成程式【編譯原理】

P - 簡單的程式碼生成程式【編譯原理】

技術標籤:編譯原理編譯原理

P - 簡單的程式碼生成程式

Description

通過三地址程式碼序列生成計算機的目的碼,在生成演算法中,對暫存器的使用順序為:暫存器中存有 > 空暫存器 > 記憶體中存有 > 以後不再使用 > 最遠距離使用

Input

單組輸入,給定輸出的三地址程式碼的個數和暫存器的個數.所有的變數為大寫字母,暫存器的數量不超過9

Output

參照示例格式輸出,不需要將最後的暫存器中的值寫回記憶體

不再使用變數不用寫回記憶體

Sample

Input

4 2
T:=A-B
U:=A-C
V:=T+U
W:=V+U

Output

LD R0, A
SUB R0, B
LD R1, A
SUB R1, C
ADD R0, R1
ADD R0, R1
#include <bits/stdc++.h>

using namespace std;

char p[100];// 模擬暫存器的個數
char s[100][100];// 輸入表示式字串
int n,m,top = 0;//n輸入的表示式,m是暫存器個數

// 暫存器中是否存在該變數
int get(char ch)
{
    for(int i = 0; i < m;i ++)
    {
        if(ch == p[i])
            return i;
    }
    return -1;
}
///暫存器的使用順序為:
///暫存器中存有 > 空暫存器 > 記憶體中存有 > 以後不再使用 > 最遠距離使用
//判斷後面是否還會使用
//x是輸入表示式的編號,語句執行順序
//ch需要判斷的字元
int use(int x, char ch)
{
    for(int i = x; i < n; i ++)
    {
        // A:=B+C這裡就是B、C
        // 如果有就返回第幾句用到
        if(ch == s[i][3] || ch == s[i][5])
            return i;
    }
    return n;
}
///暫存器的使用順序為:
///暫存器中存有 > 空暫存器 > 記憶體中存有 > 以後不再使用 > 最遠距離使用
int find(int x)
{
    // 如果top小於m,就說明就空的暫存器可以使用
   if(top < m) return top++;
   //否則就是
   int t = -1;
   int ans = -1;
   for(int i = 0; i < m; i ++)
   {
       // 逐個判斷在第x句之後,存在暫存器中的字元的使用順序
       // 返回值k是執行順序的標號
       int k = use(x,p[i]);
       // 我們的目的是找到最遠不適用的,如果返回值越大,那就是最遠不適用的
       // 記錄標號存在t裡面
       if(k > ans)
       {
           ans = k;
           t = i;
       }
   }
   return t;
}
// 減加乘除
void print1(char ch)
{
    if(ch == '+')printf("ADD ");
    else if(ch == '-') printf("SUB ");
    else if(ch == '*') printf("MUL ");
    else if(ch == '\\') printf("DIV ");
}
// 第二個運算元的使用
void print2(char ch)
{
    // 檢視是否在暫存器中
    int x = get(ch);
    // 如果在暫存器中,那就直接使用
    if(x != -1){
        printf("R%d\n",x);
    }
    else {
            // 否則就直接使用記憶體中的即可,因為已經有一個暫存器了
        printf("%c\n",ch);
    }
}
int main()
{
    cin >> n >> m;
    for(int i = 0; i < n;i ++)
    {
        cin >> s[i];
    }
    for(int i = 0; i < n; i ++)
    {
        // 將第1個運算元取出來,get()來獲取暫存器中是否存在該變數
        // T:=A-B中的A
        int x = get(s[i][3]);//如果不為-1,得到的x為所在暫存器的標號
        // 如果x為-1說明該數不在暫存器中,需要做處理
        if(x == -1)
        {
            //此時的x是我們可以使用的暫存器標號
            x = find(i);
            // 如果p[x]中有東西,並且use(i,p[x]) < n即後面會使用到
            //那我們就把原來在暫存器中的字元ST到記憶體中
            if(p[x] != '\0' && use(i,p[x]) < n)
            {
                printf("ST R%d, %c\n",x,p[x]);
                p[x] = NULL;
            }
            //將該運算元載入到我們使用的暫存器標號中
            printf("LD R%d, %c\n",x,s[i][3]);
        }
        // 這裡下面的操作就是執行運算
        // 1、輸出操作符,這裡是加減乘除
        print1(s[i][4]);
        //2、輸出暫存器標號,需要的運算元已經載入到裡面了
        printf("R%d, ",x);
        //3、第二個運算元的使用
        print2(s[i][5]);
        // 暫存器中當前存的數值就是該表示的左邊的字元,即T:=A-B中的T
        p[x] = s[i][0];
    }
    return 0;
}