งานนำเสนอกำลังจะดาวน์โหลด โปรดรอ

งานนำเสนอกำลังจะดาวน์โหลด โปรดรอ

Abstract Syntax Tree และการทำ Type Checking. เฟสของคอมไพเลอร์ที่ผ่านมา.

งานนำเสนอที่คล้ายกัน


งานนำเสนอเรื่อง: "Abstract Syntax Tree และการทำ Type Checking. เฟสของคอมไพเลอร์ที่ผ่านมา."— ใบสำเนางานนำเสนอ:

1 Abstract Syntax Tree และการทำ Type Checking

2 เฟสของคอมไพเลอร์ที่ผ่านมา

3 AST Abstract Syntax Tree เป็นโครงสร้างข้อมูลที่ใช้ แทนภาษาโปรแกรมที่จะแปลสู่ภาษาระดับล่าง เฟสของคอมไพเลอร์หลังจากการทำ parsing จะใช้ AST ในการปฏิบัติการหลายๆอย่าง – Type checking – Optimization ต่างๆ – การผลิตโค๊ดระหว่างกลาง (Intermediate Code Generation)

4 การสร้าง AST ค่อยๆสร้างแบบ bottom-up ใส่โค๊ดในการสร้าง node และ link ไว้ที่ semantic action – Semantic action คือสิ่งที่จะถูกดำเนินการขณะที่ non-terminal หรือ terminal ด้านขวาของ CFG ได้รับการประมวลเรียบร้อยแล้ว – นั่นคือเวลาที่ production rule ของ CFG ได้ ปฏิบัติการ rule นั้นเสร็จเรียบร้อยแล้ว

5 หัวใจในการสร้าง AST ต้อง abstract – ใส่เฉพาะ node ที่จำเป็นใน AST  Tree ที่ได้จากการ parse expression (1 + 2) + 3 แบบนี้ไม่ abstract เท่าไหร่  ทั้งนี้เพราะเราใส่ node เข้าไปที่ AST ทุกๆครั้งที่ production rule ที่จะทำการสร้าง expression นี้ ดำเนินการเสร็จ  เราต้องการ tree ที่ abstract ในลักษณะนี้

6 คอมไพเลอร์ยุคเก่า รันบนเครื่องคอมพิวเตอร์ที่มีหน่วยความจำหลัก น้อย หน่วยความจำหลักไม่เพียงพอที่จะบรรจุ AST ของทั้งโปรแกรมได้ จะผลิตโค๊ดและทำการ type checking ที่ semantic action โดยตรงเลย – คอมไพเลอร์ขนาดเล็กและเข้าใจได้ง่าย แต่ – ไม่ถูกต้องตามหลักการวิศวกรรมซอฟแวร์ที่ดี – ปฏิบัติการหลายๆอย่างทำได้ลำบาก คอมไพเลอร์ CSubset ไม่มีการสร้าง AST

7 โค๊ดการสร้าง AST: node ของ tree typedef struct A_exp_ *A_exp; struct A_exp_ {enum {A_varExp, A_intExp, A_callExp, A_opExp, A_assignExp, A_ifExp, A_whileExp, A_arrayExp} kind; A_pos pos; union {A_var var; /* nil; - needs only the pos */ int intt; struct {S_symbol func; A_expList args;} call; struct {A_oper oper; A_exp left; A_exp right;} op; struct {A_var var; A_exp exp;} assign; struct {A_exp test, then, elsee;} iff; /* elsee is optional */ struct {A_exp test, body;} whilee; } u; };

8 โค๊ดการสร้าง AST: ตัวอย่าง prototype A_exp A_OpExp(A_pos pos, A_oper oper, A_exp left, A_exp right); A_exp A_AssignExp(A_pos pos, A_var var, A_exp exp); A_exp A_IfExp(A_pos pos, A_exp test, A_exp then, A_exp elsee); A_exp A_WhileExp(A_pos pos, A_exp test, A_exp body);

