1 / 40

Εισαγωγή

Εισαγωγή. Ειδικά Θέματα Μεταγγλωτιστών Χειμερινό Εξάμηνο / 2003-2004 Κατασκευή compiler για την γλώσσα Minijava. Κατασκευή ενός compiler. Λεκτική Ανάλυση. Συντακτική Ανάλυση. Σημασιολογική Ανάλυση. Παραγωγή κώδικα. Sablecc 3.0b2.

cicada
Download Presentation

Εισαγωγή

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. Εισαγωγή Ειδικά Θέματα Μεταγγλωτιστών Χειμερινό Εξάμηνο / 2003-2004 • Κατασκευή compiler για την γλώσσα Minijava

  2. Κατασκευή ενός compiler Λεκτική Ανάλυση Συντακτική Ανάλυση Σημασιολογική Ανάλυση Παραγωγή κώδικα

  3. Sablecc 3.0b2 • Χρήσηαντικειμενοστραφών τεχνικών για την αυτόματη δημιουργία αυστηρά καθορισμένων συντακτικών δέντρων από τον ορισμό κάποιας γραμματικής • Χρήση του Visitor Design Pattern με αποτέλεσμα περισσότερη συναρμολογισιμότητα (modularity)

  4. Sablecc • 1. Package • 2. Helpers • 3. States • 4. Tokens • 5. Ignored Tokens • 6. Productions

  5. Lexer (1) Καταστάσεις normalκαι comment. Για την υποστήριξη εμφωλευμένων σχολίων είναι απαραίτητο να γίνει override η μέθοδος filter της τάξης Lexer. {normal->comment, comment} comment = '/*'; {comment} comment_star = '*'; {comment} comment_slash = '/'; {comment} comment_body = [all_input_chars-['*' + '/']]*;

  6. Lexer (2) public class CustomLexer extends Lexer { ……………………................... protected void filter() { if (state.equals(State.COMMENT)) { if (comment == null) { …………………………………. } else { text.append(token.getText()); // accumulate the text. if (token instanceof TComment) { count++; critical = false; } else if (token instanceof TCommentStar) { critical = true; } else if ((token instanceof TCommentSlash) && (critical = true)) { count--; critical = false; } } ………………………………………

  7. Lexer (3) …………………………………….. if (token instanceof TInteger) { try { number = Integer.parseInt(token.getText()); } catch (NumberFormatException e) { throw new RuntimeException("Integer should not exceed 32 bit signed integer."); } } …………………………………….

  8. Abstract Syntax Tree (1) program = main_class class_decl* ; main_class = [clname]:identifier [arg]:identifier statement ; class_decl = {simple} identifier var_decl* method_decl* | {extends} [newcl]:identifier [oldcl]: identifier var_decl* method_decl* ; var_decl = type identifier ; method_decl = type identifier formal* var_decl* statement* exp ; formal = type identifier ; type = {int_array} | {boolean} | {integer} | {identifier} id_literal ; statement = {block} statement* | {if} exp [ifpart]: statement [elsepart]: statement | {while} exp statement | {print} exp | {assign} identifier exp | {array_assign} identifier [index]: exp [rhs]:exp ;

  9. Abstract Syntax Tree (2) exp = {and} [left]:exp [right]:exp | {less_than} [left]:exp [right]:exp | {plus} [left]:exp [right]:exp | {minus} [left]:exp [right]:exp | {times} [left]:exp [right]:exp | {array_lookup} exp [index]:exp | {array_length} exp | {call} exp identifier [args]:exp* | {integer_literal} integer | {true} | {false} | {identifier} id_literal | {this} | {new_array} exp | {new_object} identifier | {not} exp ; identifier = id_literal ;

  10. Productions -> AST (1) • Getting an already existing element exp_list_tail -> exp = comma exp -> exp; • New alternative exp = (plus) exp plus factor -> New exp.plus(exp,factor.exp); • List creation exp_list -> exp* = exp exp_list_tail -> (exp_list_tail.exp exp);

  11. Productions -> AST (2) CST : program = main_class class_decl* {-> New program( main_class, [class_decl] ) }; AST : program= main_class class_decl* ; CST : formal_list {-> formal*} = formal formal_list_tail* {-> [formal formal_list_tail.formal]}; formal_list_tail {-> formal } = comma formal {-> formal } ; formal = type identifier {-> New formal(type, identifier) } ; AST : formal = type identifier ; CST : add_exp {-> exp } = {plus} [left]:add_exp plus [right]:mult_exp {-> New exp.plus(left.exp, right.exp) } | {minus} [left]:add_exp minus [right]:mult_exp {-> New exp.minus(left.exp, right.exp) } | {times} mult_exp {-> mult_exp.exp } ; AST : exp = {and} [left]:exp [right]:exp | {minus} [left]:exp [right]:exp

  12. Symbol Analysis - Example Symbol Table Class 1 Variable 2 Method 1 Variable 1 Variable 1 Variable 3 Class 2 Method 2 Variable 2 Method 1 Variable 1 Variable 2 Variable 1 Variable 4 Variable 3

  13. Symbol Analysis - Class • Όνομα της τάξης • Όνομα γονέα της τάξης (αν υπάρχει) • Μέθοδοι • Καθολικές για την τάξη μεταβλητές (Fields)

  14. Symbol Analysis - Method • Όνομα της μεθόδου • Τύπος επιστροφής της μεθόδου (PType από Sablecc) • Παράμετροι της μεθόδου • Τοπικές μεταβλητές της μεθόδου • Μετρητής

  15. Symbol Analysis - Variable • Όνομα μεταβλητής • Τύπος μεταβλητής • Θέση μεταβλητής. Χρήσιμο στο jas.

  16. Semantic Analysis SymbolTableClass.java SymbolTableBuilder.java TypeCheck.java • Γίνονται 3 περάσματα συνολικά. Τα δύο πρώτα για το γέμισμα του πίνακα συμβόλων με όλες τις τάξεις, μεθόδους, μεταβλητές. Στο τρίτο πέρασμα γίνονται οι υπόλοιποι σημασιολογικοί έλεγχοι. • Επίσης δηλώνουμεως global τις μεταβλητές currMethod, currClass.

  17. Semantic Analysis (2) • Τα ανιχνεύσιμα λάθη είναι : • Κάποια τάξη έχει ήδη δηλωθεί στον πίνακα συμβόλων • Ο τύπος μεταβλητής ή επιστροφής μεθόδου δεν υπάρχει • Κυκλική κληρονομικότητα τάξεων • Ο γονέας κάποιας τάξης δεν υπάρχει ως τάξη. • Κάποιο field variable δηλώνεται με ήδη υπάρχον όνομα • Κάποια παράμετρος ή τοπική μεταβλητή μεθόδου δηλώνεται με ήδη υπάρχον όνομα στην ίδια μέθοδο • Προσπάθεια δήλωσης μεθόδου με ήδη υπάρχον όνομα στην ίδιατάξη

  18. Semantic Analysis (3) 8. Το όνομα κάποιας μεταβλητής σε μία έκφραση δεν έχει δηλωθεί 9. Μη σωστός τρόπος υλοποίησης override κάποιας μέθοδου του γονέα της τάξης. Υπενθυμίζεται ότι η Minijava δεν επιτρέπει overload. 10. Ο επιστρεφόμενος τύπος μιάς μεθόδου δεν εκχωρείται στον τύπο που έχει δηλωθεί στην μέθοδο. 11. Η πιθανότητα να μην έχει αρχικοποιηθεί μια μεταβλητή όταν αυτή είναι μέρος μιας έκφρασης 12. Στο ArrayLookup ( Exp[Exp] ) το πρώτο Exp πρέπει να είναι τύπου IntArray και το δεύτερο τύπου Integer 13. Στο ArrayLength ( Exp.length ) το Exp πρέπει να είναι τύπου IntArray

  19. Semantic Analysis (4) 14. Στο NewArray ( new int [Exp] ) το Exp πρέπει να είναι τύπου Integer 15. Στους τελεστές <, +, -, * οι εκφράσεις και στα δύο μέρη τους πρέπει να είναι τύπου Integer 16. Στους τελεστές &&, ! οι εκφράσεις πρέπει να είναι τύπου Boolean 17. Στο NewObject ( new id () ) το id πρέπει να έχει δηλωθεί στον πίνακα συμβόλων ως τάξη 18. Στο CallExp ( Exp.id(ExpList) ) ο αριθμός των παραμέτρων της μεθόδου που θα κληθεί είναι μικρότερος η μεγαλύτερος από τον αριθμό παραμέτρων που πρέπει σύμφωνα με την δήλωσή της 19. Στο CallExp κάποια παράμετρος δεν μπορεί να εκχωρηθεί στον τύπο όπως προκύπτει από την δήλωση της μεθόδου στον πίνακα συμβόλων.

  20. Semantic Analysis (5) 20. Στο CallExp η μέθοδος που θέλουμε να καλέσουμε δεν υπάρχει στην τάξη όπως προκύπτει από το Exp 21. Στο Print Statement η παράμετρος πρέπει να είναι τύπου Integer 22. Στα If και WhileStatements οι εκφράσεις πρέπει να είναι τύπου Boolean 23. Ασυμβατότητα τύπων στην απλή εκχώρηση 24. Στο ArrayAssign ( id[Exp] = Exp ) το id πρέπει να είναι τύπου IntArray, το πρώτο Exp τύπου Integer όπως και το δεύτερο Exp.

  21. Semantic Analysis (6) Για κάποια από αυτά τα λάθη διακόπτεται άμεσα το typechecking με το αντίστοιχο μήνυμα λάθους Για τα περισσότερα λάθη η διαδικασία ελέγχου συνεχίζεται μέχρι το τέλος οπότε εμφανίζεται το μήνυμα λάθους και δεν προχωράμε στην επόμενη φάση. Ο λόγος είναι …….

  22. Semantic Analysis - Implementation Το typechecking γίνεται bottom-up. Αυτό γίνεται κάνοντας override τις μεθόδους της τάξης DepthFirstAdapter. Για κάθε Exp όπως φαίνεται στο AST υπολογίζω και αποθηκεύω τον τύπο που προκύπτει σε ένα HashTable με κλειδί τον ίδιο τον κόμβο που βρίσκεται η διάσχιση κάθε στιγμή. Για HashTable χρησιμοποιώ τον πίνακα out και τις μεθόδους setOut(key,value) και getOut(key) που διαθέτει η Sablecc για αυτόν τον σκοπό ειδικά. Επομένως ξεκινώντας από τα βασικά expressions IdentifierExp, IntegerLiteralExp, TrueExp, FalseExp φτάνουμε μεχρι την ρίζα. public void outAIntegerLiteralExp(AIntegerLiteralExp node) { setOut(node, new AIntegerType()); } public void outATrueExp(ATrueExp node) { setOut(node, new ABooleanType()); } public void outAFalseExp(AFalseExp node) { setOut(node, new ABooleanType()); }

  23. Semantic Analysis – Εxample 1 public void outAIdentifierExp(AIdentifierExp node) { String id = node.getIdLiteral().toString(); PType t = findVarType(id); setOut(node, t); …………………………………………………………… } public void outATimesExp(ATimesExp node) { PType leftType = (PType) getOut(node.getLeft()); PType rightType = (PType) getOut(node.getRight()); if (isIntegerType(leftType) && isIntegerType(rightType)) { setOut(node, new AIntegerType()); } else { System.out.println(currClass.getId() + "." + currMethod.getId() + ": " + "Both sides of multiplication must be Integer"); ok[0] = false; } }

  24. Semantic Analysis – Εxample 2 (1) public void inAExtendsClassDecl(AExtendsClassDecl node) { String ClassName = node.getNewcl().toString().trim(); String ParentClass = node.getOldcl().toString().trim(); currClass = symtable.getClass(ClassName); int line = ((AIdentifier) node.getNewcl()).getIdLiteral().getLine(); if (iscyclic(currClass, symtable.getClass(ParentClass))) { System.out.println("Line " + line + ": " + "Cyclic inheritance detected for class" + currClass.getId()); ok[0] = false; } …………………………………………………………………….. ……………………………………………………………………..

  25. Semantic Analysis – Εxample 2 (2) public boolean iscyclic(minijava.symbol.Class supercl, minijava.symbol.Class subcl) { if (subcl == null) { return false; } if (subcl.getId().equals(supercl.getId())) { return true; } if (subcl.parent() == null) { return false; // root reached } return iscyclic(supercl, symtable.getClass(subcl.parent())); }

  26. Semantic Analysis – Εxample 3 public void outAArrayAssignStatement(AArrayAssignStatement node) { String id = node.getIdentifier().toString(); PType lhs = findVarType(id); PType index = (PType) getOut(node.getIndex()); PType rhs = (PType) getOut(node.getRhs()); int line = ( (AIdentifier) node.getIdentifier()).getIdLiteral().getLine(); if (! (lhs instanceof AIntArrayType)) { System.out.println(currClass.getId() + "." + currMethod.getId() + "(Line " + line + "): " + "Left hand side variable must be an IntArray"); ok[0] = false; } if (!isIntegerType(index)) { System.out.println(currClass.getId() + "." + currMethod.getId() + "(Line " + line + "): " + "Index inside IntArray variable must be of Integer type"); ok[0] = false; }

  27. Semantic Analysis – Εxample 4 (1) public void outAAssignStatement(AAssignStatement node) { String id = node.getIdentifier().toString(); PType lhs = findVarType(id); PType rhs = (PType) getOut(node.getExp()); int line = ( (AIdentifier) node.getIdentifier()).getIdLiteral().getLine(); if (!assignpossible(lhs, rhs)) { System.out.println(currClass.getId() + "." + currMethod.getId() + "(Line " + line + "): " + "Types do not match in assignment"); ok[0] = false; } if (currMethod.containsVar(id)) { //local vars only initcheck.put(id, new Integer(1)); } }

  28. Semantic Analysis – Εxample 4 (2) private boolean assignpossible(PType ltyp, PType rtyp) { if (ltyp.getClass() != rtyp.getClass()) { return false; } if (ltyp instanceof AIdentifierType) { // subclass variable shoud be assignable to superclass variable minijava.symbol.Class supercl, subcl; supercl = symtable.getClass( ( (AIdentifierType) ltyp).getIdLiteral(). toString().trim()); subcl = symtable.getClass( ( (AIdentifierType) rtyp).getIdLiteral(). toString().trim()); return subclass(subcl, supercl); } return true; // of same type }

  29. Semantic Analysis – Initialization (1) private Hashtable initcheck; public void inAMethodDecl(AMethodDecl node) { ……………………………………………………………. initcheck = new Hashtable(); ……………………………………………………………. } public void outAVarDecl(AVarDecl node) { String id = node.getIdentifier().toString(); if (currMethod != null) { //local function variables initcheck.put(id, new Integer(0)); } }

  30. Semantic Analysis – Initialization (2) public void caseAIfStatement(AIfStatement node) { ………………………………………………………………… Hashtable ifcheck = new Hashtable(); Hashtable elsecheck = new Hashtable(); ifcheck.putAll(initcheck); elsecheck.putAll(initcheck); initcheck = ifcheck; if (node.getIfpart() != null) { node.getIfpart().apply(this); } setIn(node.getIfpart(), initcheck); initcheck = elsecheck; if (node.getElsepart() != null) { node.getElsepart().apply(this); } setIn(node.getElsepart(), initcheck); Hashtable doneifcheck = (Hashtable) getIn(node.getIfpart()); Hashtable doneelsecheck = (Hashtable) getIn(node.getElsepart()); initcheck = executeAnd(doneifcheck, doneelsecheck); outAIfStatement(node); }

  31. Translation • Γίνεται χρήση του Jas για την παραγωγή Java ByteCode (.class αρχείο) • Δηλώνω και εδώ μερικές global για την τάξη μεταβλητές : Οι μεταβλητές currMethod, currClass Οι μεταβλητές nclass (τύπου ClassEnv) και doit (τύπου CodeAttr) Οι μεταβλητές stackmax και stackcurr (τύπου int και οι δύο); H μεταβλητη label (τύπου int) • Δυναμικά η δήλωση StackSize και Varsize • Συμπλήρωση LovalVarTable Διαλέξεις 9 και 11 του Jingling Xue – University of New South Wales Java Virtual Machine Online Instruction Reference Manual - O'Reilly Associates. Όπου χρειαζόταν να δώ πως γίνεται κάτι ---> Disassembly Π.χ έστω αρχείο checkthis.java java –classpath . checkthis.java javap –c –l –classpath . checkthis

  32. Translation –Java Types private String extractType(PType type) { if (type instanceof ABooleanType) { return "Z"; } else if (type instanceof AIntArrayType) { return "[I"; } else if (type instanceof AIntegerType) { return "I"; } else if (type instanceof AIdentifierType) { return "L" + ( (AIdentifierType) type).getIdLiteral().toString().trim() +";“; } return null; }

  33. Translation – Example 1 public void outALessThanExp(ALessThanExp node) { Label first = new Label("label" + (++label)); Label second = new Label("label" + (++label)); try { doit.addInsn(new Insn(opc_if_icmplt, first)); doit.addInsn(new Insn(opc_iconst_0)); doit.addInsn(new Insn(opc_goto, second)); doit.addInsn(first); doit.addInsn(new Insn(opc_iconst_1)); doit.addInsn(second); } catch (jasError ex) { } stackcurr--; // -2 for if_icmplt, +1 for iconst_x = -1 }

  34. Translation – Example 2 public void inAExtendsClassDecl(AExtendsClassDecl node) { String ClassName = node.getNewcl().toString().trim(); String ParentClass = node.getOldcl().toString().trim(); currClass = symtable.getClass(ClassName); nclass = new ClassEnv(); nclass.setClass(new ClassCP(ClassName)); nclass.setSuperClass(new ClassCP(ParentClass)); nclass.setClassAccess( (short) ACC_PUBLIC); CodeAttr init = new CodeAttr(); doit = new CodeAttr(); init.addInsn(new Insn(opc_aload_0)); init.addInsn(new Insn(opc_invokenonvirtual, new MethodCP(ParentClass, "<init>", "()V"))); init.addInsn(new Insn(opc_return)); init.setStackSize((short)1); //aload_0 init.setVarSize((short) 1); //this nclass.addMethod( (short) 0, "<init>", "()V", init, null); }

  35. Translation – Example 3 (1) Position > 0 αν είναι τοπική μεταβλητή public void caseAAssignStatement(AAssignStatement node) { if (node.getIdentifier() != null) { node.getIdentifier().apply(this); } String id = node.getIdentifier().toString(); PType type = findVarType(id); int position = findVarPos(id); if (position == 0) { doit.addInsn(new Insn(opc_aload_0)); if ( (++stackcurr) > stackmax) { stackmax = stackcurr; } } if (node.getExp() != null) { node.getExp().apply(this); }

  36. Translation – Example 3 (2) if (position > 0) { //local variables , the rest later if ( (type instanceof AIntegerType) || (type instanceof ABooleanType)) { doit.addInsn(new Insn(opc_istore, position)); } else { //AIdentifierType doit.addInsn(new Insn(opc_astore, position)); } stackcurr--; } else { String classname = currClass.getId().toString(); doit.addInsn(new Insn(opc_putfield, new FieldCP(classname, id, extractType(type)))); stackcurr = stackcurr - 2; // 1 objectref + 1 value }

  37. Minijava Example 1 class Example1{ public static void main ( String [ ] a ) { System.out.println ( new Test1 ( ) . Start (5,true) ) ; } } class Test1 extends Visitor { int fielda; public int Start(int b,boolean c) { boolean ntb ; int[] nti; int ourint; nti = new int[b]; //ourint = nti[5]; System.out.println(ourint); return nti[0] ; } } Line 7: Symbol Visitor, declared as Parent of class Test1, does not exist Test1.Start (Line 18): Variable ourint might not have been initialized Semantic Analysis has failed miserably.................

  38. Minijava Example 2 class Example2{ public static void main(String[] args){ System.out.println(new B().m()); } } class A extends B{} class B extends C{ publicint m(){ int nowhere; nowhere = this.f(); /*nowhere = k;*/ return nowhere; } } class C extends A{} Line 7: Cyclic inheritance detected for classA

  39. Minijava Example 3 (1) class Example3{ publicstaticvoidmain(String[] args){ System.out.println( new Support().m()); } } class Support{ publicint m(){ Support a; int b; int c; a = new Support(); b = this.met( new Support()); return new Support().f(); } public int f(){ return 10; } public int g(){ return 7; } Continues

  40. Minijava Example 3 (2) public int met(Support o){ K k; k = this.boom( new C()); k = this.loom( new C()); return k.g(); } public K boom(K k){ return k; } public K loom(C c){ return c; } } class K extends Support{ } class C extends K{ } Any Errors ? java -classpath . Example3 10

More Related