Σχολή Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών Εθνικό Μετσόβιο Πολυτεχνείο Μεταγλωττιστές Νίκος Παπασπύου, Κωστής Σαγώνας Συντακτική ανάλυση (μέρος 1ον)
Άδεια Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άδεια χρήσης άλλου τύπου, αυτή πρέπει να αναφέρεται ρητώς.
ÓõíôáêôéêÞ áíüëõóç Óõíôáêôéêü äýíôñï (parse tree) ÊáôáóêåõÜæåôáé ìå äýï ôñüðïõò: ÊáèïäéêÜ Áðü ðüíù ðñïò ôá êüôù (top-down) äçëáäþ îåêéíþíôáò áðü ôç ñßæá êáé ðñï ùñþíôáò ðñïò ôá öýëëá ÁíïäéêÜ Áðü êüôù ðñïò ôá ðüíù (bottom-up) äçëáäþ îåêéíþíôáò áðü ôá öýëëá êáé ðñï ùñþíôáò ðñïò ôç ñßæá 3
Top-down êáé bottom-up από πάνω προς τα κάτω (top-down) 1 S 2 3 11 a A B c 13 4 A b 10 12 a 5 6 c S 8 B 7 ε 9 a 4
Top-down êáé bottom-up από πάνω προς τα κάτω (top-down) 1 S από κάτω προς τα πάνω (bottom-up) 12 S 2 3 11 a A B c 13 10 a A B c 1 8 11 4 A b 10 12 a 6 A b 7 9 a 5 6 c S 8 B 2 c 5 S B 4 7 ε 9 a ε a 3 5
ÂïçèçôéêÝò Ýííïéåò (i) Óýíïëá FIRST óôù óõìâïëïóåéñü α (T N) Ôï óýíïëï FIRST(α) T { ɛ } ðåñéý åé ôá ôåñìáôéêü óýìâïëá áðü ôá ïðïßá áñ ßæïõí ïé óõìâïëïóåéñýò ðïõ ðáñüãïíôáé áðü ôçí α 6
ÂïçèçôéêÝò Ýííïéåò (i) Óýíïëá FIRST óôù óõìâïëïóåéñü α (T N) Ôï óýíïëï FIRST(α) T { ɛ } ðåñéý åé ôá ôåñìáôéêü óýìâïëá áðü ôá ïðïßá áñ ßæïõí ïé óõìâïëïóåéñýò ðïõ ðáñüãïíôáé áðü ôçí α Áí α aβ ôüôå a FIRST(α) Áí α ɛ ôüôå ɛ FIRST(α) 7
ÂïçèçôéêÝò Ýííïéåò (ii) Óýíïëá FOLLOW óôù ìç ôåñìáôéêü óýìâïëï A Ôï óýíïëï FOLLOW(A) T { EOF } ðåñéý åé ôá ôåñìáôéêü óýìâïëá ðïõ ìðïñïýí íá áêïëïõèïýí ôï A óôç äéüñêåéá ìéáò ðáñáãùãþò Áí ôï A ìðïñåß íá åßíáé ôï ôåëåõôáßï óýìâïëï óå ìéá ðáñáãùãþ, ôüôå EOF FOLLOW(A) 8
ÂïçèçôéêÝò Ýííïéåò (ii) Óýíïëá FOLLOW óôù ìç ôåñìáôéêü óýìâïëï A Ôï óýíïëï FOLLOW(A) T { EOF } ðåñéý åé ôá ôåñìáôéêü óýìâïëá ðïõ ìðïñïýí íá áêïëïõèïýí ôï A óôç äéüñêåéá ìéáò ðáñáãùãþò Áí ôï A ìðïñåß íá åßíáé ôï ôåëåõôáßï óýìâïëï óå ìéá ðáñáãùãþ, ôüôå EOF FOLLOW(A) Áí S αaaβ ôüôå a FOLLOW(A) Áí S αa ôüôå EOF FOLLOW(A) 9
Õðïëïãéóìüò FIRST (i) FIRST(ɛ) = { ɛ } FIRST(aβ) = { a } áí ɛ FIRST(A) ôüôå FIRST(Aβ) = FIRST(A) áí ɛ FIRST(A) ôüôå FIRST(Aβ) = (FIRST(A) { ɛ }) FIRST(β) ãéá êüèå êáíüíá A α, ðñýðåé FIRST(α) FIRST(A) 10
Õðïëïãéóìüò FIRST (ii) ÐáñÜäåéãìá FIRST(E) = { id, ( } FIRST(T) = { id, ( } FIRST(F) = { id, ( } FIRST(E ) = { +, ɛ } FIRST(T ) = { *, ɛ } E T E E ɛ E + T E T F T T ɛ T * F T F ( E ) F id 11
Õðïëïãéóìüò FOLLOW (i) EOF FOLLOW(S) ãéá êüèå êáíüíá A αbβ (FIRST(β) { ɛ }) FOLLOW(B) áí ɛ FIRST(β) ôüôå FOLLOW(A) FOLLOW(B) 12
Õðïëïãéóìüò FOLLOW (ii) ÐáñÜäåéãìá FOLLOW(E) = { ), EOF } FOLLOW(T) = { +, ), EOF } FOLLOW(F) = { *, +, ), EOF } FOLLOW(E ) = { ), EOF } FOLLOW(T ) = { +, ), EOF } FIRST(E ) = { +, ɛ } FIRST(T ) = { *, ɛ } E T E E ɛ E + T E T F T T ɛ T * F T F ( E ) F id 13
ÓÁ bottom-up (i) Ç óõíôáêôéêþ áíüëõóç îåêéíü áðü ôá öýëëá ÊÜèå öïñü, áíáæçôü: ôïí áñéóôåñüôåñï êüìâï ôïõ äýíôñïõ ðïõ äåí Ý åé áêüìá êáôáóêåõáóôåß åíþ üëá ôá ðáéäéü ôïõ Ý ïõí êáôáóêåõáóôåß ÅðáíáëáìâÜíåé ìý ñé íá êáôáóêåõáóôåß ç ñßæá ÅëÜôôùóç (reducing): ç åðéëïãþ ôùí êüìâùí ðïõ èá áðïôåëýóïõí ôá ðáéäéü åíüò íýïõ êüìâïõ 14
ÓÁ bottom-up (ii) B B D D D D r a. b r a. b r a. b S r B B D B, D D a b B B S B B D D D D r a. b r a. b 15
ÓÁ bottom-up (iii) ÓÁ ïëßóèçóçò-åëüôôùóçò (shift-reduce) ñçóéìïðïéïýí ìéá (áñ éêü êåíþ) óôïßâá üðïõ ôïðïèåôïýí óýìâïëá ôçò ãñáììáôéêþò Ïëßóèçóç (shift): ìåôáöïñü åíüò óõìâüëïõ áðü ôçí åßóïäï óôçí êïñõöþ ôçò óôïßâáò ÅëÜôôùóç (reduce): áöáßñåóç áðü ôçí êïñõöþ ôçò óôïßâáò ôïõ äåîéïý ìýëïõò åíüò êáíüíá êáé ðñüóèåóç ôïõ áñéóôåñïý ìýëïõò Åðéôõ ßá: ç óôïßâá ðåñéý åé ìüíï ôï S êáé ôá óýìâïëá ôçò åéóüäïõ Ý ïõí åîáíôëçèåß 16
ÓÁ bottom-up 17 (iv) âþìá óôïßâá åßóïäïò êßíçóç 0 ɛ r a, b ïëßóèçóç 1 r a, b ïëßóèçóç 2 r a, b åëüôôùóç ìå D a 3 r D, b åëüôôùóç ìå B D 4 r B, b ïëßóèçóç (ü é åëüôôùóç ìå S r B) 5 r B, b ïëßóèçóç 6 r B, b ɛ åëüôôùóç ìå D b 7 r B, D ɛ åëüôôùóç ìå B B, D (ü é åëüôôùóç ìå B D) 8 r B ɛ åëüôôùóç ìå S r B 9 S ɛ áíáãíþñéóç S r B B D B, D D a b
ÓÁ bottom-up (v) συµβολοσειρά εισόδου a 1 a 2... a n EOF LR(k) επόµενο σύµβολο LR(0) SLR(1) LALR(1) LR(1) s m x m... κορυφή Πίνακες ελέγχου συντακτικής ανάλυσης LR(1) s 1 ACTION NEXT x 1 Συντακτικός Αναλυτής LR(1) s 0 18 στοίβα
Õëïðïßçóç ÓÁ ìå ôï bison (i) Ìåôáåñãáëåßï bison: ãåííþôïñáò ÓÁ LALR(1) Åßóïäïò: ìåôáðñüãñáììá ðïõ ðåñéãñüöåé ôç óýíôáîç êáé ôéò óçìáóéïëïãéêýò ñïõôßíåò îïäïò: ðñüãñáììá óå C Ç óõíüñôçóç yyparse õëïðïéåß ôï ÓÁ ÅðéóôñÝöåé 0 áí áíáãíùñéóôåß ç óõìâïëïóåéñü åéóüäïõ Þ 1 óå ðåñßðôùóç óõíôáêôéêïý óöüëìáôïò ÓõíåñãÜæåôáé ìå ôï ëåêôéêü áíáëõôþ (óõíüñôçóç yylex) 19
Õëïðïßçóç ÓÁ ìå ôï bison (ii) ÄïìÞ ôïõ ìåôáðñïãñüììáôïò ÌÝñïò Á %% ÌÝñïò Â %% ÌÝñïò Ã Êáé ôá ôñßá ìýñç ìðïñïýí íá åßíáé êåíü 20
Õëïðïßçóç ÓÁ ìå ôï bison (iii) ÌÝñïò Á, ðåñéý åé Ó üëéá, üðùò óôç C Êþäéêá C, ìýóá óå %{ êáé %} Äçëþóåéò ëåêôéêþí ìïíüäùí Äçëþóåéò ôåëåóôþí ôçò áñ éêþò ãëþóóáò (ðñïôåñáéüôçôá, ðñïóåôáéñéóôéêüôçôá) ÄÞëùóç ôïõ óõíüëïõ óçìáóéïëïãéêþí ôéìþí (ôýðïò YYSTYPE Þ ìå ñþóç ôïõ %union) ÄÞëùóç ôïõ ôýðïõ ôçò óçìáóéïëïãéêþò ôéìþò êüèå óõìâüëïõ 21
Õëïðïßçóç ÓÁ ìå ôï bison (iv) ÌÝñïò Á, ðáñüäåéãìá %{ void ERROR (const char msg []); %} %token T_program "program" %token T_div T_mod %token T_if T_then T_else %nonassoc '=' '<' '>' %left '+' '-' %left '*' '/' T_div T_mod 22
Õëïðïßçóç ÓÁ ìå ôï bison (v) ÌÝñïò Á, ðáñüäåéãìá (óõíý åéá) %union{ int i; double f; char str[80]; } %token<str> T_id %token<i> T_int_const %token<f> T_float_const %type<f> expression 23
Õëïðïßçóç ÓÁ ìå ôï bison (vi) ÌÝñïò Â, ðåñéý åé: ôïõò êáíüíåò ðáñáãùãþò óå ìïñöþ BNF óçìáóéïëïãéêýò ñïõôßíåò ðïõ åêôåëïýíôáé êáôü ôç óõíôáêôéêþ áíüëõóç Ïé êáíüíåò Ý ïõí ôç ìïñöþ: A : x 1 1 x 1 2... x 1 m 1 x 2 1 x 2 2...... x 2 m 2 x n 1 x n 2... x n m n ; 24
Õëïðïßçóç ÓÁ ìå ôï bison (vii) ÌÝñïò Â, ðáñüäåéãìá program : { count=0; } block_list { printf("counted %d block(s)\n", count); } ; block_list : /* nothing */ block_list block { count++; } ; block : "begin" block_list "end" ; 25
Õëïðïßçóç ÓÁ ìå ôï bison (viii) ÌÝñïò Ã, ðåñéý åé êþäéêá C Ôï ìåôáðñüãñáììá ôïõ bison áíáëáìâüíåé ôïí êåíôñéêü Ýëåã ï ôïõ ìåôáãëùôôéóôþ ðïõ åðéôõã Üíåôáé ìå ôç óõíåñãáóßá ôùí ðáñáêüôù: ôïõ ëåêôéêïý áíáëõôþ ôïõ óõíôáêôéêïý áíáëõôþ ôïõ ðßíáêá óõìâüëùí ôïõ óçìáóéïëïãéêïý áíáëõôþ ôïõ ãåííþôïñá åíäéüìåóïõ êþäéêá 26
Õëïðïßçóç ÓÁ ìå ôï bison (ix) ÌÝñïò Ã, ðáñüäåéãìá void yyerror (const char * msg) { fprintf(stderr, "syntax error in line %d: %s\n", linecount, msg); exit(1); } 27 int main () { return yyparse(); }
Õëïðïßçóç ÓÁ ìå ôï bison (x) ÐáñÜäåéãìá ìå óçìáóéïëïãéêýò ôéìýò E T E E + T T F T T * F F ( E ) F num Æçôïýìåíï: íá êáôáóêåõáóôåß ÓÁ ðïõ íá õðïëïãßæåé ôçí ôéìþ ìéáò áñéèìçôéêþò Ýêöñáóçò 28
Õëïðïßçóç ÓÁ ìå ôï bison (xi) ÐáñÜäåéãìá (óõíý åéá) %{ typedef int YYSTYPE; %} %token T_num %% program : expression { printf("value: %d\n", $1); } ; 29
Õëïðïßçóç ÓÁ ìå ôï bison (xii) ÐáñÜäåéãìá (óõíý åéá) expression : term { $$ = $1; } expression '+' term { $$ = $1 + $3; } ; term : factor { $$ = $1; } term '*' factor { $$ = $1 * $3; } ; 30
Õëïðïßçóç ÓÁ ìå ôï bison (xiii) ÐáñÜäåéãìá (óõíý åéá) factor : '(' expression ')' { $$ = $2; } T_num { $$ = $1; } ; %% Ðáñáëåßðïíôáé óôï ÌÝñïò Ã: ç óõíüñôçóç yylex (ðéèáíþò óå îå ùñéóôü áñ åßï, áí ñçóéìïðïéçèåß ôï ex) ïé óõíáñôþóåéò yyerror êáé main 31
Õëïðïßçóç ÓÁ ìå ôï bison (xiv) ÐáñÜäåéãìá Õëïðïßçóç ËÁ åéñùíáêôéêü int yylex () { int c; 32 while (isspace(c = fgetc(stdin))); if (isdigit(c)) { yylval = c - '0'; while (isdigit(c = fgetc(stdin))) yylval = yylval * 10 + c - '0'; ungetc(c, stdin); return T_num; } Óôï ìýñïò Ã
Õëïðïßçóç ÓÁ ìå ôï bison (xv) ÐáñÜäåéãìá } (óõíý åéá) if (strchr("+*()", c)) return c; if (c!= EOF) fprintf(stderr, "Illegal character: %c\n", c); return 0; Áõôïìáôïðïßçóç ôçò ìåôáãëþôôéóçò ôïõ ÓÁ mytest1: mytest1.y bison mytest1.y gcc -o mytest1 mytest1.tab.c Makele 33
Õëïðïßçóç ÓÁ ìå ôï bison (xvi) ÐáñÜäåéãìá Õëïðïßçóç ËÁ ìå ôï ex %{ #include "mytest2.tab.h" %} %% [0-9]+ { yylval = atoi(yytext); return T_num; } \( \) \+ \* { return yytext[0]; } [ \t\n]+ { /* nothing */ }. { yyerror("illegal character"); } 34 %% mytest2.l
Õëïðïßçóç ÓÁ ìå ôï bison (xvii) Áõôïìáôïðïßçóç ôçò ìåôáãëþôôéóçò ËÁ êáé ÓÁ mytest2: mytest2.l mytest2.y bison -d mytest2.y flex -s mytest2.l gcc -o mytest2 mytest2.tab.c lex.yy.c \ -lfl Åðßëõóç óõãêñïýóåùí óôï bison shift-reduce: ðüíôá shift reduce-reduce: ï ðñþôïò êáíüíáò Makele 35
ÓÁ top-down (i) Ç óõíôáêôéêþ áíüëõóç îåêéíü áðü ôç ñßæá ÊÜèå öïñü, áíáæçôü: ôï ìç ôåñìáôéêü óýìâïëï ðïõ èá áíôéêáôáóôáèåß óõíþèùò åðéëýãåôáé ôï áñéóôåñüôåñï ôïí êáíüíá ðáñáãùãþò ðïõ èá åöáñìïóôåß âüóåé ôùí åðüìåíùí k ëåêôéêþí ìïíüäùí óôç óõìâïëïóåéñü åéóüäïõ: LL(k) ÅðáíáëáìâÜíåôáé ìý ñé íá åîáíôëçèïýí ôá ìç ôåñìáôéêü 36
ÃñáììáôéêÝò LL(1) Áðáñáßôçôåò ðñïûðïèýóåéò: Áðïõóßá áñéóôåñþò áíáäñïìþò (Üìåóçò Þ Ýììåóçò) Áðïõóßá êïéíïý ðñïèýìáôïò óå åíáëëáêôéêïýò êáíüíåò ÌåñéêÝò öïñýò åßíáé äõíáôüò ï ìåôáó çìáôéóìüò ìéáò ãñáììáôéêþò óå éóïäýíáìç LL(1) áðáëïéöþ áñéóôåñþò áíáäñïìþò áñéóôåñþ ðáñáãïíôïðïßçóç 37
Ìåôáó çìáôéóìüò óå LL(1) ÁíôéêáôÜóôáóç A α 1... α n B β 1 Aβ 2 A α 1... α n B β 1 α 1 β 2... β 1 α n β 2 ÁñéóôåñÞ ðáñáãïíôïðïßçóç A αβ 1... αβ n A αb B β 1... β n ÁðáëïéöÞ Üìåóçò áñéóôåñþò áíáäñïìþò 38 A Aα 1... Aα n β 1... β m A β 1 B... β m B B α 1 B... α n B ɛ
ÓÁ áíáäñïìéêþò êáôüâáóçò 39 A α 1... α n ìåôáôñýðåôáé óå êþäéêá ôçò ìïñöþò: if token FIRST(α 1 ) then êþäéêáò ãéá ôçí áíáãíþñéóç ôçò α 1... else if token FIRST(α n ) then êþäéêáò ãéá ôçí áíáãíþñéóç ôçò α n else if ɛ FIRST(α 1 )... FIRST(α n ) then óõíôáêôéêü óöüëìá else if token FOLLOW(A) then óõíôáêôéêü óöüëìá end if
ÓÁ LL(1) (i) ñçóéìïðïéïýí ìéá óôïßâá üðïõ ôïðïèåôïýí óýìâïëá ôçò ãñáììáôéêþò áñ éêü ìüíï ôï S ÊÜèå öïñü åîåôüæåôáé ç êïñõöþ ôçò óôïßâáò: Áí åßíáé ôåñìáôéêü óýìâïëï êáé åßíáé ôï ßäéï ìå ôï åðüìåíï ôçò óõìâïëïóåéñüò åéóüäïõ, ôüôå áöáéñïýíôáé êáé ôá äýï Áí åßíáé ìç ôåñìáôéêü óýìâïëï, ôüôå áíüëïãá ìå ôï åðüìåíï ôçò óõìâïëïóåéñüò åéóüäïõ åöáñìüæåôáé êüðïéïò êáíüíáò Åðéôõ ßá: ç óôïßâá êáé ç óõìâïëïóåéñü åéóüäïõ åßíáé Üäåéåò 40
ÓÁ LL(1) (ii) συµβολοσειρά εισόδου a 1 a 2... a n EOF Ï áëãüñéèìïò êáôáóêåõþò ôïõ ðßíáêá M ïñßæåé ôçí ïéêïãýíåéá ôùí ãëùóóþí LL(1) x m... κορυφή επόµενο σύµβολο Πίνακας M συντακτικής ανάλυσης LL(1) x 2 x 1 στοίβα Συντακτικός Αναλυτής LL(1) 41
ÊáôáóêåõÞ ÓÁ LL(1) E T E E + T E ɛ T F T T * F T ɛ F ( E ) id FIRST(E) = FIRST(T) = FIRST(F) = { id, ( } FIRST(E ) = { +, ɛ } FIRST(T ) = { *, ɛ } FOLLOW(E) = FOLLOW(E ) = { ), EOF } FOLLOW(T) = FOLLOW(T ) = { +, ), EOF } FOLLOW(F) = { *, +, ), EOF } id + * ( ) EOF E E TE E TE E E +TE E ɛ E ɛ T T FT T FT T T ɛ T *FT T ɛ T ɛ F F id F (E) 42
Ëåéôïõñãßá ÓÁ LL(1) 43 0 E id + id * id EOF E T E 1 E T id + id * id EOF T F T 2 E T F id + id * id EOF F id 3 E T id id + id * id EOF 4 E T + id * id EOF T ɛ 5 E + id * id EOF E + T E 6 E T + + id * id EOF 7 E T id * id EOF T F T 8 E T F id * id EOF F id 9 E T id id * id EOF 10 E T * id EOF T * F T 11 E T F * * id EOF 12 E T F id EOF F id 13 E T id id EOF 14 E T EOF T ɛ 15 E EOF E ɛ 16 ɛ EOF áíáãíþñéóç
Χρηματοδότηση Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου του διδάσκοντα. Το έργο «Ανοικτά Ακαδημαϊκά Μαθήματα» του ΕΜΠ έχει χρηματοδοτήσει μόνο την αναδιαμόρφωση του υλικού. Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράμματος «Εκπαίδευση και Δια Βίου Μάθηση» και συγχρηματοδοτείται από την Ευρωπαϊκή Ένωση (Ευρωπαϊκό Κοινωνικό Ταμείο) και από εθνικούς πόρους.