9 โค๊ดการสร้าง AST: OpExp A_exp A_OpExp(A_pos pos, A_oper oper, A_exp left, A_exp right) { A_exp p = malloc(sizeof(*p)); p->kind=A_opExp; p->pos=pos; p->u.op.oper=oper; p->u.op.left=left; p->u.op.right=right; return p; }

10 โค๊ดการสร้าง AST: AssignExp A_exp A_AssignExp(A_pos pos, A_var var, A_exp exp) { A_exp p = malloc(sizeof(*p)); p->kind=A_assignExp; p->pos=pos; p->u.assign.var=var; p->u.assign.exp=exp; return p; }

11 โค๊ดการสร้าง AST: IfExp A_exp A_IfExp(A_pos pos, A_exp test, A_exp then, A_exp elsee) { A_exp p = malloc(sizeof(*p)); p->kind=A_ifExp; p->pos=pos; p->u.iff.test=test; p->u.iff.then=then; p->u.iff.elsee=elsee; return p; }

12 โค๊ดการสร้าง AST: WhileExp A_exp A_WhileExp(A_pos pos, A_exp test, A_exp body) { A_exp p = malloc(sizeof(*p)); p->kind=A_whileExp; p->pos=pos; p->u.whilee.test=test; p->u.whilee.body=body; return p; }

13 สร้าง AST ที่ semantic action จาก production: expr = expr + expr ใส่ semantic action ( ให้ expr ด้านขวาคือ e1 และ e2 ตามลำดับ ): {return A_OpExp(A_pos pos, A_oper A_plusOp, A_exp e1, A_exp e2);} จาก production: stmt = if (expr) stmt else stmt ใส่ semantic action ( ให้ expr และ stmt ทั้งสองที่อยู่ ด้านขวาเป็น e1 s1 และ s2 ตามลำดับ ): {return A_IfExp(A_pos pos, A_exp e1, A_exp s1, A_exp s2);}

