Download - CES-41 COMPILADORES Aulas Práticas - 2013
CES-41 CES-41 COMPILADORESCOMPILADORES
Aulas Práticas - 2013Aulas Práticas - 2013
Capítulo I Capítulo I A Ferramenta FlexA Ferramenta Flex
Flex é um gerador de analisadores léxicos:Flex é um gerador de analisadores léxicos:
Tem como entrada Tem como entrada expressões regularesexpressões regulares e e implementa um implementa um autômato finitoautômato finito reconhecedor e reconhecedor e classificador dos átomos dos programas a serem classificador dos átomos dos programas a serem compiladoscompilados
Flex Flex é uma versão, para o sistema DOS, do mais é uma versão, para o sistema DOS, do mais conhecido gerador de analisadores léxicos: o conhecido gerador de analisadores léxicos: o LexLex do sistema do sistema UnixUnix
O analisador gerado é um programa escrito emO analisador gerado é um programa escrito em C C
FlexFlex, , YaccYacc, compilador , compilador GccGcc e outros softwares e outros softwares estão reunidos numa pasta denominada estão reunidos numa pasta denominada MingWMingW, , a ser usada nas a ser usada nas aulas práticasaulas práticas de CES-41 de CES-41
Programa 1.1: Saída de dadosPrograma 1.1: Saída de dados
Num editor de texto (Bloco de Notas, Borland Num editor de texto (Bloco de Notas, Borland C++, ou outros), criar o seguinte arquivo C++, ou outros), criar o seguinte arquivo extensão .lextensão .l ( (saida.lsaida.l, por exemplo):, por exemplo):
%%%%%%%%main () {main () {printf ("hello friends!");printf ("hello friends!");
}}
Guardar esse arquivo no diretório Guardar esse arquivo no diretório ee:\alunos\ces-41\mingw\bin:\alunos\ces-41\mingw\bin
No No prompt do DOSprompt do DOS, entrar no diretório , entrar no diretório ee:\alunos\ces-41\mingw\bin:\alunos\ces-41\mingw\bin
Executar os seguintes comandos:Executar os seguintes comandos:
flex saida.lflex saida.lgcc lex.yy.c -lflgcc lex.yy.c -lflaa
Executar: Executar: a > ttta > ttt
Abrir o arquivoAbrir o arquivo tttttt ( (No DOS:No DOS: more tttmore ttt))
Por curiosidade, abrir o arquivo Por curiosidade, abrir o arquivo lex.yy.clex.yy.c e e procurar no final a função procurar no final a função mainmain que aparece que aparece no arquivo no arquivo saida.lsaida.l
Flex Flex gera uma função fundamental chamada gera uma função fundamental chamada yylexyylex, mas não é chamada pela , mas não é chamada pela main main neste neste programaprograma
Programa 1.2: Entrada de dadosPrograma 1.2: Entrada de dados
Criar em Criar em ee:\alunos\ces-41\mingw\bin:\alunos\ces-41\mingw\bin o o arquivo arquivo entra.l entra.l com o seguinte programa:com o seguinte programa:
%%%%%%%%main () {main () {int i, n;int i, n;printf ("Digite o numero de repeticoes: ");printf ("Digite o numero de repeticoes: ");scanf ("%d", &n);scanf ("%d", &n);for (i = 1; i <= n; i++)for (i = 1; i <= n; i++)
printf ("\nhello friends!");printf ("\nhello friends!");
}}
Executar os seguintes comandos:Executar os seguintes comandos:
flex entra.lflex entra.lgcc lex.yy.c -lflgcc lex.yy.c -lflaa
Criar um arquivo Criar um arquivo entra.datentra.dat, colocando nele o , colocando nele o número número 1010
Executar os comandos:Executar os comandos:
a < entra.data < entra.data < entra.dat > ttta < entra.dat > ttt
Abrir o arquivo Abrir o arquivo tttttt (No DOS: (No DOS: more tttmore ttt))
Procurar novamente a função Procurar novamente a função main main no arquivo no arquivo lex.yy.clex.yy.c
Novamente Novamente mainmain não chama não chama yylexyylex
Esquema de produção de um Esquema de produção de um programa executável usando Flex:programa executável usando Flex:
Programa 1.3: Reconhecimento de Programa 1.3: Reconhecimento de whilewhile
Criar um arquivo (Criar um arquivo (while.lwhile.l) com o seguinte ) com o seguinte programa:programa:
%{%{#define #define WHILEWHILE 11%}%}%%%%whilewhile {return WHILE;}{return WHILE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);}}
Agora main chama yylex
yytext é uma variável string, global, do arquivo lex.yy.c
Criar um arquivo de dados (while.dat) com o seguinte conteúdo:fabio 111 while else whil whiles if BHwhile22
Executar:flex while.lgcc lex.yy.c –lfla < while.dat
%{%{#define #define WHILEWHILE 11%}%}%%%%whilewhile {return WHILE;}{return WHILE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);}}
Resultados:Resultados:a < while.data < while.datfabio 111fabio 111string: while; tipo: 1;string: while; tipo: 1; else whilelse whilstring: while; tipo: 1;string: while; tipo: 1;s if BHs if BHstring: while; tipo: 1;string: while; tipo: 1;2222
Arquivo de dados:fabio 111 while else whil whiles if BHwhile22
Funcionamento do yylex:yylex lê caractere por caractere da entrada e o coloca em yytextQuando não reconhece uma sequência guardada em yytext, ele escreve seu conteúdo e a esvazia Escreve tudo o que não é Escreve tudo o que não é reconhecido, inclusive reconhecido, inclusive espaços em brancoespaços em branco
%{%{#define #define WHILEWHILE 11%}%}%%%%whilewhile {return WHILE;}{return WHILE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);}}
Resultados:Resultados:a < while.data < while.datfabio 111fabio 111string: while; tipo: 1;string: while; tipo: 1; else whilelse whilstring: while; tipo: 1;string: while; tipo: 1;s if BHs if BHstring: while; tipo: 1;string: while; tipo: 1;2222
Arquivo de dados:fabio 111 while else whil whiles if BHwhile22
Funcionamento do yylex:
Continua percorrendo a Continua percorrendo a entrada, tentando entrada, tentando reconhecer algoreconhecer algo
Neste programa, só while é reconhecido
Ao reconhecer algo, executa a ação em frente
{return WHILE;}{return WHILE;}
%{%{#define #define WHILEWHILE 11%}%}%%%%whilewhile {return WHILE;}{return WHILE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);}}
Resultados:Resultados:a < while.data < while.datfabio 111fabio 111string: while; tipo: 1;string: while; tipo: 1; else whilelse whilstring: while; tipo: 1;string: while; tipo: 1;s if BHs if BHstring: while; tipo: 1;string: while; tipo: 1;2222
Arquivo de dados:fabio 111 while else whil whiles if BHwhile22
Funcionamento do yylex:
Retorna Retorna zerozero ao encontrar ao encontrar fim de arquivofim de arquivo
Tenta reconhecer a maior Tenta reconhecer a maior string possívelstring possível
Sempre esvazia Sempre esvazia yytextyytext no no início de sua execuçãoinício de sua execução
Estrutura de um programa em Flex:Estrutura de um programa em Flex: Um programa em Um programa em FlexFlex é dividido em é dividido em três partestrês partes::
DeclaraçõesDeclarações %%%% Regras de traduçãoRegras de tradução %%%% Rotinas auxiliaresRotinas auxiliares
As strings As strings “%%”“%%” são os são os separadoresseparadores dessas dessas partes partes
Seu uso é Seu uso é obrigatórioobrigatório, mesmo que o programa , mesmo que o programa não tenhanão tenha alguma(s) dessa(s) parte(s) alguma(s) dessa(s) parte(s)
Regras de tradução:Regras de tradução: Constituem-se na Constituem-se na parte principalparte principal de um programa de um programa
em em FlexFlex
São comandos da forma:São comandos da forma: p1 {ação1}p1 {ação1} p2 {ação2}p2 {ação2} pn {açãon}pn {açãon}
Cada Cada pi pi é uma é uma expressão regularexpressão regular e cada e cada açãoiaçãoi é é um fragmento de um fragmento de programaprograma em Cem C
Caso um Caso um conjunto máximoconjunto máximo de caracteres da de caracteres da entrada entrada se enquadrese enquadre em uma expressão regular em uma expressão regular pipi, a , a açãoiaçãoi é executada é executada
Declarações:Declarações:
Nelas estão inclusas:Nelas estão inclusas:
DeclaraçõesDeclarações de variáveis, tipos e de variáveis, tipos e diretivas de diretivas de pré-processamentopré-processamento ( (definedefine’s, ’s, includeinclude’s, etc), ’s, etc), tudo escrito tudo escrito em Cem C, delimitado por , delimitado por %{%{ e e %}%}
Definições regularesDefinições regulares componentes das componentes das expressões regularesexpressões regulares que aparecem nas regras que aparecem nas regras de tradução de tradução
Essas definições ficam fora dos Essas definições ficam fora dos %{%{ e e %}%}
Os arquivos Os arquivos incluídosincluídos devem conter somente devem conter somente declaraçõesdeclarações
Rotinas auxiliares:Rotinas auxiliares:
São as definições das São as definições das funções em Cfunções em C, , referenciadas nas ações das referenciadas nas ações das regras de regras de traduçãotradução
Podem trazer inclusão de Podem trazer inclusão de arquivos com arquivos com extensão .cextensão .c
A função A função mainmain pode aí aparecer pode aí aparecer
Programa 1.4: Reconhecimento de Programa 1.4: Reconhecimento de várias palavrasvárias palavras
Criar um arquivo com o seguinte programa:Criar um arquivo com o seguinte programa:%{%{#define #define WHILEWHILE 11#define #define IFIF 22#define #define IF11IF11 33#define #define FORFOR 44#define #define ELSEELSE 55%}%}%%%%whilewhile {return WHILE;}{return WHILE;}ifif {return IF;}{return IF;}if11if11 {return IF11;}{return IF11;}forfor {return FOR;}{return FOR;}elseelse {return ELSE;}{return ELSE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ()) printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);
}}
Arquivo de dados: fabio 111 while else wh whi whil whiles then if for BHifelse22 if1 if11
Resultados:a < reserv.datfabio 111string: while; tipo: 1;
string: else; tipo: 5; wh whi whilstring: while; tipo: 1;s thenstring: if; tipo: 2;
string: for; tipo: 4; BHstring: if; tipo: 2;
string: else; tipo: 5;22string: if; tipo: 2;1string: if11; tipo: 3;
Executar
Programa 1.4: Reconhecimento de Programa 1.4: Reconhecimento de várias palavrasvárias palavras
%{%{#define #define WHILEWHILE 11#define #define IFIF 22#define #define IF11IF11 33#define #define FORFOR 44#define #define ELSEELSE 55%}%}%%%%whilewhile {return WHILE;}{return WHILE;}ifif {return IF;}{return IF;}if11if11 {return IF11;}{return IF11;}forfor {return FOR;}{return FOR;}elseelse {return ELSE;}{return ELSE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ()) printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);
}}
Arquivo de dados: if if1 if11 if12
Resultados:a < reserv.datstring: if; tipo: 2;
string: if; tipo: 2;1string: if11; tipo: 3;
string: if; tipo: 2;12
Para if1 e if12, yylex lê 1{branco} e 12 Como if1{branco} e if12 não são reconhecidos, ele devolve 1{branco} e 12 para o buffer de entradaReconhece o if e retorna
Programa 1.5: Tratamento de espaços Programa 1.5: Tratamento de espaços em brancoem branco
%{%{#define #define WHILEWHILE 11#define #define IFIF 22#define #define IF11IF11 33#define #define FORFOR 44#define #define ELSEELSE 55%}%}%%%%[ \t\n\r]+[ \t\n\r]+ {printf ("\n");}{printf ("\n");}whilewhile {return WHILE;}{return WHILE;}ifif {return IF;}{return IF;}if11if11 {return IF11;}{return IF11;}forfor {return FOR;}{return FOR;}elseelse {return ELSE;}{return ELSE;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ()) printf ("\nstring: %6s; tipo: %d; \n", printf ("\nstring: %6s; tipo: %d; \n", yytext, i);yytext, i);
}}
Arquivo de dados: fabio 111 while else wh whi whil whiles then if for BHifelse22 if1 if11
Expressão regular reconhecedora de espaço de um ou mais brancos, tabulações, new-lines ou carriage-returns
[abc] significa: um caractere que pode ser a, b ou c
[abc]+ significa: um ou mais caracteres a, b ou c
[abc]* significa: zero ou mais caracteres a, b ou c
Resultados:Resultados:fabiofabio111111
string: while; tipo: 1;string: while; tipo: 1;
string: else; tipo: 5;string: else; tipo: 5;
whwhwhiwhiwhilwhil
string: while; tipo: 1;string: while; tipo: 1;ssthenthen
string: if; tipo: 2;string: if; tipo: 2;
string: for; tipo: 4;string: for; tipo: 4;
BHBHstring: if; tipo: 2;string: if; tipo: 2;
string: else; tipo: 5;string: else; tipo: 5;2222
string: if; tipo: 2;string: if; tipo: 2;11
string: if11; tipo: 3;string: if11; tipo: 3;
Reconhecimento da regra
[ \t\n\r]+[ \t\n\r]+ {printf ("\n");}{printf ("\n");}
Imprime Imprime new-linenew-line e não e não retornaretornaEsvazia Esvazia yytextyytext ao iniciar ao iniciar novo processo de novo processo de reconhecimentoreconhecimento
Arquivo de dados:
fabio 111 while else wh whi whil whiles then if for BHifelse22 if1 if11
Programa 1.6: Identificadores, números e Programa 1.6: Identificadores, números e operadoresoperadores
%{%{#define #define DOLAR DOLAR 00#define#define LTLT 11#define#define LELE 22#define#define EQEQ 33#define#define NENE 44#define#define GTGT 55#define#define GEGE 66#define#define IFIF 77#define #define THEN THEN 88#define #define ELSE ELSE 99#define#define IDID 1010#define#define NUMNUM 1111%}%}delimdelim [ \t\n\r][ \t\n\r]wsws {delim}+{delim}+digitodigito [0-9][0-9]letraletra [A-Za-z][A-Za-z]numnum {digito}+{digito}+idid {letra}({letra}|{digito})*{letra}({letra}|{digito})*%%%%
Definições regulares
O conteúdo do que está entre os colchetes [ e ] representa um só caractereEntre as chaves { e } coloca-se o nome de uma definição regularEntre os parêntesis ( e ) coloca-se uma sub-expressão regular
{ws}{ws} { ;}{ ;}ifif {return IF;}{return IF;}thenthen {return THEN;}{return THEN;}elseelse {return ELSE;}{return ELSE;}{id}{id} {return ID;}{return ID;}{num}{num} {return NUM;}{return NUM;}"<""<" {return LT;}{return LT;}"<=""<=" {return LE;}{return LE;}"=""=" {return EQ;}{return EQ;}"<>""<>" {return NE;}{return NE;}">"">" {return GT;}{return GT;}">="">=" {return GE;}{return GE;}"$""$" {return DOLAR;}{return DOLAR;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d;", printf ("\nstring: %6s; tipo: %d;", yytext, i);yytext, i);}}
É preciso usar chaves: {id}, {num} e {ws}
A função main é igual à dos programas anteriores, exceto por um ‘\n’
Por que?
{ws}{ws} { ;}{ ;}ifif {return IF;}{return IF;}thenthen {return THEN;}{return THEN;}elseelse {return ELSE;}{return ELSE;}{id}{id} {return ID;}{return ID;}{num}{num} {return NUM;}{return NUM;}"<""<" {return LT;}{return LT;}"<=""<=" {return LE;}{return LE;}"=""=" {return EQ;}{return EQ;}"<>""<>" {return NE;}{return NE;}">"">" {return GT;}{return GT;}">="">=" {return GE;}{return GE;}"$""$" {return DOLAR;}{return DOLAR;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d;", printf ("\nstring: %6s; tipo: %d;", yytext, i);yytext, i);}}
Executar com o seguinte arquivo de entrada:
then if xxx 123 < <> <= >= > = else $
Resultados:
string: then; tipo: 8;string: if; tipo: 7;string: xxx; tipo: 10;string: 123; tipo: 11;string: <; tipo: 1;string: <>; tipo: 4;string: <=; tipo: 2;string: >=; tipo: 6;string: >; tipo: 5;string: =; tipo: 3;string: else; tipo: 9;
Por curiosidade, colocar a regra do {id} antes da regra do if
Caso uma string seja reconhecida por 2 regras, a regra escolhida é a que aparece primeiro na lista de regras
{ws}{ws} { ;}{ ;}ifif {return IF;}{return IF;}thenthen {return THEN;}{return THEN;}elseelse {return ELSE;}{return ELSE;}{id}{id} {return ID;}{return ID;}{num}{num} {return NUM;}{return NUM;}"<""<" {return LT;}{return LT;}"<=""<=" {return LE;}{return LE;}"=""=" {return EQ;}{return EQ;}"<>""<>" {return NE;}{return NE;}">"">" {return GT;}{return GT;}">="">=" {return GE;}{return GE;}"$""$" {return DOLAR;}{return DOLAR;}%%%%main () {main () {
int i;int i;while (i = yylex ()) while (i = yylex ())
printf ("\nstring: %6s; tipo: %d;", printf ("\nstring: %6s; tipo: %d;", yytext, i);yytext, i);}}
then if xxx 123 < <> <= >= > = else $
Resultados:
string: then; tipo: 8;string: if; tipo: 7;string: xxx; tipo: 10;string: 123; tipo: 11;string: <; tipo: 1;string: <>; tipo: 4;string: <=; tipo: 2;string: >=; tipo: 6;string: >; tipo: 5;string: =; tipo: 3;string: else; tipo: 9;
Este é um exemplo de formação de átomos de uma mini-linguagemyylex retorna o tipo do átomo
Programa 1.7: AutômatoPrograma 1.7: Autômato%{%{#define#define ACEITAACEITA 11#define #define OUTRA OUTRA 22%}%}delimdelim [ \t\n\r][ \t\n\r]wsws {delim}+{delim}+aceitaaceita 0*1(0*10*1)*0*0*1(0*10*1)*0*stringstring [^ \t\n\r]+[^ \t\n\r]+%%%%{ws}{ws} { ;}{ ;}{aceita} {aceita} {return ACEITA;}{return ACEITA;}{string}{string} {return OUTRA;}{return OUTRA;}%%%%main () {main () {
int i;int i;while (i = yylex ())while (i = yylex ())
switch (i) {switch (i) {case ACEITA:case ACEITA:
printf ("%-20s: Aceita\n", yytext); printf ("%-20s: Aceita\n", yytext); break;break;
case OUTRA:case OUTRA:printf ("%-20s: Rejeitada\n", yytext); printf ("%-20s: Rejeitada\n", yytext); break;break;
}}}}
Reconhecimento de strings de 0’s e 1’s contendo um número ímpar de 1’s
Executar com o seguinte arquivo de entrada:
111 001 00101 11 00 100100 100100001 21 000001 00110001 01110001100
[^abc] : um caractere diferente de a, b e c
Exercício 1.1:Exercício 1.1: Escrever um programa em Flex Escrever um programa em Flex reconhecedor de strings sobre o alfabeto reconhecedor de strings sobre o alfabeto {0, 1}{0, 1} que possuam pelo menos dois dígitos que possuam pelo menos dois dígitos 0’s0’s seguidos seguidos
Exercício 1.2:Exercício 1.2: Escrever um programa em Flex Escrever um programa em Flex reconhecedor de strings sobre o alfabeto reconhecedor de strings sobre o alfabeto {0, 1, {0, 1, 2},2}, nas quais cada dígito nas quais cada dígito 22 é imediatamente é imediatamente seguido por dois seguido por dois 0’s0’s e cada dígito e cada dígito 11 é é imediatamente seguido por um dígito imediatamente seguido por um dígito 00 ou pelo ou pelo par de dígitos par de dígitos 2020
Exercício 1.3:Exercício 1.3: Escrever um programa em Flex Escrever um programa em Flex reconhecedor de strings sobre o alfabeto reconhecedor de strings sobre o alfabeto {0, 1}{0, 1}, , nas quais o número de dígitos nas quais o número de dígitos 00 é par ou o é par ou o número de dígitos número de dígitos 11 é ímpar é ímpar
Exercício 1.4:Exercício 1.4: Escrever um programa em Flex Escrever um programa em Flex reconhecedor de strings sobre o alfabeto reconhecedor de strings sobre o alfabeto {0, {0, 1}1}, nas quais a string , nas quais a string 101101 não é uma sub- não é uma sub-stringstring
Exercício 1.5:Exercício 1.5: Escrever um programa em Flex Escrever um programa em Flex reconhecedor de strings sobre o alfabeto reconhecedor de strings sobre o alfabeto {0, {0, 1}1}, nas quais o número de dígitos , nas quais o número de dígitos 00 é par e o é par e o número de dígitos número de dígitos 11 é ímpar é ímpar
Programa 1.8: Atributos para os átomos Programa 1.8: Atributos para os átomos além do tipoalém do tipo
Sejam os seguintesSejam os seguintes define define’s’s para tipos de para tipos de átomos:átomos:
%{%{#define #define ELSE ELSE 11#define #define IF IF 22#define#define WHILE WHILE 33#define#define IDID 44#define#define CTINTCTINT 55#define#define OPRELOPREL 66%}%}
O tipo dos átomos ELSE, IF e WHILE já os define completamente
Os átomos de tipos ID, CTINT e OPREL necessitam de mais informações para ficarem completamente definidos:
ID: sua stringCTINT: seu valor numéricoOPREL: qual o operador relacional
Solução: atributos para os átomos
%{%{#include #include <string.h><string.h>#define #define ELSE ELSE 11#define #define IF IF 22#define#define WHILE WHILE 33#define#define IDID 44#define#define CTINTCTINT 55#define#define OPRELOPREL 66#define #define LT LT 11#define #define LE LE 22#define#define GTGT 33#define#define GEGE 44#define#define EQEQ 55#define#define NENE 66union {union {
char string[50];char string[50];int atr, valor;int atr, valor;char carac;char carac;
} yylval;} yylval;%}%}
yylval: variável global com vários campos:Um campo para cada tipo de átomo
Atributos:
ID: stringCTINT: valor numéricoOPREL: operador
Define’s para os atributos dos átomos de tipo OPREL
delimdelim [ \t\n\r][ \t\n\r]wsws {delim}+{delim}+digitodigito [0-9][0-9]letraletra [A-Za-z][A-Za-z]ctintctint {digito}+{digito}+idid {letra}({letra}|{digito})*{letra}({letra}|{digito})*%%%%{ws}{ws} { ;}{ ;}elseelse {return ELSE;}{return ELSE;}ifif {return IF;}{return IF;}whilewhile {return WHILE;}{return WHILE;}{id}{id} {strcpy (yylval.string, yytext); return ID;}{strcpy (yylval.string, yytext); return ID;}{ctint}{ctint} {yylval.valor = atoi(yytext); return CTINT;}{yylval.valor = atoi(yytext); return CTINT;}"<""<" {yylval.atr = LT; return OPREL;}{yylval.atr = LT; return OPREL;}"<=""<=" {yylval.atr = LE; return OPREL;}{yylval.atr = LE; return OPREL;}">"">" {yylval.atr = GT; return OPREL;}{yylval.atr = GT; return OPREL;}">="">=" {yylval.atr = GE; return OPREL;}{yylval.atr = GE; return OPREL;}"==""==" {yylval.atr = EQ; return OPREL;}{yylval.atr = EQ; return OPREL;}"!=""!=" {yylval.atr = NE; return OPREL;}{yylval.atr = NE; return OPREL;}%%%% Alguns átomos formados por yylex são
compostos pelo valor retornado e pelo valor de algum campo de yylval
main () {main () {int i;int i;printf ("\n texto | tipo | atributo \n");printf ("\n texto | tipo | atributo \n");printf ("--------------------------------\n");printf ("--------------------------------\n");while (i = yylex ()) {while (i = yylex ()) {
printf ("%10s|%10d|", yytext, i);printf ("%10s|%10d|", yytext, i);switch (i) {switch (i) {
case ID:case ID:printf ("%10s", yylval.string); break;printf ("%10s", yylval.string); break;
case CTINT:case CTINT:printf ("%10d", yylval.valor); break;printf ("%10d", yylval.valor); break;
case OPREL:case OPREL:printf ("%10d", yylval.atr); break;printf ("%10d", yylval.atr); break;
}}printf ("\n");printf ("\n");
}}}} Executar com o seguinte
arquivo de entrada:
while if else xxx 123 < <= > >= == !=
Acrescentar pelo meio da entrada:
(&%
Programa 1.9: Tratamento de caracteres Programa 1.9: Tratamento de caracteres estranhosestranhos
Acrescentar a seguinte regra no final das Acrescentar a seguinte regra no final das regras de tradução:regras de tradução:
.. {yylval.carac = yytext[0]; return INVAL;}{yylval.carac = yytext[0]; return INVAL;}
Acrescentar no meio dos Acrescentar no meio dos definedefine’s a declaração:’s a declaração:
#define INVAL 7#define INVAL 7
Acrescentar na função Acrescentar na função main ( )main ( )::
case INVAL: printf ("%10c", yylval.carac); break;case INVAL: printf ("%10c", yylval.carac); break;
O ponto ‘.’ é um meta-símbolo que significa qualquer caractere, exceto o new-line
Alterações no Programa 1.8
Exercício 1.6: Exercício 1.6: Acrescentar ao programa anterior Acrescentar ao programa anterior regras para reconhecimento de regras para reconhecimento de constantes reaisconstantes reais, , caracterescaracteres e e stringsstrings
Constante real: Constante real: um ou mais um ou mais dígitosdígitos seguidos de seguidos de um um ponto decimalponto decimal, seguido de zero ou mais , seguido de zero ou mais dígitosdígitos
A constante pode ainda estar na A constante pode ainda estar na notação notação exponencialexponencial::
Acrescenta-se Acrescenta-se opcionalmenteopcionalmente o seguinte: a o seguinte: a letra letra EE maiúscula ou minúscula, seguida maiúscula ou minúscula, seguida opcionalmente de opcionalmente de + ou -+ ou -, seguidos de um ou mais , seguidos de um ou mais dígitosdígitos
Exemplos: 12. 3.57 0.23 3.2E19 7.5e-45Exemplos: 12. 3.57 0.23 3.2E19 7.5e-45
Exercício 1.6: Exercício 1.6: Acrescentar ao programa Acrescentar ao programa anterior regras para reconhecimento de anterior regras para reconhecimento de constantes reaisconstantes reais, , caracterescaracteres e e stringsstrings
Caractere: Caractere: qualquer caractere entre qualquer caractere entre apóstrofosapóstrofos; cuidado com os caracteres ; cuidado com os caracteres iniciados pela iniciados pela barra ‘\’barra ‘\’; cuidado quando o ; cuidado quando o caractere for o caractere for o apóstrofoapóstrofo
Exemplos: ‘w’ ‘\n’ ‘\‘’Exemplos: ‘w’ ‘\n’ ‘\‘’ Strings: Strings: conjunto de caracteres entre aspas; conjunto de caracteres entre aspas;
mesmos cuidados; cuidado quando o caractere mesmos cuidados; cuidado quando o caractere for for aspasaspas
Exemplo: “w\n123\g\“”Exemplo: “w\n123\g\“”Executar o programa com o seguinte arquivo:while if else xxx 123 12.53 13. 31.5E-12 1.5e11 19.E+27 ';' '\'' '\n' 's' "ab \\ \" \n'z" '"' "'"
Dicas:Dicas: Definir novos tipos de átomos:Definir novos tipos de átomos:
Constante real, constante caractere e Constante real, constante caractere e constante stringconstante string
Novo campo para Novo campo para yylvalyylval::union {union {char string[50];char string[50];int atr, valor;int atr, valor;float valreal;float valreal;char carac;char carac;
} yylval;} yylval;
Caractere Caractere e e string string podem usar o campo podem usar o campo string string do do yylvalyylval
Criar Criar definições regularesdefinições regulares para para constante constante realreal, constante , constante caracterecaractere e constante e constante stringstring
Constante caractere:Constante caractere:carac1carac1 \\.|[^\\']\\.|[^\\']ctcaracctcarac '{carac1}''{carac1}'
Constante string:Constante string:carac2carac2 \\.|[^\\\"]\\.|[^\\\"]stringstring \"{carac2}*\"\"{carac2}*\"
Criar novas Criar novas regras de traduçãoregras de tradução para para constante constante realreal, , ctcarac ctcarac e e stringstring
Aumentar o Aumentar o switchswitch da função da função mainmain
Qualquer caractere precedido pela ‘\’ ou qualquer caractere que não seja ‘\’ ou apóstrofo isolados
Qualquer caractere precedido pela ‘\’ ou qualquer caractere que não seja ‘\’ ou aspas isolados
Solução: no arquivo RealCharString.l
Página do Professor
Exercício 1.7: Exercício 1.7: Acrescentar ao programa Acrescentar ao programa anterior regras para anterior regras para reconhecimento e reconhecimento e descarte de comentáriosdescarte de comentários
Comentários: Comentários: tudo entre tudo entre /*/* e e */*/; ;
Não é para criar um átomo do Não é para criar um átomo do tipo tipo comentáriocomentário
Eles devem ser lidos e Eles devem ser lidos e descartadosdescartados, antes do , antes do retorno da função retorno da função yylexyylex
Exercício 1.7: Exercício 1.7: Acrescentar ao programa Acrescentar ao programa anterior regras para anterior regras para reconhecimento e reconhecimento e descarte de comentáriosdescarte de comentários
Acrescentar uma linha com o protótipoAcrescentar uma linha com o protótipovoid comentario (void);void comentario (void);
entre os delimitadores entre os delimitadores %{ e %}%{ e %}
Acrescentar a seguinte regra de tradução:Acrescentar a seguinte regra de tradução:"/*""/*" {comentario ();}{comentario ();}
Acrescentar e programar a seguinte rotina Acrescentar e programar a seguinte rotina auxiliar:auxiliar:
void comentario () { ----- }void comentario () { ----- }
Idéia: Idéia: usar o seguinte usar o seguinte autômatoautômato depois de depois de detectado o par detectado o par /*/*::
Executar o programa com o seguinte arquivo:while if /* else xxx */ 123 /*12.53 13. 31.5E-12 */1.5e11/* 19.E+27*/ ';' '\'' '\n' 's' "ab \\ \" \n'z"
void comentario () {void comentario () {char c; int estado;char c; int estado;estado = 1;estado = 1;while (estado != 3) {while (estado != 3) {
switch (estado) {switch (estado) {case 1:case 1:
c = input ();c = input ();if (c == EOF) estado = 3;if (c == EOF) estado = 3;else if (c == '*') estado = 2;else if (c == '*') estado = 2;break;break;
case 2:case 2:- - - - -- - - - -
}}}}
}}