ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-1 Επίλυσης ασάφειας με εισαγωγή μη-τερματικών Π.χ. stmt = “if”, expr, “then”, stmt | “if”, expr, “then”, stmt, “else”, stmt | other ; H συμβολοσειρά:if E1 then if E2 then S1 else S2 έχει δύο διαφορετικά συντακτικά δένδρα. stmt = matched_stmt | unmatched_stmt ; matched_stmt = “if”, expr, “then”, matched_stmt, “else”, matched_ stmt | other ; unmatched_stmt = “if”, expr, “then”, stmt | “if”, expr, “then”, matched_stmt, “else”, unmatched_ stmt ;
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-2 Επίλυση ασάφειας (συνέχεια) H παρακάτω γραμματική είναι ασαφής; stmt = “if”, expr, “then”, stmt | matched ; matched = “if”, expr, “then”, matched, “else”, stmt | other ; Η συμβολοσειρά if E1 then if E2 then S1 else if E3 then S2 else S3 πώς μπορεί να παραχθεί; Έχει περισσότερα από ένα συντακτικά δένδρα;
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-3 Συντακτική Ανάλυση - Επαναπροσέγγιση ΣΑ ή parser : πρόγραμμα το οποίο δοθείσης μίας συμβολοσειράς, προσπαθεί να κατασκευάσει μία αντίστοιχη παραγωγή. Είδη συντακτικών δένδρων: –explicit : δημιουργείται η δομή που αναπαριστά το δένδρο –implicit : δεν δημιουργείται το δένδρο αλλά κατάλληλες ενέργειες εκτελούνται στα σημεία που αντιστοιχούν στους κόμβους του δένδρου. Parsers: –Top-down : εύρεση των παραγωγών που δημιουργούν την είσοδο ξεκινώντας από το αρχικό σύμβολο της γραμματικής. Αριστερότερη παραγωγή. –Bottom - up : εύρεση των παραγωγών που δημιουργούν την είσοδο ξεκινώντας από το τερματικά σύμβολα της εισόδου, δηλ. τα φύλλα του δένδρου. Δεξιότερη παραγωγή.
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-4 ΣΑ από πάνω προς τα κάτω Οι ΣΑ εξετάζουν την είσοδο από αριστερά προς τα δεξιά και με βάση τα επόμενα σύμβολα εισόδου προσπαθούν να μαντέψουν την επόμενη παραγωγή. Π.χ.έστω η γραμματική S = “c”, A, “d” ; A = “a”, “b” | “a” ; Ανάγνωση εισόδου: 2. c a d 3. c a d 3.1. c a d (backtracking) 4. c a d
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-5 Υλοποίηση ΣΑ από πάνω προς τα κάτω Για κάθε μη τερματικό σύμβολο της γραμματικής υλοποιούμε μία συνάρτηση (recursive descent parsing). Έτσι, για ένα κανόνα της μορφής A=“a”, B| “c”, D ; η συνάρτηση που αντιστοιχεί στο Α καλεί τη συνάρτηση Β αν επόμενο σύμβολο εισόδου είναι το “a”, ή την D αν επόμενο σύμβολο εισόδου είναι το “c”. Όταν ολοκληρωθεί η εκτέλεση της συνάρτησης που αντιστοιχεί στο S, και δεν υπάρχει άλλο σύμβολο εισόδου, η αναγνώριση είναι επιτυχής. Προβλήματα: –Κανόνες A = A, Β (αριστερά αναδρομικοί) –Οπισθοδρόμηση (Backtracking)
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-6 Απαλειφή της αριστερής αναδρομικότητας Μία γραμματική ονομάζεται αριστερά αναδρομική αν υπάρχει παραγωγή της μορφής όπου Α V N και Χ V * Απαλειφή άμεσης αναδρομικότητας. Αν A = A, a 1 | A, a 2 |... | A, a m | β 1 | β 2 |... | β n ; όπου τα β ι δεν αρχίζουν με το Α, και α ι != ε, τότε αντικαθιστούμε τους παραπάνω κανόνες με τους εξής: Α = β 1, Α’ | β 2, Α’ |... | β n, Α’ ; Α’= a 1, Α’ | a 2, Α’ |... | a m, Α’ | “” ; Έμμεση αναδρομικότητα: S = A, “a” ; A = S, “b” | “b” ;
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-7 Παράδειγμα Π.χ. Ε = Ε, “+”, Τ | Τ ; Τ = Τ, “*”, F | F ; F = “(”,E, “)” | id ; Ε = T, E’ ; E’ = “+”, Τ, E’ | ε ; Τ = F, T’ ; Τ’ = “*”, F, T’ | ε ; F = “(”,E, “)” | id ;
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-8 Απάλειψη της έμμεσης αρ. αναδρομικότητας Δοθέντος γραμματικής χωρίς κύκλους (Α Α) και παραγωγές ε, και με μη-τερματικά σύμβολα Α 1, Α 2, …, Α n : for i=1 to n { for j=1 to i-1 { replace each production of the form A i = A j, g by the productions A i = h 1, g| h 2, g| … | h k,g where A j = h 1 | h 2 | … | h k are all the current productions of A j } eliminate immediate left recursion in A i productions }
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-9 Παράδειγμα S = A, “a” | “b” ; A = A, “c” | S, “d” | ε ; i=1 i=2, j=1 S = A, “a” | “b” ; A = A, “c” | A, “a”, “d” | “b”, “d” | ε ; S = A, “a” | “b” ; A = “b”, “d”, A’ | A’ ; A’ = “c”, A’ | “a”, “d”, A’ | ε ; Σημ.: Ο αλγόριθμος εργάζεται παρόλη την παραγωγή ε. Τυπικά θα έπρεπε να ξαναγραφτεί η γραμματική ώστε να μην υπάρχει παραγωγή ε.
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-10 Αριστερή παραγοντοποίηση Η αριστερή παραγοντοποίηση (left factoring) έχει στόχο την αποφυγή της οπισθοδρόμησης. Αλγόριθμος: 1. Για κάθε μη τερματικό Α βρες το μεγαλύτερο κοινό πρόθεμα α των κανόνων παραγωγής του. Π.χ. Α = α, Β 1 | α, Β 2 | … | α, Β n | c ; όπου c τα δεξιά μέλη που δεν έχουν πρόθεμα το α. 2. Αντικατέστησε τους παραπάνω κανόνες με τους Α = α, Α’ | c ; Α’ = Β 1 | Β 2 | … | Β n ; όπου Α’ νέο μη τερματικό σύμβολο. 3. Επανέλαβε τα παραπάνω μέχρι να μην υπάρχουν εναλλακτικοί κανόνες με κοινό πρόθεμα.
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-11 ΣΑ με πρόβλεψη (predictive parsing) ΣΑ από πάνω-προς-τα-κάτω ο οποίος δεν εκτελεί οπισθοδρόμηση. Αυτό συνεπάγεται την ύπαρξη μίας μόνο παραγωγής για κάθε ζευγάρι μη τερματικής κατάστασης - συμβόλου εισόδου. Απαραίτητοι μετασχηματισμοί γραμματικής: –Απάλειψη αριστερής αναδρομής –Αριστερή παραγοντοποίηση Παράδειγμα τέτοιας γραμματικής: stmt = “if”, expr, “then”, stmt, “else”, stmt | “while”, expr, “do”, stmt | “begin”, stmt_list, “end” ;
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-12 Aναδρομική ΣΑ με πρόβλεψη (recursive predictive parsing) Υλοποίηση του ΣΑ με αναδρομικές συναρτήσεις: e() { /* Ε = T, E’ */ t(); e_prime(); } e_prime() { /* E’ = “+”, Τ, E’ | ε */ if(c == “+”) {advance(); t(); e_prime();} } t() { /* Τ = F, T’ */ f(); t_prime(); } t_prime() { /* Τ’ = “*”, F, T’ | ε */ if(c == “*”) {advance(); f(); t_prime();} }
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-13 Aναδρομική ΣΑ με πρόβλεψη (2) f() { /* F = (E) | id */ if(c == “(”) {advance(); e(); if(c==“)”) advance(); else error(); } else if(c== ID) advance(); else error(); } όπου error() επιστρέφει μήνυμα λάθους advance() καταναλώνει ένα σύμβολο εισόδου c το σύμβολο εισόδου
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-14 Μη αναδρομική ΣΑ με πρόβλεψη Non-recursive predictive parsing. Υλοποίηση με χρήση στοίβας και πίνακα συντακτικής ανάλυσης (parsing table): $ : τερματικό σύμβολο που παριστάνει το τέλος της εισόδου
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-15 Μη αναδρομική ΣΑ με πρόβλεψη (2) Έστω Χ το σύμβολο στην κορυφή της στοίβας, α το σύμβολο εισόδου και Μ ο διδιάστατος συντακτικός πίνακας. Η λειτουργία του συντ. αναλυτή ακολουθεί τους κανόνες: 1. Τοποθέτησε το $ και S στη στοίβα και επανέλαβε τα Αν Χ = α = $ τότε η συμβολοσειρά εισόδου αναγνωρίστηκε. 3. Αν Χ = α != $ τότε αφαίρεσε το Χ από τη στοίβα και προχώρησε στο επόμενο σύμβολο εισόδου. 4. Αν Χ μη τερματικό και Μ[Χ, α] = { Χ = U,Z,W } όπου U,Z,W V *, τότε αφαίρεσε το Χ από τη στοίβα και τοποθέτησε διαδοχικά τα W,Z, U στη στοίβα (U στη κορυφή).
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-16 Παράδειγμα Πώς θα προχωρήσει η αναγνώριση της συμβολοσειράς: id + id * id$
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-17 Κατασκευή του συντακτικού πίνακα Έστω ο κανόνας παραγωγής X = a όπου a V * Ο κανόνας αυτός θα πρέπει να εισαχθεί σε κάθε θέση του πίνακα M, η οποία δεικτοδοτείται από το σύμβολο X και τα τερματικά σύμβολα από τα οποία είναι δυνατό να ξεκινά το a. Επίσης, αν υπάρχει παραγωγή με την οποία a ε (nullable), πρέπει να τοποθετηθεί ο παραπάνω κανόνας και σε όλα τα κελιά του Μ τα οποία δεικτοδοτούνται από το Χ και τα τερματικά σύμβολα τα οποία είναι δυνατό να ακολουθούν το Χ. Αν με την παραπάνω κατασκευή κάθε στοιχείο του πίνακα περιέχει το πολύ ένα κανόνα, είναι δυνατή η χρήση ΣΑ με πρόβλεψη.
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-18 Συνάρτηση FIRST Έστω το σύμβολο Χ. Η συνάρτηση FIRST(X) επιστρέφει το σύνολο των τερματικών συμβόλων (συμπεριλαμβανομένου του ε) με τα οποία είναι δυνατό να ξεκινά το Χ. Υπολογισμός της FIRST(X): 1. Αν Χ είναι τερματικό τότε FIRST(X) = { X } 2. Αν υπάρχει παραγωγή Χ ε, τότε ε FIRST(X). 3. Αν υπάρχει κανόνας Χ=Y 1,Y 2,…,Y K τότε FIRST(Y j ) FIRST(X), για κάθε j i, όπου υπάρχει παραγωγή Υ j ε και ε FIRST(Y i ).
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-19 Συνάρτηση FOLLOW Έστω το σύμβολο Χ. Η συνάρτηση FΟLLOW(X) επιστρέφει το σύνολο των τερματικών συμβόλων (συμπεριλαμβανομένου του $) τα οποία είναι δυνατό να ακολουθούν το Χ. Υπολογισμός της FΟLLOW(X): 1. $ FΟLLOW( S ). 2. Αν Χ = a, B, c τότε FIRST(c) - {ε} FOLLOW(B). 3. Αν Χ = a, B τότε FOLLOW(Χ) FOLLOW(B)
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-20 Παράδειγμα Έστω η γραμματική: Ε = T, E’ ;E’ = “+”, Τ, E’ | ε ; Τ = F, T’ ;Τ’ = “*”, F, T’ | ε ; F = “(”,E, “)” | id ; Τότε: FIRST(E) = FIRST( Τ, Ε’) = FIRST(Τ) = = FIRST(F) = {“(”, id} FIRST(E’) = FIRST(“+”, Τ, E’) {ε}={“+”, ε} FIRST(T’) = FIRST(“*”, F, T’ ) {ε}={“*”, ε}
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-21 Παράδειγμα (συνέχεια) Ε = T, E’;E’ = “+”, Τ, E’ | ε ; Τ = F, T’;Τ’ = “*”, F, T’ | ε ; F = “(”,E, “)” | id ; Επίσης : FOLLOW(E) = { $, “)”} FOLLOW(E) FOLLOW(E’) = { $, “)”} FOLLOW(T) = (FIRST(E’) -{ε}) FOLLOW(E) FOLLOW(E’) = {“+”, $, “)” } FOLLOW(T) FOLLOW(T’) = {“+”, $, “)” } FOLLOW(F) = (FIRST(T’)-{ε}) FOLLOW(T) = = { “*”, “+”, $, “)” }
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-22 Συμπληρώνοντας το συντ. πίνακα Αλγόριθμος: 1. Για κάθε κανόνα παραγωγής Χ=α της γραμματικής εκτέλεσε τα βήματα 2, Για κάθε τερματικό β ε που ανήκει στο σύνολο FIRST(α), εισήγαγε την παραγωγή Χ=α στη θέση M[X, β] 3. Αν ε FIRST(α), εισήγαγε την παραγωγή Χ=α στις θέσεις M[X, β], όπου β FOLLOW(X). 4. Αν ε FIRST(α) και $ FOLLOW(X), εισήγαγε την παραγωγή Χ=ε στη θέση M[X, $]
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-23 Γραμματικές LL(1) Οι γραμματικές που ο συντακτικός τους πίνακας περιέχει το πολύ μία παραγωγή σε κάθε κελί, ονομάζονται LL(1). L : “Left to right scanning”, δηλ. ανάγνωση εισόδου από αριστερά προς τα δεξιά L : “Left to right derivation”, δηλ. αριστερότερη παραγωγή (1) : “one look-ahead symbol”, δηλ. ένα μόνο σύμβολο εισόδου καθορίζει την εκτέλεση του ΣΑ
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-24 Χαρακτηριστικά γραμμ. LL(1) Οι μετασχηματισμοί που απαιτούνται για την δημιουργία μίας γραμμ. LL(1) είναι δυνατό να οδηγήσουν σε μία γραμματική που είναι δύσκολο να διαβαστεί. Υπάρχουν γραμματικές που η απάλειψη της αριστερής αναδρομικότητας και η αριστερή παραγοντοποίηση δεν αναιρούν την ασάφεια, π.χ: S = “if”, E, “then”, S, S’ | “a” ; S’ = “else”, S | ε ; Ε = “b” ;
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-25 Ανάνηψη από λάθη (γενικά) Πολιτικές: –Είσοδος σε λειτουργία πανικού (panic mode) : απόρριψη των ΛΜ που ακολουθούν μέχρι να βρεθεί ΛΜ συγχρονισμού (π.χ. ‘;’ στη C) –Επιδιόρθωση σε επίπεδο πρότασης (phrase level recovery) : εισαγωγή ή διαγραφή κατάλληλης συμβολοσειράς –Παραγωγές λάθους (error productions) : κατασκευή κανόνων παραγωγής που περιγράφουν τα πιο συνηθισμένα λάθη –Ολική διόρθωση (global correction) : εύρεση των ελάχιστων αλλαγών που πρέπει να γίνουν ώστε να παράγεται συντακτικό δένδρο
ΕΠΛ Θεωρία και Πρακτική Μεταγλωττιστών5-26 Είσοδος σε λειτουργία πανικού: χρησιμοποίηση των τερματικών του συνόλου FOLLOW(X) για συγχρονισμό. Αν α σύμβολο εισόδου και Μ[Χ,α]=error, κατανάλωσε το α. Αν α σύμβολο εισόδου και Μ[Χ,α]=sync, αφαίρεσε το Χ από τη στοίβα. Ανάνηψη στην ΣΑ με πρόβλεψη