14 โค๊ดการสร้าง AST ใน parser A_exp parseStmt() { A_exp result; switch (next_token) { case IF: consume(IF); consume(LPAREN); A_exp e1 = parseExpr(); consume(RPAREN); A_exp s1, s2; s1 = parseStmt(); if (next_token == ELSE) { consume(ELSE); s2 = parseStmt(); } else s2 = EmptyStmt(); result = A_IfExp(A_pos pos, A_exp e1, A_exp s1, A_exp s2); break; case ID:... case WHILE:...

15 Type Checking Traverse AST โดยใช้ recursive function Function ที่ traverse AST จะตรวจสอบ expression ที่จะ type check หนึ่งใน argument ของ function นี้คือ context หรือ environment ที่ให้ข้อมูลเพิ่มเติมเกี่ยวกับ expression ที่จะ type check – Symbol table เก็บข้อมูล context Function นี้จะ return ข้อมูลเกี่ยวกับ type ของ expression ที่กำลังพิจารณา

16 โค๊ดสำหรับการทำ type check typedef struct Ty_ty_ *Ty_ty; struct Ty_ty_ {enum {Ty_record, Ty_nil, Ty_int, Ty_string, Ty_array, Ty_name, Ty_void} kind; union { Ty_ty array; struct {S_symbol sym; Ty_ty ty;} name; } u; }; Ty_ty Ty_Int(void); Ty_ty Ty_String(void); Ty_ty Ty_Void(void); Ty_ty Ty_Array(Ty_ty ty); ข้อมูลเกี่ยวกับ type และตัวอย่างของ prototype

17 โค๊ดสำหรับการทำ type check static struct Ty_ty_ tyint = {Ty_int}; Ty_ty Ty_Int(void) {return &tyint;} static struct Ty_ty_ tystring = {Ty_string}; Ty_ty Ty_String(void) {return &tystring;} static struct Ty_ty_ tyvoid = {Ty_void}; Ty_ty Ty_Void(void) {return &tyvoid;} Ty_ty Ty_Array(Ty_ty ty) { Ty_ty p = malloc(sizeof(*p)); p->kind=Ty_array; p->u.array=ty; return p; } ฟังก์ชั่นที่ return ข้อมูลเกี่ยวกับ type ชนิดต่างๆ

18 Function สำหรับ type check Ty_ty transExp(S_table env, A_exp a) { switch(a->kind) { case A_varExp : { return transVar(env, a->u.var); } case A_intExp: { return Ty_Int(); } case A_opExp: { A_oper oper = a->u.op.oper; Ty_ty left = transExp(env, a->u.op.left); Ty_ty right = transExp(env, a->u.op.right); if (oper == A_plusOp) { if (left->kind == Ty_int && right->kind == Ty_int) return Ty_Int(); else if … else Print_Error(“Type error”) } else if … break; } …

19 Type check สำหรับ assignment statement Ty_ty transExp(S_table env, A_exp a) { switch(a->kind) { … case A_assignExp: { // Retrieve types for the expression and variable parts of the assignment. Ty_ty assignExp = transExp(env, a->u.assign.exp); Ty_ty assignVar = transVar(env, a->u.assign.var); // Insert code to check if assignExp is type-compatible with assignVar return Ty_Void(); break; } …

20 Type check สำหรับ if statement Ty_ty transExp(S_table env, A_exp a) { switch(a->kind) { … case A_ifExp: { Ty_ty test; Ty_ty then; Ty_ty elsee; // Grab expressions for test, then, and else. test = transExp(env, a->u.iff.test); then = transExp(env, a->u.iff.then); if (a->u.iff.elsee != NULL) elsee = transExp(env, a->u.iff.elsee); else elsee = Ty_Nil(); // Insert code to check if test is type-compatible with boolean // if then and elsee are well-typed, return Void type return Ty_Void(); break; } …

21 Type check สำหรับ call statement case A_callExp: { E_enventry functionID = NULL; A_expList argsList = NULL; Ty_tyList formals; Ty_ty returnVal; // Verify that function has been defined previously. functionID = S_look(venv, a->u.call.func); if (functionID == NULL) { Print_Error(“No function by that name”); } returnVal = functionID->u.fun.result; if (no argument function) { return ActualTypeOf(returnVal)); } // Check parameters and function call types. argsList = a->u.call.args; formals = functionID->u.fun.formals; while (argsList != NULL && formals != NULL) { Ty_ty fType = formals->head; A_exp argExp = argsList->head; Ty_ty argType = transExp(env, argExp); formals = formals->tail; argsList = argsList->tail; // Insert code to check if fType and artType are compatible } return ActualTypeOf(returnVal)); break; } Additional typedef typedef struct Ty_tyList_ *Ty_tyList; struct Ty_tyList_ {Ty_ty head; Ty_tyList tail;}; typedef struct A_expList_ *A_expList; struct A_expList_ {A_exp head; A_expList tail;};

22 ฟังก์ชั่น main ของคอมไพเลอร์ extern A_exp absyn_root; void SEM_transProg(A_exp exp) { Ty_ty exprType; // Create environments. S_table env = NULL; env = symTabConstruct(exp); // construct the symbol table exprType = transExp(env, exp); // type-checking } int main(int argc, char **argv) { if (argc!=2) { fprintf(stderr,"usage: parsetest filename\n"); exit(1); } /* Step 1, get tokens from lexical analysis; Step 2, build an AST while parsing */ parseInput(argv[1]); /* Step 3, traverse AST for semantic analysis from the entry point of absyn_root. */ SEM_transProg(absyn_root); return 0; }


ดาวน์โหลด ppt Abstract Syntax Tree และการทำ Type Checking. เฟสของคอมไพเลอร์ที่ผ่านมา.

งานนำเสนอที่คล้ายกัน


Ads by Google