Vous êtes sur la page 1sur 14

Prof.

Von Zuben DCA/FEEC/Unicamp


EA877 1S99

Lex & Yacc1


objetivo genrico: ferramentas de auxlio na escrita de programas que
promovem transformaes sobre entradas estruturadas.
objetivo especfico: ferramentas desenvolvidas para programadores de
compiladores e interpretadores.
objetivos especficos secundrios: ferramentas vlidas tambm para outras
aplicaes, como deteco de padres em arquivos de dados, linguagens de
comandos, etc.
vantagens

sobre

ferramentas

alternativas:

permitem

um

rpido

desenvolvimento de prottipos e uma manuteno simples do software.


tanto o Lex como o Yacc foram desenvolvidos nos Bell Laboratories.
1

Este material est baseado em Levine, Mason & Brown, lex & yacc, OReilly & Associates, Inc., 1995.

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

Yacc (Yet another compiler-compiler): Stephen C. Johnson (1975)


Lex: Mike Lesk & Eric Schmidt desenvolvido posteriormente para
trabalhar junto com o Yacc
Free Software Foundation Projeto GNU flex & bison
bison: Robert Corbett & Richard Stallman
verso padronizada: POSIX 1003.2
existem verses tambm para arquiteturas padro IBM/PC
gcc (GNU C compiler): foi desenvolvido com Lex & Yacc
etapas:
Anlise lxica: dividir as entradas em unidades coerentes (tokens)
Anlise sinttica: descobrir o relacionamento entre os tokens
toda tarefa que envolve ambas ou uma das etapas acima candidata a ser
resolvida via Lex e/ou Yacc.
2

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

papel do Lex: toma um conjunto de descries de possveis tokens e produz


uma rotina em C que ir identificar estes tokens analisador lxico
descries de possveis tokens: expresses regulares (especificao lxica)
papel do Yacc: toma uma descrio concisa de uma gramtica e produz uma
rotina em C que ir executar a anlise sinttica ou parsing.
nota1: um analisador lxico desenvolvido usando Lex quase sempre mais
rpido do que um analisador lxico escrito diretamente em C.
nota2: um analisador sinttico desenvolvido utilizando Yacc geralmente
mais lento do que um analisador sinttico escrito diretamente em C. Mas o
ganho no desenvolvimento e manuteno do programa enorme.

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

1. Geradores de Analisadores Lxicos


a anlise lxica pode ser vista como a primeira fase do processo de
compilao.
sua principal tarefa ler uma seqncia de caracteres de entrada, geralmente
associados a um cdigo-fonte, e produzir como sada uma seqncia de itens
lxicos.
por outro lado, a anlise sinttica tem por objetivo agrupar os itens lxicos em
blocos de comandos vlidos, procurando reconstruir uma rvore sinttica,
conforme ilustrado na figura 1.
os itens lxicos so geralmente denominados tokens e correspondem a
palavras-chave, operadores, smbolos especiais, smbolos de pontuao,
identificadores (variveis) e literais (constantes) presentes em uma linguagem.

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

o analisador lxico pode executar tambm algumas tarefas secundrias de


interface com o usurio, como reconhecer comentrios no cdigo-fonte,
eliminar caracteres de separao (espao, tabulao e fim de linha), associar
mensagens de erro provenientes de outras etapas do processo de compilao
com as linhas correspondentes no cdigo-fonte, realizar pr-processamento,
etc.
Entrada de
caracteres
(cdigofonte)

token
Analisador
lxico

Solicitao do prximo token

Analisador
sinttico

rvore
sinttica

Tabela
de
smbolos

Figura 1 - Interao entre anlise lxica e sinttica


5

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

1.1. Lex
a ferramenta de automatizao da anlise lxica a ser estudada utiliza o
comando lex disponvel no UNIX (ou seu correspondente flex da GNU). O
programa Lex produz automaticamente um analisador lxico a partir de
especificaes de expresses regulares, passveis de representao na forma
de autmatos finitos.
o programa Lex geralmente utilizado conforme ilustrado na figura 2. O
formato geral para a especificao de uma gramtica regular em Lex
definies

/* opcional */

%%
regras
%%
rotinas do usurio

/* opcional */

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

programa-fonte
do Lex
lex.l

Compilador

lex.yy.c

Lex

Compilador

lex.yy.c

a.out

Seqncia
de
entrada

a.out

Seqncia
de
tokens

Figura 2- Criando um analisador lxico com Lex

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

a seo de definies inclui:


1. a definio de macros como:
digito [01]+

/* substituir {digito} por [01]+ ao processar as regras */

