Analisi Lessicale Nicola Fanizzi Corso di Linguaggi di Programmazione Dipartimento di Informatica Università degli Studi di Bari 1 aprile 2014 N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 1 / 37 Sommario 1 Analizzatore Lessicale Introduzione Funzionalità 2 Progetto di uno Scanner Definizione delle categorie Attributi dei token Estensioni delle espressioni regolari Errori Lessicali Recupero delle situazioni d’errore 3 Implementazione Codifica Funzione scanner Analisi lessicale ed automi Azioni N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 2 / 37 Analizzatore Lessicale Sommario 1 Analizzatore Lessicale Introduzione Funzionalità 2 Progetto di uno Scanner Definizione delle categorie Attributi dei token Estensioni delle espressioni regolari Errori Lessicali Recupero delle situazioni d’errore 3 Implementazione Codifica Funzione scanner Analisi lessicale ed automi Azioni N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 3 / 37 Analizzatore Lessicale Introduzione Analisi Lessicale I L’analisi lessicale è l’attività del compilatore tesa ad aggregare i caratteri di un programma sorgente per riconoscere e classificare le stringhe appartenenti al vocabolario (o lessico) del linguaggio di programmazione N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 4 / 37 Analizzatore Lessicale Introduzione Analisi Lessicale II L’analizzatore lessicale (o scanner, lexer) è generalmente realizzato come sottoprogramma del compilatore su chiamata dell’analizzatore sintattico lettura flusso di caratteri fino ad identificare una stringa corrispondente ad una categoria del linguaggio di prog. chiamata (controllo) sorgente analizzatore txt lessicale caratteri token analizzatore sintattico albero di derivazione resto del compilatore tabella dei simboli N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 5 / 37 Analizzatore Lessicale Introduzione Analisi Lessicale III terminologia token: categoria lessicale (insieme di stringhe) saranno i terminali per la sintassi Esempio IF, ID, OP_REL pattern = regole (produzioni o ER) per la costruzione dei token Esempi IF = "if"; ID = LETTERA (CIFRA + LETTERA)*; OP_REL = "<", ">", ">=", "<=" lessema: stringa che corrisponde a un pattern (per un token) Esempio "if", "P123", "<" N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 6 / 37 Analizzatore Lessicale Funzionalità Funzionalità Funzioni dello scanner: riconoscimento di pattern corrispondenti alle categorie parole chiave identificatori numeri separatori ed operatori stringhe .. . eliminazione spazi superflui, commenti e caratteri di controllo produzione listati del sorgente con gli eventuali errori espansione delle macro (se previste dal linguaggio) N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 7 / 37 Progetto di uno Scanner Sommario 1 Analizzatore Lessicale Introduzione Funzionalità 2 Progetto di uno Scanner Definizione delle categorie Attributi dei token Estensioni delle espressioni regolari Errori Lessicali Recupero delle situazioni d’errore 3 Implementazione Codifica Funzione scanner Analisi lessicale ed automi Azioni N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 8 / 37 Progetto di uno Scanner Definizione delle categorie Definizione delle categorie I Linguaggio Pascal-like parole chiave: program, procedure, begin, end, . . . identificatori: somma_parziale, h1, . . . (lunghezza max: 15 caratteri) separatori ed operatori a singolo carattere: + - ; : . . . operatori a due caratteri: :=, <=, . . . numeri interi positivi: es. 223472, . . . stringhe: es. ’ciao, mondo!’, . . . commenti: { ecco un commento } Spazi e terminatori di linea servono a separare i vari simboli del linguaggio N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 9 / 37 Progetto di uno Scanner Definizione delle categorie Definizione delle categorie II Linguaggio Java-like parole chiave: class, try, new, . . . identificatori: sommaParziale, h1, . . . (lunghezza max: 32 caratteri) separatori ed operatori a singolo carattere: , + - ; = . . . operatori a due caratteri: [ ], <=, . . . numeri interi positivi: es. 223472, . . . stringhe: es. "ciao, mondo!", . . . commenti: /* questo e’ un commento */, . . . Spazi e terminatori di linea servono a separare i vari simboli del linguaggio N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 10 / 37 Progetto di uno Scanner Attributi dei token Attributi dei token I Quando più di un pattern corrisponde ad un lessema lo scanner deve fornire l’info associata A tale scopo, lo scanner fornisce attributi associati ai token i token influenzano il parsing gli attributi servono alla traduzione dei token N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 11 / 37 Progetto di uno Scanner Attributi dei token Attributi dei token II Esempio (attributi dei token) Data la riga: E = M * C ** 2 risultano le coppie seguenti: (ID, p(E)), (ASS, ·), (ID, p(M)), (MUL, ·), (ID, p(C)), (POW, ·), (NUMINT, 2) p(·) puntatore al record nella tavola dei simboli NB: alcune coppie non hanno bisogno di attributo N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 12 / 37 Progetto di uno Scanner Attributi dei token Lessico I Il lessico può essere descritto mediante espressioni regolari sull’alfabeto dei caratteri ammessi: KEYWORD = class + public + int + static + . . . LETTERA = ’A’ + . . . + ’Z’ + ’a’ + . . . + ’z’ CIFRA = ’0’ + ’1’ + ’2’ + ’3’ + ’4’ + ’5’ + ’6’ + ’7’ + ’8’ + ’9’ ID = LETTERA(CIFRA+LETTERA)* OP1 = ’!’ + ’=’ + . . . OP2 = ’==’ + ’!=’ + ’<=’ + . . . NUM = ( CIFRA )+ CAR_STAMP = insieme dei caratteri stampabili CAR_STR = CAR_STAMP \ { " } N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 13 / 37 Progetto di uno Scanner Attributi dei token Lessico II CAR_COMM = CAR_STAMP \ { * } .. . STRINGA = " (CAR_STR)* " COMMENTO = ’/’’*’ (CAR_COMM + EoLn)* ’*’’/’ SPAZIATURA = ( ’ ’ + ’\t’ + EoLn ) SIMBOLO = KEYWORD + ID + OP1 + OP2 + NUM + STRINGA SORGENTE = (SIMBOLO + COMMENTO + SPAZIATURA)* EoF L’espressione SORGENTE descrive l’intero codice sorgente di un programma N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 14 / 37 Progetto di uno Scanner Estensioni delle espressioni regolari Estensioni delle espressioni regolari I sistemi automatici estendono gli operatori con abbreviazioni: Estensioni | in genere sostituisce il + delle ER (...)? opzionalità (zero o uno): (R)? ≡ R| (...)+ iterazione (uno o più): (R)+ ≡ R(R)* [c1-c2] ins. di caratteri: un carattere tra c1+. . . +c2 es. [’a’-’z’] può indicare un caratteri tra ’a’ e ’z’ Esempio CIFRA INTERO FRAZIONE EXP NUM_REALE = = = = = [’0’-’9’] (CIFRA)+ (’.’INTERO)? (’E’(’+’|’-’)? INTERO )? INTERO FRAZIONE EXP approfonditi in JavaCC N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 15 / 37 Progetto di uno Scanner Errori Lessicali Errori Lessicali I codice 1 2 3 4 5 .. . N. Fanizzi Linguaggi di prog.+Lab messaggio di errore identificatore troppo lungo numero intero troppo grande fine linea inattesa fine file inattesa carattere non ammesso .. . Analisi Lessicale 1 aprile 2014 16 / 37 Progetto di uno Scanner Errori Lessicali Errori Lessicali II Dato che lo scanner ha una visione locale del sorgente pochi errori individuabili a livello lessicale Esempio wile ( a < g(x)) Se, in un programma (C,Java), si incontra wile per la prima volta nel contesto mostrato: lo scanner non sa distinguere tra un errore di battitura d’una keyword o il nome di una funzione (non dichiarata) Restituirebbe un identificatore segnalerebbe un errore più avanti N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 17 / 37 Progetto di uno Scanner Recupero delle situazioni d’errore Recupero delle situazioni d’errore I Quando lo scanner non può andare avanti perché nessun pattern corrisponde ai prefissi dell’input rimanente si ricorre ad azioni di recupero Panic Mode Si cancellano i caratteri successivi fino a quando non si ritrovi il pattern corrispondente ad un token valido Osservazioni può confondere il parser va bene in modalità interattive N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 18 / 37 Progetto di uno Scanner Recupero delle situazioni d’errore Recupero delle situazioni d’errore II Altre azioni di recupero: 1 cancellazione di caratteri estranei al set ammesso 2 tentativo di inserimento di caratteri mancanti 3 rimpiazzo di caratteri non corretti con quelli giusti 4 scambio di caratteri adiacenti In genere si prova la sequenza minima di trasformazioni per riportare il programma in forma sintatticamente analizzabile Crierio della minima distanza Un programma errato ha k errori se la sequenza più corta di trasformazioni che lo porti a diventare un programma valido ha lunghezza k N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 19 / 37 Implementazione Sommario 1 Analizzatore Lessicale Introduzione Funzionalità 2 Progetto di uno Scanner Definizione delle categorie Attributi dei token Estensioni delle espressioni regolari Errori Lessicali Recupero delle situazioni d’errore 3 Implementazione Codifica Funzione scanner Analisi lessicale ed automi Azioni N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 20 / 37 Implementazione Codifica Strutture Dati Tipi strutturati per descrivere i token Sintassi C-like union Val_Codice { char nome_id[16]; 3 int val_int; 4 char buffer_str[81]; 5} 1 2 6 struct Token { int codice; 9 union Val_Codice val; 10 int col; 11 } 7 8 Come definire una classe Token in Java ? N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 21 / 37 Implementazione Codifica Codifica cost. mnemonica I_C N_C S_C EOF_C .. . cost. numerica 1 2 3 4 .. . significato identificatore intero stringa fine file .. . PROGRAM_C CLASS_C .. . 11 12 .. . keyword PROGRAM keyword CLASS .. . PLUS_C MINUS_C .. . 51 52 .. . operatore + operatore .. . ASSIGN_C GE_C ... 71 72 ... operatore := operatore >= ... N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 22 / 37 Implementazione Funzione scanner Implementazione dello scanner come funzione: Token SCAN(void) oppure come procedura: SCAN(Token SYMBOL) Compiti: costruire simboli del linguaggio di programmazione (categorie) fornire l’informazione strutturata sul loro contenuto N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 23 / 37 Implementazione Analisi lessicale ed automi Analisi lessicale ed automi I Gli automi a stati finiti trovano applicazione nell’analisi lessicale: Sviluppo diretto degli analizzatori lessicali Tool per la generazione automatica di analizzatori lessicali (es.: Lex, Flex, JavaCC, ANTLR, ecc.) Strumenti di elaborazione di testi (es.: awk, grep, ecc.) per il riconoscimento dei pattern nel testo (espressioni regolari) Ad es., per il linguaggio precedente... N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 24 / 37 Implementazione Analisi lessicale ed automi Analisi lessicale ed automi II CAR_COMM ERR SPAZIATURA car. err. A EOLN / COM DIV / EQ NEQ = = ASS = * ! + NOT PLUS > GEQ LEQ S2 N. Fanizzi = = " GT MIN < LETTERA " LT S1 MUL CIFRA CAR_STR Linguaggi di prog.+Lab Analisi Lessicale ID* LETTERA +CIFRA NUM CIFRA 1 aprile 2014 25 / 37 Implementazione Analisi lessicale ed automi Implementazione (pseudo-codice) I 1 2 /* variabili globali */ char ch; 3 /* costanti */ const int A_S=0, COM_S=1, I_S=2, NUM_S=3; 6 const int S1_S=4, GT_S=6, LT_S=7; 7 const int ... 4 5 8 /* analizzatore lessicale (incompleto) */ void scan(Token symbol) { 11 int stato=A_S, exit_flag=0, read_flag=1; 12 do 13 switch(stato) { 14 case A_S: 15 if (ch == ’/’) stato=DIV_S; 16 else if (ch == ’*’) 17 { stato=MUL_S; exit_flag=1; } 9 10 N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 26 / 37 Implementazione Analisi lessicale ed automi Implementazione (pseudo-codice) II 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 N. Fanizzi else if (ch == ’+’) { stato=PLUS_S; exit_flag=1; } else if (ch == ’*’) { stato=MUL_S; ; exit_flag=1; } else if (ch == ’-’) { stato=MIN_S; exit_flag=1; } else if (isalpha(ch)) stato=ID_S; else if (isnum(ch)) stato=NUM_S; else if (ch == ’=’) stato=ASS_S; else if (ch == ’!’) stato=NOT_S; else if (ch == ’>’) stato=GT_S; else if (ch == ’<’) stato=LT_S; else if (ch == ’"’) stato=S1_S; else stato = ERR_S; getnextchar(ch); break; case DIV_S: Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 27 / 37 Implementazione Analisi lessicale ed automi Implementazione (pseudo-codice) III 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 N. Fanizzi if (ch == ’/’) stato = COM_S; else { exit_flag=1; read_flag=1; } case COM_S: if (iscommentcar(ch)) getnextchar(ch); else if (ch == ’\n’) stato = A_S; else if (ch == EOF) { stato=EOF_S; exit_flag=1; } else error(COM_S); break; case I_S: if (isalnum(ch)) getnextchar(ch); else { exit_flag=1; read_flag=1; } break; case NUM_S: if (isnum(ch)) getnextchar(ch); else { exit_flag=1; read_flag=1; } Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 28 / 37 Implementazione Analisi lessicale ed automi Implementazione (pseudo-codice) IV 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 N. Fanizzi break; case ASS_S: if (ch == ’=’) stato = EQ_S; else { exit_flag=1; read_flag=1; } break; case EQ_S: exit_flag=1; break; case NOT_S: if (ch == ’=’) stato = NEQ_S; else { exit_flag=1; read_flag=1; } break; case NEQ_S: exit_flag=1; break; case S1_S: if (isstrchar(ch)) getnextchar(ch); Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 29 / 37 Implementazione Analisi lessicale ed automi Implementazione (pseudo-codice) V 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 N. Fanizzi else if (ch == ’"’) stato = S2_S; else error(S1_S); break; case GT_S: if (ch == ’=’) stato = GEQ_S; else { exit_flag=1; read_flag=1; } break; case GEQ_S: exit_flag=1; break; case LT_S: if (ch == ’=’) stato = NEQ_S; else { exit_flag=1; read_flag=1; } break; case LEQ_S: exit_flag=1; break; Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 30 / 37 Implementazione Analisi lessicale ed automi Implementazione (pseudo-codice) VI 86 87 default: error() /* stato inatteso */ } /* switch */ 88 if (!read_flag) getnextchar(ch); 91 } while(!exit_flag); 92 return token(stato); 93 } /* scan */ 89 90 N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 31 / 37 Implementazione Analisi lessicale ed automi Routine di servizio In C, invece delle switch con molti rami, si possono usare if in cascata e test implementati mediante funzioni di libreria isalnum(), isalpha(), isdigit(), . . . procedura readch(char *ch,int *ch_col) restituisce in ch il prossimo carattere e restituisce in ch_col la sua posizione nella linea corrente occorre anche una procedura di inizializzazione init_scan(Token *SYMBOL) apre il file sorgente, inizializza la tabella delle parole chiave legge il primo carattere chiamando readch() N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 32 / 37 Implementazione Azioni Azioni I Codice da eseguire secondo l’evoluzione dell lavoro di analisi az. iniziale associato allo stato di partenza es. A ` ID il primo carattere dell’identificatore viene copiato (contenuto in ch) in un array SYMBOL_name[0] az. associata ad arco codice eseguito quando si transita sull’arco es. ID ` ID la lettera o la cifra in ch viene aggiunta alla stringa SYMBOL_name; se si è raggiunto il limite si segnala l’errore az. finali associate ad uno stato finale con archi uscenti, es. ID se c’è stato errore lo si segnala altrimenti si cerca nella tabella delle parole-chiave la categoria sintattica corrispondente sarà identificatore oppure quella della keyword trovata N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 33 / 37 Implementazione Azioni Azioni II void scan(Token *SYMBOL) { int s=A_S; int exit_flag=0, read_flag=1; 3 do 4 switch(s) { 5 case A_S: 6 switch(ch) { 7 case ’A’: 8 ... 9 case ’Z’: 10 SYMBOL->col=ch_col; 11 i=1; 12 SYMBOL->name[0]=ch; 13 s=I_S; 14 break; 15 } /* switch interno A_S*/ 1 2 16 17 N. Fanizzi ... Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 34 / 37 Implementazione Azioni Azioni III 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 N. Fanizzi case I_S: switch(ch) { case ’0’: ... case ’9’: case ’A’: ... case ’Z’: if (i<I_LENGTH) {i++; SYMBOL->name[i-1]=ch;} else error_flag=1; default: if (error_flag) error(1,SYMBOL->col); for( ; i<I_LENGTH ; i++) SYMBOL->name[i-1]=’ ’; Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 35 / 37 Implementazione Azioni Azioni IV if (is_keyword(SYMBOL->name,key)) SYMBOL->code=key; else SYMBOL->code=I_C; } /* switch interno I_S */ 35 36 37 38 39 40 ... N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 36 / 37 Bibliografia Fonti Aho, Lam, Sethi, Ullman: Compilatori - Principi, tecniche e strumenti. 2a ed., Pearson Dos Reis: Compiler Construction Using Java, JavaCC, and Yacc. Wiley-IEEE Grune, Bal, Jacobs, Langendoen: Modern Compiler Design, Wiley N. Fanizzi Linguaggi di prog.+Lab Analisi Lessicale 1 aprile 2014 37 / 37
© Copyright 2024 Paperzz