CES-41
COMPILADORES
Capítulo IV
Complementos de Análise Léxica
Capítulo IV – Complementos de
Análise Léxica
4.1 – Interface entre programa-fonte e compilador
4.2 – Bufferização do programa
4.3 – Observação de átomos seguintes
4.4 – Lex para observar átomos seguintes
4.1 – Interface entre Programa-Fonte
e Compilador

Os principais conceitos sobre análise léxica foram
introduzidos no capítulo anterior:
–
Formação e classificação de átomos
–
Diagrama de transições léxicas
–
Ferramenta do analisador sintático
Sendo a interface entre programa-fonte e compilador, pode
executar algumas tarefas secundárias:

Pular comentários, espaços em branco, tabulações, newlines, etc (vistos em diagramas de transições e em Flex)

Contar o número de linhas lidas, possibilitando a inclusão
do número da linha em mensagens de erro

Gerenciar o controle das linhas e sua continuação, nos
programas escritos em linguagens em que a divisão em
linhas é relevante (Fortran, Cobol)
Exemplo: contagem de linhas no diagrama de transições léxicas
– para a análise sintática
Exemplo: uma linha de programa em Fortran

Caractere na coluna 6: a linha é continuação da anterior
4.2 – Bufferização do Programa

A complexidade do analisador léxico é bem menor,
conceitualmente falando, do que a dos outros componentes de
um compilador

No entanto, é nele que o front-end de um compilador
consome a maior porção de seu tempo

É o componente que lê caractere por caractere do arquivo
do programa

A velocidade do analisador léxico é crucial no projeto de um
compilador

Os caracteres podem ser lidos em blocos (1 ou 4 Kbytes),
evitando-se a taxa de um acesso ao disco por caractere lido

Tais blocos podem ser armazenados um por vez num
buffer (string) e a análise de cada caractere pode ser feita nele

Essa bufferização pode ficar encapsulada numa função; no
caso do Mini-Pascal, isso poderia acontecer na função
NovoCarac
4.3 – Observação de Átomos
Seguintes

Algumas linguagens requerem, para a formação e
classificação de um átomo, a observação de átomos que o
seguem, dentro do programa

Em Fortran, espaços em branco são eliminados durante o
pré-processamento, dificultando a classificação dos átomos
Exemplo: Em Fortran, os comandos
DO
DO
5
5
I
I
=
=
1.25
1,25
são transformados
em
DO5I=1.25
DO5I=1,25
Os átomos de cada comando são:
1º) DO5I=1.25: (ID, DO5I), (ATRIB), (CTREAL, 1.25)
2º) DO5I=1,25: (DO), (ROTULO, 5), (ID, I), (ATRIB),
(CTINT, 1), (VIRG), (CTINT, 25)

Nos dois comandos, até antes da virgula ou do ponto, nada
se pode decidir sobre a formação e classificação de todos
esses átomos
1º) DO5I=1.25: (ID, DO5I), (ATRIB), (CTREAL, 1.25)
2º) DO5I=1,25: (DO), (ROTULO, 5), (ID, I), (ATRIB),
(CTINT, 1), (VIRG), (CTINT, 25)

Os átomos formados na tentativa de definição de outro deles
podem ser colocados numa fila pelo analisador léxico e
entregues um por um, quando solicitados pelo analisador
sintático

A função NovoAtomo do Mini-Pascal só deve procurar
novos caracteres, quando a fila de átomos estiver vazia
4.4 – Lex para Observar Átomos
Seguintes

A linguagem Lex admite uma expressão regular do tipo
r1 /r2
onde r1 e r2 são expressões regulares

Significado: uma cadeia se enquadra em r1 somente se for
seguida de outra cadeia que se enquadre em r2
Exemplo: Em Fortran, para o caso dos comandos
DO5I=1.25

e
DO5I=1,25
A palavra reservada do pode ser reconhecida pela expressão:
do/({letra}|{digito})*=({letra}|{digito})*,

Seja o programa em Lex a seguir:
%{
#define
DOLAR
0
#define
ID
1
#define
NUM
2
#define
DO
3
#define
VIRG
4
#define
PONTO
5
#define
EQ
6
union {
char *cadeia;
int valor;}
yylval;
%}
delim
[ \t\n]
ws
{delim}+
dig
[0-9]
letr
[A-Za-z]
num
{dig}+
id
{letr}({letr}|{dig})*
%%
{ws}
{ ;}
do/(({letr}|{dig})*=({letr}|{dig})*,)|{ws}
{return DO;}
{id}
{yylval.cadeia = yytext; return ID;}
{num}
{yylval.valor = atoi (yytext);
return NUM;}
"="
{return EQ;}
","
{return VIRG;}
"."
{return PONTO;}
"$"
{return DOLAR;}
%%
main () {
int i;
while (i = yylex ()) {
printf ("tipo = %d; atributo = ", i);
switch (i) {
case EQ: case PONTO:
case VIRG: case DO:
printf ("%s\n", yytext);
break;
case ID:
printf ("%s\n", yylval.cadeia);
break;
case NUM:
printf ("%d\n", yylval.valor);
break;
}
}
}
Rodando para a seguinte entrada:
xxx do 123 do5i=1,25 do5i=1.25 $
Resultados:
Obs.: o programa não
reconhece constantes reais
Observações finais:

Fortran é uma linguagem de difícil análise léxica, devido ao
controle das linhas e das colunas dos programas e outras
coisas mais

É mais fácil fazer um analisador manual do que usar um
gerador automático
Download

CES-41 Teoria Cap 4