frac

.[0-9]+

/* substituir {frac} por .[0-9]+ ao processar as regras */

nl

\n

/* substituir {nl} por \n ao processar as regras */

2. a incluso das linhas de comando em C, que devem ser delimitadas por <%{>
e <%}>, como:
%{
#include <y.tab.h>
extern int yylval;
%}
a redefinio dos tamanhos das tabelas utilizadas pelo gerador, tais como
nmero de ns da rvore sinttica, nmero de transies e nmero de estados.

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

a seo de regras define a funcionalidade do analisador lxico. Cada regra


compreende uma seqncia vlida de caracteres (utilizando literais e
expresses regulares) e as aes semnticas associadas a ela.
Lex armazena temporariamente a subseqncia de caracteres identificada na
varivel yytext do tipo <char *>. Podemos, ento, usar a funo sscanf()
da biblioteca de C para convert-la em outros tipos de dados. A varivel
reservada pelo Lex para armazenar o resultado da converso yylval. A
seo de rotinas do usurio opcional e ela usada para incluir rotinas em C
desenvolvidas pelos usurios, como o programa yylex() que chama o
analisador lxico gerado pelo Lex.
quando uma seqncia de caracteres de entrada casa com mais de uma regra,
Lex adota uma das seguintes estratgias para resolver ambigidades:
escolher a regra que consegue casar a maior seqncia de caracteres possvel;

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

quando h mais de uma regra que case com a maior seqncia de caracteres,
escolher aquela que aparece primeiro na seo de regras.
embora o Lex seja relativamente simples de entender, ele freqentemente
associado ao Yacc (j no to simples) em aplicaes no domnio dos
compiladores. No entanto, o Lex pode (e deve) ser utilizado tambm como
uma ferramenta nica.

2. Geradores de Analisadores Sintticos


Ferramentas similares e complementares aos geradores de analisadores
lxicos.
Ferramenta mais comum: yacc (yet another compiler-compiler)
lex gera a funo yylex( ) que retorna o identificador de um item lxico
reconhecido.

10

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

yacc gera a funo yyparse( ), que analisa os itens lxicos e decide se eles
formam ou no uma sentena vlida.

2.1. Passos para gerar analisador sinttico


Escrever programa analisador lxico ou usar ferramenta lex para tal.
Escrever gramtica da linguagem em arquivo com extenso .y .
Escrever programa analisador sinttico ou usar a ferramenta yacc para tal.
Compilar e ligar os programas-fonte.
Para yylex( ) e yyparse( ) trabalharem em conjunto preciso garantir que os
tokens e seus valores sejam comuns s duas funes.

11

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

2.2. Formato geral da gramtica de Yacc


Similar ao da gramtica de lex
trs sees no arquivo .y:
definies (declarao de nomes e tipos de tokens, de variveis, etc)
%%
regras (contm as produes da gramtica em BNF)
smbolo : derivaes

{aes semnticas}

%%
rotinas do usurio (contm a funo principal main( ) e outras rotinas do
usurio)

12

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

3. Cooperao entre LEX e YACC


para obter um analisador sinttico com o uso de Lex e Yacc necessrio (veja
figura 3):
1. especificar a gramtica de definio dos itens lxicos em linguagem de
especificao de Lex num arquivo, por conveno com extenso <.l>, e gerar
o analisador lxico em C (yylex()) atravs do seguinte comando:
flex <filename>.l. O arquivo que contm yylex() denominado
<lex.yy.c>.
2. especificar a estrutura sinttica da linguagem atravs da linguagem de
especificao de Yacc num arquivo, por conveno com extenso <.y>, e
gerar o analisador sinttico em C (yyparse()) atravs do seguinte
comando: yacc -d <filename>.y. A chave <d> indica que um arquivo
de definio de itens lxicos e tipo de dados da varivel global <yylval>,
13

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

filename.tab.h, deve ser gerado. Este arquivo estabelece a dependncia


simblica entre o analisador lxico e o sinttico. Yacc inclui automaticamente
as chamadas a yylex() para obter os itens lxicos e os seus valores. O
arquivo que contm yyparse() chamado <filename.tab.c>;
3. compilar e ligar os programas-fonte com outros programas adicionais atravs
do seguinte comando:
cc -o filename filename.tab.c lex.yy.c -ly -ll
para gerar o cdigo executvel, por exemplo <filename>. Os indicadores <y>
e <l> correspondem incluso de rotinas das bibliotecas em C <liby.a> e
<libl.a>, respectivamente.

14

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

