• Nenhum resultado encontrado

Gera¸c˜ao de C´odigo

3.9 Transforma¸c˜oes de M´odulos

4.1.4 Gera¸c˜ao de C´odigo

As regras de tradu¸c˜ao das constru¸c˜oes de Notus para Alex s˜ao descritas em semˆantica denotacional nas Figuras 4.10 e 4.11. As regras de tradu¸c˜ao descrevem o processo de gera¸c˜ao de c´odigo das constru¸c˜oes da especifica¸c˜ao l´exica em Notus discutida na Se¸c˜ao 3.5, para as constru¸c˜oes correspondentes de uma especifica¸c˜ao l´exica em Alex.

As se¸c˜oes de defini¸c˜ao dos dom´ınios sint´aticos e semˆanticos da Figura 4.10 decla- ram os dom´ınios usados na especifica¸c˜ao. A se¸c˜ao de sintaxe abstrata formaliza as constru¸c˜oes de Notus para a especifica¸c˜ao l´exica discutida na Se¸c˜ao 3.5. A especi- fica¸c˜ao l´exica pode conter declara¸c˜oes de tokens, macros, por meio da cl´ausula element, e express˜oes regulares a serem ignoradas por meio da cl´ausula ignore.

7

4.1. Compilac¸˜ao da Especificac¸˜ao L´exica 75

token if = "if"; token then = "then"; token else = "else"; token while = "while"; token do = "do";

token id = seqld;

element seqld = leter ( leter | digit )*; element leter = [’A’ .. ’Z’] | [’a’ .. ’z’]

public element digit = [’0’ .. ’9’]; token num = digit+;

macros: digit leter seqld tokens: if then else while do num id Module 1 Module 2 Module 3

lex.x (not optimized) Lex Generator (Notus Compiler) macros: digit leter seqld tokens: num id lex.x (optimized)

Figura 4.9: Composi¸c˜ao da descri¸c˜ao l´exica em arquivos de entrada (com e sem a otimiza¸c˜ao proposta) para o programa Alex

Express˜oes regulares em Notus podem ser compostas por caracteres, strings, iden- tificadores de macros ou por operadores. Os operadores bin´arios existentes s˜ao o de uni˜ao, representado por ‘|’, e o de concatena¸c˜ao, representado por simples justaposi¸c˜ao de express˜oes. Os un´arios s˜ao o operador de complemento (ˆ), que representa o com- plemento da express˜ao regular que o sucede, o operador de Kleene star (∗), o operador de Kleene plus (+) e o operador de op¸c˜ao (?) que indicam, respectivamente, zero ou mais repeti¸c˜oes, uma ou mais repeti¸c˜oes, e no m´aximo uma ocorrˆencia da express˜ao regular que os antecedem. A express˜ao regular ‘.’ reconhece qualquer caractere exceto a quebra de linha (“\n”).

A fun¸c˜ao de compila¸c˜ao de declara¸c˜ao, cujo tipo ´e determinado na Figura 4.10, recebe uma declara¸c˜ao e um estado e produz o c´odigo referente a essa declara¸c˜ao na nota¸c˜ao aceita por Alex. O mesmo acontece com a fun¸c˜ao de compila¸c˜ao de express˜oes regulares que, dados uma express˜ao e um estado, gera c´odigo para essa express˜ao seguindo o especificado pelo Alex para express˜oes regulares. O estado ´e modelado por uma fun¸c˜ao que associa a cada identificador um valor l´ogico indicando se o identificador corresponde ou n˜ao a uma macro. Essa distin¸c˜ao ´e necess´aria para a gera¸c˜ao de c´odigo para a macro, j´a que de acordo com a especifica¸c˜ao do Alex, todo identificador de macro deve ser precedido pelo s´ımbolo ‘@’.

As equa¸c˜oes semˆanticas da Figura 4.11 traduzem cada constru¸c˜ao de especifica¸c˜ao l´exica de Notus, para as constru¸c˜oes equivalentes em Alex. O operador “?”, que aparece

Dom´ınio Sint´atico: Bool = {true, f alse}

Ide = {I|I ´e um identificador}

Exp = {E|E ´e uma express˜ao regular} Dec = {D|D ´e uma declara¸c˜ao}

String = {S|S ´e um string entre aspas duplas} Sintaxe Abstrata: D ::= token I1 : I2? = E1 isE2 | token I1 : I2? = E1 | elementI = E | ignore E E ::= (E1|E2) | “ ˜ ”E | E “ ∗ ” | E “ + ” | E “?” | “(” E “)” | “[” Char1 - Char2 “]” | S | I | “.” Dom´ınios Semˆanticos:

State= [Ide 7→ Bool] s ∈ State

Fun¸c˜oes Semˆanticas de Compila¸c˜ao:

• Compila¸c˜ao de Declara¸c˜ao KD : Dec 7→ State 7→ IO • Compila¸c˜ao de Express˜ao

KE : Exp 7→ State 7→ IO Fun¸c˜oes Auxiliares:

