Hello Compiler

源语言 : 加法表达式语言,支持形如 1+11+2+3 …… 的运算

目标机器:栈式计算机,支持push(n)add() 两种操作(使用C++模拟)

构造一个栈式计算机

#include

#define ERROR -9999;

using namespace std;

class StackComputer{
    private:
        int stack_arr[100]; // 操作数栈 
        int head = 0;          // 栈顶指针 
        
        int pop() { 
            if(this->head < 1) return ERROR;
            
            this->head--;
            
            return this->stack_arr[this->head];
        }
    public:
        StackComputer() = default;
        void push(int n) {
            this->stack_arr[this->head] = n;
            
            this->head ++;
        }
        int add() {
            if(this->head < 2) return ERROR;
            
            int result = this->pop() + this->pop();
            
            this->push(result);
            
            return result;
        }
        void print() {       // 打印结果 
             if(this->head == 1) cout<pop()<

main函数如下


int main() {
    StackComputer c;
    
    c.push(1);
    c.push(10);
    c.add();
    c.push(100);
    c.add();
    
    c.print();  // 输出111 
}

现在我们编写一个编译器将1+10+100编译成:

    c.push(1);
    c.push(10);
    c.add();
    c.push(100);
    c.add();
    
    c.print(); 

编写编译器

步骤说明

首先将1+10+100生成如下的抽象语法树

Hello Compiler_第1张图片

然后对该二叉树进行后续遍历,按照如下的规则生成代码

  1. 遇到整数n,则生成c.push(n)
  2. 遇到操作符+,则生成c.add()
  3. 遍历完成整棵树以后,生成c.print()

构造抽象语法树

#define MODE_NUM 0
#define MODE_CHAR 1

typedef struct AbsTree* BinTree;
struct AbsTree {
    int mode;
    int data;
    bool isRoot; // 标记当前节点是否为根节点 
    BinTree left, right;
}; // 一棵二叉树

BinTree genTree(int mode, int data) { // 生成二叉树结点的工具
    BinTree tree = (BinTree)malloc(sizeof(AbsTree));
    
    tree->left = NULL;
    tree->right = NULL;
    tree->isRoot = false;
    
    if(mode == MODE_NUM) tree->data = data;
    
    tree->mode = mode;
    
    return tree;
}

BinTree genAbsTree(char* lang) { // 生成抽象语法树并返回根节点
    BinTree root = NULL, left = NULL, right = NULL;
     
    for(int i=0; i 123]
            while(i+1 < strlen(lang) 
                    && isdigit(lang[i+1])) {
                        
                num = num*10 + (lang[++i] - 48);    
            }
            
            
            if(left == NULL) {
                left = genTree(MODE_NUM, num);
            }
            else {
                right = genTree(MODE_NUM, num);
                root->right = right;
                root->left = left;
                left = root;
            }
        }
        else { // 扫描到非数字
            if (elem == ' ') continue;
            
            root = genTree(MODE_CHAR, -1);
            root->left = left;
        }
    }
    
    if (root!=NULL) root->isRoot = true; // 标记当前结点为根节点 

    return root; 
} 

生成目标代码

// 树的后序遍历生成目标代码
void genTargetCode(BinTree node) {
    if(node == NULL) return;
    genTargetCode(node->left);
    genTargetCode(node->right);
    
    if (node->mode == MODE_NUM) {
        printf("c.push(%d);\n", node->data);
    }
    else {
        printf("c.add();\n");
    }
    
    if(node->isRoot) printf("c.print();\n");
}

测试

int main() {
    char sum_exp[100] = "1 + 10 + 100";
    
    BinTree root = genAbsTree(sum_exp);
    
    genTargetCode(root);
} 

运行之后生成目标代码正确。

你可能感兴趣的:(compiler)