Gramtica
especificada no
formato LEX
num arquivo
com extenso
*.l
lex
ou flex

Gramtica
especificada no
formato YACC
num arquivo
com extenso
*.y
yacc
ou bison

Analisador lxico
yylex()
no arquivo lex.yy.c

Analisador sinttico
yyparse() no arquivo
filename.tab.c

Outros
programas
em C

cc

Rotinas das
bibliotecas libl.a e
liby.a

Programa

Figura 3 - Esquema do uso de Lex e Yacc


15

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

Exemplos: Os programas a seguir devem ser compilados com o comando


flex p<?>.l, seguido do comando gcc lex.yy.c -ll -o p<?>.
p1.l
%%
[A-Z]
.

printf("%c", yytext[0]+'a'-'A');
ECHO;

Execute o seguinte comando: p1 < p1.l

p2.l
%{
int nlin=0;
%}
Qqchar
NovaLinha
%%

.*
[\n]

^{Qqchar}{NovaLinha} {nlin=nlin+1;printf("%4d\t%s", nlin, yytext);}

Execute o seguinte comando: p2 < p2.l


16

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

p3.l
Dia
[" "](00-11)[:]
Tarde
[" "](12-17)[:]
Noite
[" "](18-23)[:]
%%
{Dia}
printf("\nBom Dia !\n");
{Tarde} printf("\nBoa Tarde !\n");
{Noite} printf("\nBoa Noite !\n");
.

Execute o seguinte comando: date | p3


p4.l
%{
int count=0;
%}
%%
[^ \t\n]+ count++;
%%
main(){
yylex();
printf("\n%d palavras contadas.\n", count);
}
17

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

