ePrometeusCorsoLinuxLinux
testi articoli
Testi Articoli  Download
Home | OpenSource | PhpNuke | Programming | SysAdm | 
CorsoJava è ora Video! Free for all!
Clicca Qui!
UN COMPILATORE CON LEX E YACC
Usare Lex e Yacc per un traduttore da BASIC a C
Grammatiche ed alberi di sintassi concreta e astratta
Lex e Yacc
Un traduttore elementare da BASIC a C
Il processo della compilazione
Analisi lessicale con Lex
Analisi sintattica con Yacc
Azioni semantiche di traduzione
Conclusioni
Riferimenti
Download
L'Autore


<<< Un traduttore elementare da BASIC a C >>>

In questo articolo descriviamo un limitato compilatore sviluppato con Lex e Yacc, chiamato b2c. In realtà si tratta di un convertitore di formato tra due noti linguaggi di programmazione: da BASIC a C. Il traduttore è molto limitato nelle sue funzionalità: tratta solo un successive sottoinsieme del BASIC. Un compilatore in generale è un traduttore di programmi in un linguaggio in programmi in un altro linguaggio. Il vantaggio di questa operazione è insita nelle ottimizzazioni che vengono effettuate dal compilatore.

Lex e Yacc comunque sono utili in qualunque contesto sia richiesta una conversione di dati da un formato ad un altro: per esempio, conversioni di formato di testi (ricordiamo i tanti traduttori da qualche formato in HTML), compilatori ad alto livello da un linguaggio ad un altro, (per esempio esistono compilatori da Pascal, Fortran, Lisp e Prolog in C), interpreti (l'interprete Perl usa una sostanziosa grammatica Yacc), editor guidati dalla sintassi e via discorrendo.

Illustriamo il BASIC giocattolo che b2c supporta. Ribadisco che si tratta di un linguaggio talmente limitato da essere inutilizzabile per qualsiasi contesto pratico (anche se può essere un'ottima base per dei progetti concreti). Le limitazioni sono volute per mantenere il tutto ad un puro livello didattico ed evitare qualunque complicazione che possa oscurare i concetti. La sintassi del linguaggio è data nel seguente listato:

/* ESPRESSIONI */

constant: INTEGER ;

primary.expression:
VARIABLE
| constant
| '(' expression ')'
;

unary.expression:
primary.expression 
| '+' primary.expression
| '-' primary.expression
| NOT primary.expression
;

multiplicative.expression:
unary.expression
| multiplicative.expression '*' unary.expression
| multiplicative.expression '/' unary.expression
;

additive.expression:
multiplicative.expression
| additive.expression '+' multiplicative.expression
| additive.expression '-' multiplicative.expression
;

relational.expression:
additive.expression
| relational.expression '<' additive.expression
| relational.expression '>' additive.expression 
| relational.expression LE additive.expression
| relational.expression GE additive.expression 
;

equality.expression:
relational.expression
| equality.expression EQ relational.expression
| equality.expression NE relational.expression
;

AND.expression:
equality.expression
| AND.expression AND equality.expression
;

OR.expression:
AND.expression
| OR.expression OR AND.expression
;

expression:
OR.expression
;

/* COMANDI */

sep.list: 
SEP
| sep.list SEP 
;

sep.list.opt : | sep.list ;

statement.list:
statement
| statement.list sep.list statement 
;

statement:
assignment.statement
| for.statement
| while.statement
| if.statement
| print.statement
| input.statement
;

assignment.statement:
LET VARIABLE '=' expression
| VARIABLE '=' expression
;

for.statement:
FOR VARIABLE '=' expression TO expression 
sep.list statement.list sep.list NEXT
;

while.statement:
WHILE expression sep.list statement.list sep.list WEND
;


if.statement:
IF expression THEN 
sep.list.opt statement.list sep.list.opt 
else.statement.opt
;

else.statement.opt:
ENDIF
| ELSE sep.list.opt statement.list sep.list.opt ENDIF
print.statement:
PRINT
| PRINT VARIABLE
| PRINT VARIABLE ';'
| PRINT STRING
| PRINT STRING ';'
;

input.statement:
INPUT VARIABLE
;
program: 
sep.list.opt statement.list sep.list.opt
;

I simboli terminali (i token) sono racchiusi tra virgolette singole oppure sono scritti interamente in maiuscolo. Tutti gli altri sono simboli non-terminali. Il nostro BASIC ammette soltanto espressioni aritmetiche: le costanti possono essere soltanto intere. Sono ammesse le 4 operazioni, le classiche operazioni relazionali (=, >, >=, <=, <>), AND, OR e NOT. Le variabili possono essere solo di tipo intero, equivalenti se minuscole o maiuscole e significative solo per il primo carattere. Questa limitazione (che può sembrare eccessiva, ma del resto tutto il linguaggio è solo un prototipo) ci consentirà di allocare staticamente tutte le variabili; per una implementazione un po' meno limitativa sarebbe necessario costruire esplicitamente l'albero di sintassi astratta, scandirlo per trovare le variabili e generare delle dichiarazioni prima di convertire il resto del codice.

Per quanto riguarda i comandi, avremo FOR...NEXT, IF...THEN...ELSE...ENDIF, WHILE...WEND, PRINT e INPUT. Sarà possibile solo il PRINT di una stringa o una variabile, eventualmente seguita da un ";" nel caso si voglia la soppressione del newline prodotto automaticamente dalla PRINT. La grammatica può sembrare qua e là più complicata del necessario, ma è la vera grammatica utilizzata dallo Yacc per il b2c, e come tale richiede qualche compromesso e complicazione per rientrare nell'insieme delle grammatiche da esso supportate.

ePrometeus s.r.l. - Web Software House & Open Source System Integrator
MILANO - SAN BENEDETTO DEL TRONTO(AP)
Contatti: info@eprometeus.com