print : String 7→ IO

Figura 4.10: Regras de tradu¸c˜ao de Notus para a especifica¸c˜ao l´exica

ap´os o identificador representando o nome de um dom´ınio sint´atico, indica que esses elementos s˜ao opcionais. Para o Alex, um token ´e definido escrevendo-se sua express˜ao regular (R) seguida por c´odigo Haskell entre {}, que corresponde `a a¸c˜ao a ser executada quando um string denotado por R ´e reconhecido. O Alex requer que todas as a¸c˜oes possuam o mesmo tipo. O compilador de Notus gera a¸c˜oes do tipo String → T oken, onde o parˆametro String, representado por s nas a¸c˜oes geradas, corresponde ao lexema reconhecido, e o tipo Token, um datatype definido em Haskell, possui um construtor de tipos para cada token declarado pela linguagem especificada. Se uma declara¸c˜ao de token define uma fun¸c˜ao para o seu lexema pelo uso da cl´ausula is, o compilador de Notus gera uma a¸c˜ao que aplica essa fun¸c˜ao a s.

4.1. Compilac¸˜ao da Especificac¸˜ao L´exica 77

Equa¸c˜oes Semˆanticas Para Gera¸c˜ao de C´odigo:

KD[[token I1 : I2? = E1 isE2]]s0 = KE[[E1]]s0• print(“{\s → ”)•

KE[[I1]]s0• print(“(”)•

KE[[E2]]s0• print(“ s)}”)

KD[[token I1 : I2? = E1]]s0 = KE[[E1]]s0• print(“{\s → ”)•

KE[[I1]]s0• print(“}”)

KD[[element I = E]]s0 = print(“@”) • KE[[I]]s0•

print(“ = ”) • KE[[E]]s0

KD[[ignore E]]s0 = KE[[E]]s0• print(“; ”)

KE[[(E1|E2)]]s0 = KE[[E1]]s0• print(“|”) • KE[[E2]]s0

KE[[“ ˆ ”E]]s0 = print(“ˆ”) • KE[[E]]s0

KE[[E “ ∗ ”]]s0 = KE[[E]]s0• print(“ ∗ ”)

KE[[E “ + ”]]s0 = KE[[E]]s0• print(“ + ”)

KE[[E “?”]]s0 = KE[[E]]s0• print(“?”)

KE[[“(” E “)”]]s0 = print(“(”) • KE[[E]]s0•

print(“)”)

KE[[“[” Char1 - Char2 “]”]]s0 = print(“[”Char1 “ − ” Char2 “]”)

KE[[S]]s0 = print(S)

KE[[I]]s0 = s0 I → print(“@ I”) , (print(“I”) )

KE[[“.”]]s0 = print(“.”)

Figura 4.11: Regras de tradu¸c˜ao de Notus para a especifica¸c˜ao l´exica.

do identificador que o define, possui o efeito colateral de associar na fun¸c˜ao State o identificador da macro ao valor l´ogico true, indicando que esse identificador ´e macro. A defini¸c˜ao de uma macro em Alex segue o formato:

@identificador macro = express˜ao regular

Os operadores que podem aparecer na defini¸c˜ao de uma express˜ao regular em Notus correspondem aos usados pelo Alex. Dessa forma, a tradu¸c˜ao de express˜oes regulares

´e direta. Note que, na equa¸c˜ao semˆantica para identificadores, verifica-se se o identifi- cador ´e macro para que o s´ımbolo @ seja gerado somente quando necess´ario. Durante a fase de an´alise semˆantica, associa-se a cada identificador um valor l´ogico indicando se ele corresponde ou n˜ao a uma macro. Esse mapeamento ´e armazenado em s0.

O c´odigo gerado, mostrado nas Listagens 4.3 e 4.2, ´e submetido ao Alex para a obten¸c˜ao de um analisador l´exico para a linguagem especificada no exemplo da Figura 4.5. O m´odulo Tree da Listagem 4.2 ´e importado por toda defini¸c˜ao em Alex gerada por Notus. Esse m´odulo cont´em a defini¸c˜ao de uma ´arvore bin´aria e uma fun¸c˜ao de pesquisa nesta ´arvore.

1

2 module Tree where

3 data Tree a b = L e a f ( a , b )

4 | Node ( a , b ) ( Tree a b ) ( Tree a b )

5 | N u l l

6 d e r i v i n g Eq

7

8 lookupT : : Ord a => Tree a Token −> a −> Token −> Token 9 lookupT ( L e a f ( a , b ) ) s r o o t T o k e n 10 | s == a = b 11 | o t h e r w i s e = r o o t T o k e n 12 lookupT ( Node ( n , t ) l r ) s r o o t T o k e n 13 | n == s = t 14 | s > n = lookupT r s r o o t T o k e n 15 | s < n = lookupT l s r o o t T o k e n 16 lookupT N u l l r o o t T o k e n = r o o t T o k e n

Listagem 4.2: C´odigo do m´odulo Tree.