p5.l
%%
[.]
;
then
;
var
;
[{]
printf("/*");
[}]
printf("*/");
mod
printf("%%");
or
printf("||");
and
printf("&&");
begin
printf("{");
end
printf("}");
program.*[(].*$ printf("main()\n{");
[^:><][=]
printf("==");
[:][=]
printf("=");
[<][>]
printf("!=");
^.*integer;
ShuffleInt();
.
ECHO;
%%
ShuffleInt()
{ int i;
printf("int ");
for(i=0; yytext[i]!=':'; i++) printf("%c", yytext[i]);
printf(";");
}

18

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

p6.l
%%
[1-9][0-9]*
0[0-7]+
0[x|X][0-9A-Fa-f]+
.?

printf("Decimal\n");
printf("Octal\n");
printf("\nHexadecimal\n");
printf("Nao numerico\n");

*******************************
Calculadora (lex)
*******************************

%{
#include "y.tab.h"
%}
integer
[0-9]+
nl
\n
%%
[ \t]+
;
{integer} {sscanf(yytext,"%d",&yylval.integer);return INTEGER;}
{nl}
{extern int lineno; lineno++; return '\n'; }
.
{return yytext[0];}
%%

19

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

*******************************
Calculadora (yacc)
*******************************
%{
#include <stdio.h>
%}
%union {
double real;
int integer;
}
%token <integer> INTEGER
%type <integer> expr;
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%%
lines: /* nothing */
| lines line
;
line: '\n'
| expr '\n' {printf("%d\n", $1);}
| error '\n' {yyerror();}
;

20

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

expr: INTEGER
| expr '+'
| expr '-'
| expr '*'
| expr '/'

expr
expr
expr
expr

{$$ = $1 + $3;}
{$$ = $1 - $3;}
{$$ = $1 * $3;}
{if($3) $$ = $1 / $3;
else {
yyerror("divide by zero");
}
}
| '(' expr ')' {$$ = $2;}
| '-' expr %prec UMINUS {$$ = - $2;}
;

%%
int lineno = 0;
main(){
yyparse();
}
yyerror(s)
char *s;
{
printf("calc: %s", s);
printf("line %d\n", lineno);
}

21

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

*******************************
Calculadora "cientfica" (lex)
*******************************
%{
#include "y.tab.h"
%}
integer
real
nl
%%
[ \t]+ ;
{integer}
{real}
{nl}
sin
cos
tan
.
%%

[0-9]+
[0-9]*"."[0-9]*
\n

{sscanf(yytext, "%d", &yylval.integer); return INTEGER;}


{sscanf(yytext, "%lf", &yylval.real); return REAL;}
{extern int lineno; lineno++; return '\n'; }
{return SIN;}
{return COS;}
{return TAN;}
{return yytext[0];}

22

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

*******************************
Calculadora "cientfica" (yacc)
*******************************
%{
#include <stdio.h>
#include <math.h>
%}
%union {
double real;
int integer;
}
%token <integer> INTEGER
%token <real> REAL
%token SIN COS TAN
%type <integer> expr_i;
%type <real> expr;
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%%
lines: /* nothing */
| lines line
;

23

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

line: '\n'
| expr '\n' {printf("%lf\n", $1);}
| error '\n' {yyerror();}
;
expr_i: INTEGER;
expr: REAL
| expr_i {$$ = $1;}
| SIN '(' expr ')' {$$ = sin($3);}
| COS '(' expr ')' {$$ = cos($3);}
| TAN '(' expr ')' {$$ = tan($3);}
| expr '+' expr {$$ = $1 + $3;}
| expr '-' expr {$$ = $1 - $3;}
| expr '*' expr {$$ = $1 * $3;}
| expr '/' expr {if($3) $$ = $1 / $3;
else {
yyerror("divide by zero");
}
}
| '(' expr ')' {$$ = $2;}
| '-' expr %prec UMINUS {$$ = - $2;}
;

24

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

%%
int lineno = 0;
main(){
yyparse();
}
yyerror(s)
char *s;
{
printf("calc: %s", s);
printf("line %d\n", lineno);
}

4. Autmatos finitos
Definio: Um autmato finito M uma quntupla ordenada M = {S, s0, F, A, g}:
1. S um conjunto finito de estados;
2. s0 S o estado inicial;
3. F S um conjunto de estados finais;
4. A um alfabeto de entrada;
5. g: S A S um conjunto finito de aplicaes de transio.
25

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

5. Expresses regulares
Uma expresso regular um objeto matemtico especfico que permite a escrita concisa
de uma seqncia vlida de caracteres. Para tanto, so utilizados operadores na forma de
metacaracteres, sendo que os mais comuns so apresentados na tabela 1.
Mesmo sabendo ser possvel descrever a sintaxe lxica de uma linguagem utilizando
gramticas livres de contexto, esta descrio geralmente feita por meio de expresses
regulares pelas seguintes razes:
1. as regras lxicas de uma linguagem so geralmente muito simples, no necessitando
uma descrio gramatical (recurso demasiadamente poderoso para tal fim);
2. expresses regulares geralmente fornecem uma notao mais concisa e fcil de entender
do que a correspondente representao gramatical;
3. analisadores lxicos automticos construdos a partir de expresses regulares so mais
eficientes que aqueles construdos a partir de gramticas arbitrrias.

26

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

Tabela 1 - Metacaracteres utilizados em expresses regulares


Operador
?
*
+
|
()
.
^
$
[]
{}
\

Significado
Exemplo
a expresso anterior opcional
54?1 541 ou 51
qualquer repetio, inclusive vazio
a* {,a,aa,...}
qualquer repetio, exclusive vazio
a+ {a,aa,...}
alternativa entre duas expresses
a|b a ou b
agrupamento de expresses
qualquer caracter, exceto linefeed
casa com o incio de uma linha, exceto quando est
entre [ ], quando significa complemento.
fim de uma linha
qualquer caracter especificado
[abc] {a,b,c}
dentro de [ ], qualquer caracter entre os extremos
[0-9] {0,1,2,3,4,5,6,7,8,9}
indica o nmero de repeties permitido, ou substitui
a{1,2} {a,aa}
uma definio macro
{digito} [0-1]+
permite interpretar o prximo caracter como caracter
. \.
comum. tambm utilizado para representar
\t tabulao
caracteres no-imprimveis
\b blank
\n linefeed
especifica um conjunto de seqncias seguida de uma [012]+/Y aceita qualquer
expresso
seqncia composta de 0, 1 e
2 seguida de Y

27

Prof. Von Zuben DCA/FEEC/Unicamp


EA877 1S99

Exerccios
1. Apresente a expresso regular mais compacta que seja capaz de descrever
qualquer nmero decimal positivo (e somente eles), com a parte inteira sendo
separada da parte fracionria por ponto, quando for o caso. Por exemplo, so
seqncias vlidas: 0.89 / 12 / 4.0 / .32748 / 34.52
2. Como uma alternativa expresso regular obtida acima, apresente o autmato
finito que permite validar ou no qualquer nmero decimal positivo. Resolva
a questo com base nas seguintes hipteses:
existem dois tipos de smbolos terminais ou eventos: "[0-9]" e ".";
utilize dois estados finais, lembrando que a seqncia de caracteres s vlida
se for atingido um estado final e no houver mais caracteres a processar.
para qualquer estado, deve haver uma lei de transio de estados a partir de
cada um dos eventos existentes.
28

Vous aimerez peut-être aussi