pràctiques mètodes i eines de compilació
DESCRIPTION
Pràctiques Mètodes i Eines de Compilació. Marc Massot i Bayés [email protected] AM11-S2 Mateu Villaret Auselle [email protected] AM11-S2. Planificació. Una sola pràctica a realitzar amb el PCCTS. Grups de 2 persones. Entrega de la pràctica abans de cada exàmen de cada Convocatòria. - PowerPoint PPT PresentationTRANSCRIPT
PràctiquesMètodes i Eines de Compilació
Marc Massot i Bayé[email protected]
AM11-S2
Mateu Villaret [email protected]
AM11-S2
Planificació
• Una sola pràctica a realitzar amb el PCCTS. • Grups de 2 persones.• Entrega de la pràctica abans de cada exàmen
de cada Convocatòria.• La nota de la pràctica serà un 30% de la nota
final.• A l’exàmen hi haurà 2 punts amb preguntes
sobre la pràctica.
Breu descripció de la Pràctica
• Realitzar un compilador de sentències SQL parametritzades a codi Visual Basic que permeti executar les sentències donades, sobre la base de dades definida, en un entorn de finestres.
Etapes d’un procés de Compilació
• Anàlisi lèxica
• Anàlisi sintàctica
• Anàlisi semàntica
• Generació codi intermig
• Optimització de codi
• Generació de codi
PCCTS Perdue Compiler Construction Tool Set
• Conjunt d’eines que faciliten la construcció de compiladors i traductors
• Conté dues eines bàsiques:– DLG (DFA-Based Lexical Generator).– ANTLR (Another Tool for Language Recognition)
• Genera codi C++.
PCCTS(II)
____.cppantlr
dlg
____.g
____.cpp
____.dlg
PCCTS (III)
• Genera un parser descendent. Gramàtiques lliures de contexte LL.
• Procés de compilació dirigit per la sintaxis.
Anàlisi Sintàctica
Anàlisi Lèxica Anàlisi Semàntica Generació de Codi
Entorn de treball amb el PCCTS• Crearem un directori de treball on hi posarem el fitxer
<grammar>.g que ens descriurà la classe amb la regla a reconeixer <class>
• Hem de poder compilar i linkar els fitxers en C++ generats pel PCCTS.
• Ho tractarem com a projecte Visual C++, cosa que ens permetrà a l’estil Makefile:– Engegar les comandes d’execució del ANTLR i del DLG.– Compilar i muntar els fitxers generats.
Fitxer <grammar>.g<<#include "PBlackBox.h"#include "DLGLexer.h"
typedef ANTLRCommonToken ANTLRToken;
main() { ParserBlackBox<DLGLexer, PrimerParser, ANTLRToken> p(stdin); p.parser()->programa();}>>
// Anàlisi Sintàcticaclass PrimerParser {programa : (~"@")*"@" <<printf("\nFinal de procés.\n");>>;}
// Anàlisi Lèxica ...... ......
Lèxic (i)
• Podem utilitzar expressions regulars directament a les regles sintàctiques.
• o podem definir tokens amb l’etiquetatge:– #token Ident “[a-zA-Z][a-zA-Z0-9_]*”– El nom del token ha de començar amb majúscules.– L’expressió regular va entre cometes dobles “”.– L’ordre de definició és important, en cas
d’ambigüetat escull el primer.
Lèxic (ii)
Expressions regulars que podem reconèixer:
Expressióregular
Interpretació
"e1|e2" reconeix e1 o bé e2
"(e1)" reconeix e1
"{e1}" reconeix e1 o be res (seria com (e1|)
"[c1c2...cn]" reconeix un (només un) dels caràcters de la llista seria com: (c1|c2|...|cn)
"[c1-cn]" reconeix un dels caràcters que tinguin el codi ASCII entre c1 i cn
"~[c1c2...cn]" reconeix un caràcter dels que no està a la llista
"~[]" reconeix un caràcter qualsevol, és com dir: no cap caracter (o sigui,algun)
"e1*" reconeix zero o més ocurrencies de l'expressió e1
"e1+" reconeix un o més ocurrencies de l'expressió e1
"\c1" reconeix el caràcter c1 encara que tingui un cert significat en lesexpressions regulars: per ex. (\+)
Lèxic (iii)
També es poden reconeixer una sèrie de caràcters especials:
"@" reconeix el fi de fitxer
"\t" tabulador
"\n" línea nova (Newline)
"\r" enter
"\b" backspace
"\c" ESC
"\0nnn" reconeix el caràcter amb valor octal: nnn
"\0xnn" reconeix el caràcter amb valor hexadecimal: nn
"\mnn" reconeix el caràcter amb valor decimal mnn (1=m=9)
"\ " reconeixer l'espai.
Lèxic (iv)
• Per agrupar tokens, podem definir classes de tokens amb:– #tokclass nomclasse { T1 … Tn }– podem usar nomclasse per a referirnos a qualsevol
dels T1 … Tn.
• Podem associar accions al reconeixement de tokens per tal que es realitzin un cop reconeguts aquests:– #token nomtok expreg << acció_desitjada >>
Lèxic (v)
Algunes de les funcions/accions que ens poden ser útils amb el DLG:
replchar(DLGchar c) Substitueix el text del l'últim element lèxic per c. Es pot borrar el text de l'últimelement enviant el caràcter '\0'.
replstr(DLGchar *s) Substitueix el text del l'últim element lèxic per s.
int line() La linia actual que s'està processant.
newline() Informem al DLG que s'ha trobat un caràcter de canvi de línia.
more() Indiquem al DLG que busqui un nou token però que els proper caràcterss'afegeixen al text del token actual.
Lèxic (vi)
skip() Indiquem al DLG que continui processant un nou token però que no guardi eltext del token actual.
advance() Fem que el DLG consumeixi un nou caràcter.
int ch L'últim caràcter processat.
DLGChar *lextext() El text que s'han llegit des de que l'últim token que s'ha retornat.
DLGchar *begexpr() Començament de l'ultim token trobat.
Lèxic (vii)
DlGchar *endexpr() Punter a l'últim caràcter de l'últim token trobat.
trackColumns() Cal cridar aquesta funció si es vol comptabilitzar les columnes. El número decolumna es posa a zero quan es troba un caràcter de final de línia. També s'actualitzael número de columna quan es troben caràcter que ocupen més d'un espai (p.e.TAB).
int begcol() El número de columna començant per 1 del primer caràcter de l'últim token detectat.
int endcol() El número de columna començant per 1 de l'últim caràcter de l'últim token detectat.
Lèxic (viii)• Per a definir accions, funcions, variables, etc., que
volem usar en el codi ___.cpp generat pel DLG que tindrà l’scaner fem:– #lexaction << codi en C++ que desitgem >>
• Podem definir diverses classes lèxiques amb les seves regles cadascuna:– Per definir l’inici d’una classe farem:
• #lexclass contexte.
– La classe lèxica inicial per defecte és: START.
– Per canviar de classe lèxica farem:• mode (nova_classe).
Sintàctic 1• L’anàlisi sintàctica consistirà en la definició de
regles sintàctiques:– Una regla descriu una porció del llenguatge d’entrada.– Consisteix en un nom de regla que comença amb
minúscules i una llista d’alternatives.– Te utilitats de pas de valors entre regles i d’utilitats de
tractaments d’errors (opcionals).
• Notem que cada regla és un “mètode” de la classe del parser, per tant pot tenir variables locals, paràmetres, etc.
Sintàctic 2• Esquema de regla:
r1 [a1,…an]>[r1,…rn]: prod1|…|prodn ;– r1 és el nom de la regla, comença amb minúscula.– Els ai són possibles arguments d’entrada per a la
regla i els ri possibles valors de retorn de la regla.– Els prodi són produccions possibles que
defineixen la regla, estan formades per:• referències a regles
• referències a tokens
• subregles
• accions
• predicats
Sintàctic 3
• Per a referenciar una regla només cal posar el seu nom i els arguments (e/s) si en té:– referència[paràm entrada]>[paràm sortida]
• Podem referenciar el token, posar una expressió regular o bé referenciar classes de tokens, exemples:– Identificador– “altrament”– Operadors
Sintàctic 4
• Les subregles són regles sense etiquetes ni paràmetres:– Simple: (…) ex: (Id|Const)– Zero_o_mes: (…)* ex: Id (“,” Id)*– Una_o_mes: (…)+ ex: (decvars)+– Opcional: {...} ex: {“altrament” sentencia}
Sintàctic 5
• Les accions són codi C++ entre <<...>>:– Inicialitzacions: es posarà just després del “:” i
s’executarà abans de reconèixer res.– Accions de fracàs: es posarà després del “;” i
s’executarà si el gestor d’errors no és actiu al trobar un error en el reconeixement de la regla.
– Intermitges: les posarem al mig de la regla i s’executaran segons l’ordre de reconeixement dels elements de la regla.
Sintàctic 6• Els predicats poden ser de dos tipus semàntics
i sintàctics. Els sintàctics són especificacions del contexte on certa producció farà “matching” amb èxit i es definirà dins:– ( … ) ?
• Exemple:– a: (llista “=“ ) ? llista “=“ llista
|llista
Sintàctic 7• Etiquetatge: Les referències dins d’una
producció poden ser etiquetades amb un identificador que es sol fer servir per accedir al token, s’etiqueta així:– etiqueta : element
• Podem accedir a l’element etiquetat (token) amb: $etiqueta, exemple:– r1: t:ID <<printf(“%s\n”, $t->getText());>>
;
Sintàctic 8• El PCCTS proporciona una utilitat per al
tractament d’errors (notificació) i la resincronització a base d’excepcions.
• Quan en el reconeixement d’una regla es produeix un error sintàctic el parser llença una excepció que és capturada pel manegador d’excepcions que atengui aquella excepció, més proper.
• Una vegada atesa l’excepció el parser segueix, retornan de la regla generadora.
Sintàctic 9
• Els manegadors d’exepcions es poden posar a:– Després de qualsevol alternativa: aquests manegadors només
s’aplicaran sobre al reconexer els components de la corresponent alternativa.
– Després del “;” de definició de la regla: s’aplicarà a qualsevol excepció de qualsevol alternativa de la regla.
– Després de la llista de regles: és un manegador global i actuarà quan no actuin manegadors locals.
Sintàctic 10
• La manera de definir-los és la següent:– exception {[etiqueta]}
(catch signal: <<codi associat>>)*{default: <<codi associat>>}
• Els possibles signals són:– NoViableAlt– NoSemViableAlt– MismatchedToken
Sintàctic 11
• Si definim manegador d’excepcions associats a etiquetes, ho farem al final de la regla (recordem que les etiquetes són úniques).– …a: A t:expr B | …..
;exception[t]catch:catch:...
Sintàctic 12
• L’ordre d’execució de les excepcions és el determinat per la proximitat de la definició del manegador:– etiqueta– alternativa– regla– global
Sintàctic 13
• Per a resincronitzar es poden fer servir les següents accions:– consumeUntil(X_set)– consumeUntilToken(T)
Semàntic 1
• Per a fer tractament semàntic usarem el pas de paràmetres entre regles ja explicat i la una taula de símbols per tal de poder fer comprovacions com:
– Unicitat d’identificadors.– Ús de cada identificador correcte: variables,
constants, accions i funcions.– Operadors utilitzats amb operands del tipus
correcte.
Semàntic 2
• Altres comprovacions semàntiques:– Coincidència del tipatge al prototipus de les
funcions/accions i a l’implementació.– Parametrització de les funcions correcta:
• Entrada sortida correcta.
• Paràmetres del tipus corresponent.
– Correcte ús de les funcions i les variables com a expressions del tipus correcte.
– Taules indexades correctament.
Semàntic 3
• La taula de símbols ens servirà per a guardar la informació semàntica de tots els identificadors del programa a compilar.
• Utilitzarem una TS que proporciona el PCCTS al directori:– /usr/local/pccts/support/sym
Semàntic 4
• Aquesta taula de símbols te dos fitxers, caldrà que modifiquem el template.h en la definició del símbol tal com ens interessi.
• Caldrà afegir la compilació i linkatge en el projecte i posar l’include adequat en el fitxer ___.g.
#header << #include <iostream.h> >><<#include “PblackBox.h”#include “DLGLexer.h”
main() { ParserBlackBox<DLGLexer, Calculadora, ANTLRCommonToken> p(stdin); p.parser()->calcul();}
class Calculadora { calcul: (~”@”)*”@”;}
#token “[\n\r]” << skip(); newline(); >>#token “[\ \t]” << skip(); >>#token ID “[a-zA-Z][a-zA-Z0-9_]”
<< cout << “Trobat ID(“ << line() << “): ” << lextext() << endl;>>
#token ENTER “(0|([1-9][0-9]*))”<< cout<< “Trobat ENTER(“ << line() << “): ” << lextext()<< endl;>>
#token REAL “(0|([1-9][0-9]*))\.[0-9]+”<< cout << “Trobat REAL(“ << line() << “): ” << lextext() <<
endl;>>
#token “~[@]”<< skip(); cout << “Error Lèxic(“ << line() << “): ” << lextext() <<
endl;>>