首先特別感謝網易公司,網易公司提供的雲課堂,公開課實在是太好了,有了這些東西我們這些渣渣學校的也可以學習國內外名校的課程了。
由於我在大學學習的網絡工程,大學的時候自己也too young,學校沒教《編譯原理》這門課,自己也沒主動接觸過,看到許多大牛都很推薦學習《編譯原理》這門課堂(程序員的三大浪漫之一:操作系統,編譯原理,圖形學),所以我也就很關注網易雲課堂的這門課,最近這門課終於開了,所以把自己的學習歷程記錄下來吧,希望課程結束的時候自己能夠寫出來一個簡單的編譯器。
課程主頁在這裏:網易雲課堂--中國科學技術大學--編譯原理
注:有些圖片直接從該課程講師 @華保健 老師提供的ppt中截取。已經在徵取老師的意見了,如果不合適的話,我會重新制作插圖。
什麼是編譯器
編譯器和解釋器
編譯器的結構
1:分析部分
2:綜合部分
編譯器的優化
- 優化必須是正確的。也就是說,不能改變被編譯程序的意思
- 優化必須能夠改善很多程序的性能
- 優化所需要的時間必須在可接受範圍內
- 優化所需要的工程方面的工作必須是可管理的
編譯器的第一個課堂作業
#include <iostream>
#include <vector>
#include <cassert>
class Expression
{
public:
Expression() { }
virtual ~Expression() { }
enum EXP_TYPE { ET_INT, ET_SUM };
virtual EXP_TYPE type() = 0;
};
class Expression_Int : public Expression
{
public:
Expression_Int(int v) : value_(v) { }
virtual ~Expression_Int() { }
virtual Expression::EXP_TYPE type() override
{ return Expression::ET_INT; }
int value() const { return value_; }
private:
int value_;
};
class Expression_Sum : public Expression
{
public:
Expression_Sum(Expression* left, Expression* right)
: left_(left), right_(right) { }
virtual ~Expression_Sum() { }
virtual Expression::EXP_TYPE type() override
{ return Expression::ET_SUM; }
Expression* left() { return left_; }
Expression* right() { return right_; }
private:
Expression* left_;
Expression* right_;
};
class Compiler
{
struct StackElem
{
enum ELEM_TYPE { ET_PUSH, ET_ADD };
ELEM_TYPE type_;
union
{
int value;
} context;
};
public:
void process(Expression* exp)
{
if (!exp) return;
switch (exp->type())
{
case Expression::ET_INT:
{
Expression_Int* p = dynamic_cast<Expression_Int*>(exp);
assert(p);
StackElem se;
se.type_ = StackElem::ET_PUSH;
se.context.value = p->value();
elemVec.push_back(se);
break;
}
case Expression::ET_SUM:
{
Expression_Sum* p = dynamic_cast<Expression_Sum*>(exp);
assert(p);
process(p->left());
process(p->right());
StackElem se;
se.type_ = StackElem::ET_ADD;
elemVec.push_back(se);
break;
}
default:
break;
}
}
void show()
{
for (auto e : elemVec)
{
switch (e.type_)
{
case StackElem::ET_ADD:
{
std::cout << "ADD" << std::endl;
break;
}
case StackElem::ET_PUSH:
{
std::cout << "PUSH " << e.context.value << std::endl;
break;
}
default:
break;
}
}
}
private:
std::vector<StackElem> elemVec; //stack
};
int main()
{
std::cout << "Compile starting" << std::endl;
// build an expression tree:
// +
// / \
// + 4
// / \
// 2 3
Expression* left = new Expression_Sum(new Expression_Int(2), new Expression_Int(3));
Expression* right = new Expression_Int(4);
Expression* exp = new Expression_Sum(left, right);
Compiler c;
c.process(exp);
c.show();
return 0;
}