210 likes | 350 Vues
ΘΠ06 - Μεταγλωττιστές. Ανάνηψη από σφάλματα κατά τη συντακτική ανάλυση. Ανάνηψη από σφάλματα. Διαδικασία κατά την οποία ανιχνεύεται ένα συντακτικό σφάλμα και συνεχίζεται η ανάλυση για την ανίχνευση περισσότερων λαθών. Τεχνικές ανάνηψης: Error Recovery Error Repair Error Correction.
E N D
ΘΠ06 - Μεταγλωττιστές Ανάνηψη από σφάλματα κατά τη συντακτική ανάλυση
Ανάνηψη από σφάλματα • Διαδικασία κατά την οποία ανιχνεύεται ένα συντακτικό σφάλμα και συνεχίζεται η ανάλυση για την ανίχνευση περισσότερων λαθών. • Τεχνικές ανάνηψης: • Error Recovery • Error Repair • Error Correction
Error Recovery • Ανίχνευση συντακτικού λάθους. • Αγνόηση μέρους της εισόδου. • Aρχικοποίηση περιβάλλοντος αναλυτή (στοίβα, μεταβλητές) για την ανάλυση της υπόλοιπης συμβολοσειράς εισόδου. • Μπορεί να οδηγήσει σε ανίχνευση επόμενων λαθών που δεν είναι στην πραγματικότητα λάθη (cascaded errors) => ποιότητα ανάνηψης από σφάλματα. • Οι φάσεις της σημασιολογικής ανάλυσης και της παραγωγής ενδιάμεσου κώδικα απενεργοποιούνται. • Panic Mode: αναζήτηση για ένα ασφαλές σύμβολο (π.χ. ‘;’) από το οποίο επανεκκινείται η συντακτική ανάλυση.
Error Repair • Διαδικασία κατά την οποία ανιχνεύεται ένα σφάλμα και τροποποιείται το κομμάτι της συμβολοσειράς που έχει ήδη αναλυθεί ή το επόμενο του με σκοπό την παραγωγή μίας έγκυρης εισόδου. • Εισαγωγή/διαγραφή τερματικών συμβόλων. • x=a b+c; //εισαγωγή του συμβόλου ‘=‘ ή ’+’ κτλ. μετά το a • Οι επόμενες φάσεις συνεχίζονται κανονικά. • Διορθωμένα συντακτικά σφάλματα μπορεί να δημιουργήσουν σφάλματα για τις επόμενες φάσεις.
Error Correction • Ό,τι και στην τεχνική του Error Repair με τη διαφορά ότι οι τροποποιήσεις της εισόδου αντικατοπτρίζουν το τί ήθελε ο χρήστης να γράψει.
Error Recovery στον Bison (1/3) • Προκαθορισμένη συμπεριφορά κατά την ανίχνευση σφάλματος: • κλήση yyerror()για την εκτύπωση διαγνωστικού μηνύματος • τερματισμός • %error-verbose: οδηγία για πιο κατατοπιστικά μηνύματα • Η προκαθορισμένη συμπεριφορά δεν υλοποιεί Error Recovery.
Error Recovery στον Bison (2/3) • Ειδικό σύμβολο γραμματικής: error • Παράγεται όταν ανιχνευθεί ένα συντακτικό σφάλμα. • error: Όταν ανιχνευθεί σφάλμα, σηματοδοτεί μέχρι που θα πρέπει να αγνοηθεί η είσοδος, ώστε να συνεχίσει η συντακτική ανάλυση. • stmt: error ‘;’ ; // είσοδος y = d; x = a b; • Στοίβα: stmt‘x’ ‘=‘ ‘a’, lookahead: ‘b’ • Ανιχνεύεται σφάλμα=> • εξάγονται τα ‘x’, ‘=‘, ‘a (Στοίβα: stmt) • shift του error (Στοίβα: stmterror) • διαγραφή ‘b’, lookahead: ‘;’ • Στοίβα: stmt error ‘;’ => Στοίβα: stmt stmt
Error Recovery στον Bison (3/3) • error: Μόλις ενεργοποιηθεί το σύμβολο καλείται η yyerror() • yyerrok: μακροεντολή για την ένδειξη τέλους φάσης Error Recovery • Φειδώ στη χρήση του error: • δημιουργία συγκρούσεων • αναφορά λαθών που δεν υπάρχουν • “Error recovery strategies are necessarily guesses. When they guess wrong, one syntax error often leads to another.”
Παράδειγμα v1.0 (1/3) %{ #include <stdio.h> void yyerror (char const *s); extern int num_lines; %} %token TK_NUM TK_ID TK_BADID %left '-' '+' %left '*' '/' %left TK_NEG /* negation--unary minus */ %right '^' /* exponentiation */ %% /* The grammar follows. */ input: /* empty */ | input line ; line: ';' | exp ';' ;
Παράδειγμα v1.0 (2/3) exp: TK_NUM | TK_ID | exp '+' exp {printf("exp + exp\n");} | exp '-' exp {printf("exp - exp\n");} | exp '*' exp {printf("exp * exp\n");} | exp '/' exp {printf("exp / exp\n");} | '-' exp %prec TK_NEG {printf("-exp\n");} | exp '^' exp {printf("exp ^ exp\n");} | '(' exp ')' {printf("( exp )\n");} ; %% int main(void) { return yyparse(); } void yyerror (char const *s) { printf("%d: %s\n", num_lines, s); }
Παράδειγμα v1.0 (3/3) Είσοδος: 1. sdf 1234; 2. 234fsdf + 234; 3. 1234 + asf; 4. (2345); 5. (asdf; 6. 1243 + 234; 7. 234); 8. 234 * 234; Έξοδος: 1: syntax error
Παράδειγμα v1.1 Προσθήκη: %error-verbose Είσοδος: 1. sdf 1234; 2. 234fsdf + 234; 3. 1234 + asf; 4. (2345); 5. (asdf; 6. 1243 + 234; 7. 234); 8. 234 * 234; Έξοδος: 1: syntax error, unexpected TK_NUM
Παράδειγμα v1.2 (1/2) %{ #include <stdio.h> void yyerror (char const *s); extern int num_lines; %} %error-verbose %token TK_NUM TK_ID TK_BADID %left '-' '+' %left '*' '/' %left TK_NEG /* negation--unary minus */ %right '^' /* exponentiation */ %% /* The grammar follows. */ input: /* empty */ | input line ; line: ';' | exp ';‘ | error ';‘ {yyerrok;} ;
Παράδειγμα v1.2 (2/2) Είσοδος: 1. sdf 1234; 2. 234fsdf + 234; 3. 1234 + asf; 4. (2345); 5. (asdf; 6. 1243 + 234; 7. 234); 8. 234 * 234; Έξοδος: • 1: syntax error, unexpected TK_NUM • 2: syntax error, unexpected TK_BADID • exp + exp • ( exp ) • 5: syntax error, unexpected ';' • exp + exp • 7: syntax error, unexpected ')' • exp * exp
Παράδειγμα v1.3 (1/2) exp: TK_NUM | TK_ID | TK_BADID {yyerror("invalid ID"); YYERROR; yyerrok;} | exp '+' exp {printf("exp + exp\n");} | exp '-' exp {printf("exp - exp\n");} | exp '*' exp {printf("exp * exp\n");} | exp '/' exp {printf("exp / exp\n");} | '-' exp %prec TK_NEG {printf("-exp\n");} | exp '^' exp {printf("exp ^ exp\n");} | '(' exp ')' {printf("( exp )\n");} ; %% int main(void) { return yyparse(); } void yyerror (char const *s) { printf("%d: %s\n", num_lines, s); }
Παράδειγμα v1.3 (2/2) Είσοδος: 1. sdf 1234; 2. 234fsdf + 234; 3. 1234 + asf; 4. (2345); 5. (asdf; 6. 1243 + 234; 7. 234); 8. 234 * 234; Έξοδος: • 1: syntax error, unexpected TK_NUM • 2: invalid ID • exp + exp • ( exp ) • 5: syntax error, unexpected ';' • exp + exp • 7: syntax error, unexpected ')' • exp * exp
Παράδειγμα v1.4 (1/2) %{ #include <stdio.h> void yyerror (char const *s); extern int num_lines; %} %error-verbose %token TK_NUM TK_ID TK_BADID %left '-' '+' %left '*' '/' %left TK_NEG /* negation--unary minus */ %right '^' /* exponentiation */ %% /* The grammar follows. */ input: /* empty */ | input line; line: ';' | exp ';‘ | exp error exp ';' {yyerror("missing arithmetic operator or ';'"); yyerrok;} | error ';‘ {yyerrok;} ;
Παράδειγμα v1.4 (2/2) Είσοδος: 1. sdf 1234; 2. 234fsdf + 234; 3. 1234 + asf; 4. (2345); 5. (asdf; 6. 1243 + 234; 7. 234); 8. 234 * 234; Έξοδος: • 1: syntax error, unexpected TK_NUM • 1: missing arithmetic operator or ';' • 2: invalid ID • exp + exp • ( exp ) • 5: syntax error, unexpected ';‘ • exp + exp • 7: syntax error, unexpected ')' • exp * exp • 8: missing arithmetic operator or ';'
Παράδειγμα v1.5 (1/2) exp: TK_NUM | TK_ID | TK_BADID {yyerror("invalid ID"); YYERROR; yyerrok;} | exp '+' exp {printf("exp + exp\n");} | exp '-' exp {printf("exp - exp\n");} | exp '*' exp {printf("exp * exp\n");} | exp '/' exp {printf("exp / exp\n");} | '-' exp %prec TK_NEG {printf("-exp\n");} | exp '^' exp {printf("exp ^ exp\n");} | '(' exp ')' {printf("( exp )\n");} | '(' exp error {yyerror("Missing operator ')'");yyerrok;} ; %% int main(void) { return yyparse(); } void yyerror (char const *s) { printf("%d: %s\n", num_lines, s); }
Παράδειγμα v1.5 (2/2) Είσοδος: 1. sdf 1234; 2. 234fsdf + 234; 3. 1234 + asf; 4. (2345); 5. (asdf; 6. 1243 + 234; 7. 234); 8. 234 * 234; Έξοδος: • 1: syntax error, unexpected TK_NUM • 1: missing arithmetic operator or ';' • 2: invalid ID • exp + exp • ( exp ) • 5: syntax error, unexpected ';‘ • 5: Missing operator ')' • exp + exp • 7: syntax error, unexpected ')' • exp * exp • 8: missing arithmetic operator or ';'
Αναφορές • Εγχειρίδιο χρήσης Bison. http://www.gnu.org/software/bison/manual/html_mono/bison.html.gz . • Charles Fischer, University of Wisconsin, Richard LeBlanc.Crafting a Compiler with C.Addison-Wesley, 1991.