1 / 22

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

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

ganya
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 ที่ abstract ในลักษณะนี้ • Tree ที่ได้จากการ parse expression (1 + 2) + 3 แบบนี้ไม่ abstract เท่าไหร่ • ทั้งนี้เพราะเราใส่ node เข้าไปที่ AST ทุกๆครั้งที่ production rule ที่จะทำการสร้าง expression นี้ ดำเนินการเสร็จ

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

  7. โค๊ดการสร้าง AST: node ของ tree typedefstructA_exp_ *A_exp; structA_exp_ {enum {A_varExp, A_intExp, A_callExp, A_opExp, A_assignExp, A_ifExp, A_whileExp, A_arrayExp} kind; A_pos pos; union {A_varvar; /* nil; - needs only the pos */ intintt; struct {S_symbolfunc; A_expListargs;} call; struct {A_operoper; A_exp left; A_exp right;} op; struct {A_varvar; 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_expA_OpExp(A_pos pos, A_operoper, A_exp left, A_exp right); • A_expA_AssignExp(A_pos pos, A_varvar, A_exp exp); • A_expA_IfExp(A_pos pos, A_exp test, A_exp then, A_expelsee); • A_expA_WhileExp(A_pos pos, A_exp test, A_exp body);

  9. โค๊ดการสร้าง AST:OpExp • A_expA_OpExp(A_pos pos, A_operoper, 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_expA_AssignExp(A_pos pos, A_varvar, 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_expA_IfExp(A_pos pos, A_exp test, A_exp then, A_expelsee) { • 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_expA_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_operA_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_expparseStmt() { • 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 ข้อมูลเกี่ยวกับ type และตัวอย่างของ prototype typedefstructTy_ty_ *Ty_ty; structTy_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_tyty;} name; } u; }; Ty_tyTy_Int(void); Ty_tyTy_String(void); Ty_tyTy_Void(void); Ty_tyTy_Array(Ty_tyty);

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

  18. Function สำหรับ type check Ty_tytransExp(S_tableenv, 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_operoper = 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_tytransExp(S_tableenv, A_exp a) { switch(a->kind) { … case A_assignExp: { // Retrieve types for the expression and variable parts of the assignment. Ty_tyassignExp = transExp(env, a->u.assign.exp); Ty_tyassignVar = 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_tytransExp(S_tableenv, A_exp a) { switch(a->kind) { … case A_ifExp: { Ty_ty test; Ty_ty then; Ty_tyelsee; // 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_enventryfunctionID = NULL; A_expListargsList = NULL; Ty_tyList formals; Ty_tyreturnVal; // 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_tyfType = formals->head; A_expargExp = argsList->head; Ty_tyargType = 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 typedefstructTy_tyList_ *Ty_tyList; structTy_tyList_ {Ty_ty head; Ty_tyList tail;}; typedefstructA_expList_ *A_expList; structA_expList_ {A_exp head; A_expList tail;};

  22. ฟังก์ชั่น main ของคอมไพเลอร์ extern A_expabsyn_root; void SEM_transProg(A_exp exp) { Ty_tyexprType; // Create environments. S_tableenv= NULL; env= symTabConstruct(exp); // construct the symbol table exprType = transExp(env, exp); // type-checking } int main(intargc, 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; }

More Related