notas pr´aticas e exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em c e compreendem...

41
Notas Pr´ aticas e Exerc´ ıcios para apoio ` a disciplina de Processamento de Linguagens LEX/YACC Maria Jo˜ao Tinoco Varanda Pereira Fevereiro 2006

Upload: vophuc

Post on 20-Jan-2019

227 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Notas Praticas e Exercıcios para apoio a disciplina de

Processamento de Linguagens

LEX/YACC

Maria Joao Tinoco Varanda Pereira

Fevereiro 2006

Page 2: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2

Page 3: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Conteudo

1 Introducao 91.1 Compiladores e Geradores de Compiladores . . . . . . . . . . . . . . . . . . . . . . . . . . 91.2 Ferramentas LEX e YACC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 LEX 132.1 Teoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.1.1 Algoritmo de funcionamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.1.2 Automatos de Estados Finitos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2 Pratica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.1 Exemplo de funcionamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.2 Divisao de um ficheiro Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.3 Expressoes Regulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.2.4 Gramatica do Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.2.5 Variaveis pre-definidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2.6 Alguns exemplos simples de programas Lex . . . . . . . . . . . . . . . . . . . . . . 18

2.3 Construcao de um preprocessador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.4 Construcao de um analisador lexico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.5 Mais acerca do Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.5.1 Estados iniciais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.5.2 Palavras reservadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.5.3 Debug de um programa Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.6 Exercıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.7 Exercıcios de exames dos anos anteriores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

3 YACC 273.1 Teoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.2 Pratica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.2.1 Divisao de um ficheiro Yacc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283.2.2 Gramatica do Yacc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.2.3 Ligacao entre o Lex e Yacc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.3 Mais acerca do Yacc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.3.1 Recursividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.3.2 Ambiguidade IF ELSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.3.3 Mensagens de erro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.3.4 Atributos herdados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.3.5 Accoes intermedias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343.3.6 Debug de um programa Yacc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.4 Exercıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.5 Exercıcios de exames dos anos anteriores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3

Page 4: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CONTEUDO

4

Page 5: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Lista de Figuras

1.1 Sequencia de compilacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.2 Construcao de um compilador usando Lex/Yacc . . . . . . . . . . . . . . . . . . . . . . . . 11

2.1 Automato finito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

5

Page 6: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

LISTA DE FIGURAS

6

Page 7: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Lista de Tabelas

2.1 Primitivas usadas na especificacao de padroes . . . . . . . . . . . . . . . . . . . . . . . . . 152.2 Exemplos de expressoes regulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.3 Funcoes e variaveis pre-definidas do Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.4 Correspondencia entre vogais e transformacoes . . . . . . . . . . . . . . . . . . . . . . . . 24

7

Page 8: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

LISTA DE TABELAS

8

Page 9: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Capıtulo 1

Introducao

Estes apontamentos tem por objectivo explicar como se constroi compiladores usando LEX/YACC. Estasferramentas sao usadas para gerar analisadores lexicos e sintacticos. Assume-se que os alunos conseguemprogramar em C e compreendem estruturas de dados como listas ligadas e arvores.Ate 1975, construir um compilador era um processo lento e trabalhoso. A partir dessa data surgemtrabalhos como o de Lesk [SL75] e Johnson [Joh75] que apresentam o LEX/YACC como ferramentas quetornariam a construcao de compiladores uma tarefa mais simples. Detalhes de implementacao podem serencontrados em [ASU86].

1.1 Compiladores e Geradores de Compiladores

Um compilador divide-se em duas metades: o bloco frontal (front-end) responsavel pelo reconhecimentodo programa fonte; e o bloco de retaguarda (back-end) que se encarrega da geracao de codigo para amaquina destino. Por outro lado, um compilador e constituıdo por quatro componentes essenciais: oanalisador lexico (scanner), o analisador sintactico (parser), o analisador semantico (attribute evaluator)e o gerador de codigo.Assim, os analisadores lexico, sintactico e semantico constituem o bloco frontal. O bloco de retaguardaconsiste no gerador de codigo e nos modulos de optimizacao.A especificacao de uma linguagem divide-se em varias fases. Ao nıvel lexico (para definir as palavras dalinguagem) usa-se normalmente expressoes regulares. Uma expressao regular especifica uma sequencia decaracteres que podera eventualmente pertencer ao texto fonte e e constituıda por caracteres de texto, derepeticao ou de escolha. Ao nıvel sintactico (para definir como se juntam as palavras da linguagem paraformar frases validas) sao usadas gramaticas independentes de contexto.Ao nıvel semantico, a especificacao depende do tipo de gerador de compiladores que se usa: uns efec-tuam uma traducao orientada a sintaxe (e o caso do Yacc) e outros efectuam uma traducao orientada asemantica. Neste ultimo caso, sao usadas gramaticas de atributos. Nas gramaticas de atributos [Hen92],a cada sımbolo da gramatica independente de contexto, que define a sintaxe da linguagem, associa-seum conjunto de atributos. O valor dos atributos define-se atraves de regras semanticas associadas asproducoes e o calculo desse valor depende, normalmente, dos valores de outros atributos (pertencentesou nao a mesma producao). A tarefa de producao da saıda, resultado final do processador, e especificadaatraves da definicao de esquemas de traducao, que associadas as producoes da gramatica de atributos,determinam como se deve construir a saıda em funcao do significado reconhecido.Um gerador de compiladores usa as especificacoes da linguagem a ser processada e gera um executavel.Exemplos de geradores de compiladores: Lex/Yacc [Nie], [ABH91], [AF91]; Ox [Bis93](uma extensao aoLex/Yacc); PCCTS [PDC93] (tambem uma evolucao do Lex/Yacc); Synthesizer Generator [RT89] uma po-derosa e muito divulgada ferramenta que gera, a partir de uma especificacao de alto nıvel de abstraccao,um editor de texto estruturado associado a um compilador incremental; ELI [GHK90] uma ferramenta degeracao de compiladores que se caracteriza essencialmente pelo facto das especificacoes usadas permitirema descricao da natureza do problema e nao da solucao; LISA e um compilador de compiladores, ou um

9

Page 10: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 1. INTRODUCAO

load id3mul id4add id2store id1

a = b + c * d

id1 = id2 + id3 * id4

=

id1 +

id2 *

id4id3

tokens

árvore de sintaxe

código gerado

código fonte

Analisador Sintáctico

Analisador Léxico

Gerador de Código

Figura 1.1: Sequencia de compilacao

sistema, que automaticamente gera um compilador/interpretador a partir de uma especificacao de lingua-gem baseada em gramaticas de atributos. A sintaxe e a semantica das especificacoes LISA (gramaticas deatributos numa abordagem orientada ao objecto), assim como algumas extensoes como o uso de templates

e de heranca multipla de gramatica de atributos sao descritos em pormenor em [MLAZ00].

1.2 Ferramentas LEX e YACC

O Lex gera codigo C para o analisador lexico ou scanner. As especificacoes Lex usam padroes parareconhecer as strings do texto de entrada, convertendo-as em tokens. Os tokens sao representacoesnumericas de strings que simplificam o processo de reconhecimento da linguagem.A medida que o Lex encontra identificadores no texto de entrada insere-os na tabela de sımbolos, quecontem informacao sobre o tipo de dados (inteiro, real,...) e sobre o endereco da variavel em memoria.Todas as subsequentes referencias a identificadores indicam o seu ındice nessa tabela.O Yacc gera codigo C para o analisador sintactico ou parser. Nas especificacoes Yacc usa-se regras da

10

Page 11: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

1.2. FERRAMENTAS LEX E YACC

y.tab.h

y.tab.c

(yyparse)

lex.yy.c

(yylex)

fonte

saída

cc

yacc

lex

ficheiro.exe

ficheiro.y

ficheiro.l

Figura 1.2: Construcao de um compilador usando Lex/Yacc

gramatica da linguagem para analisar os tokens gerados pelo Lex e criar uma representacao em arvoreda sintaxe do texto fonte. Essa arvore sintactica impoe uma estrutura hierarquica aos tokens que foramreconhecidos.O gerador de codigo faz uma travessia depth-first na arvore de sintaxe e produz codigo (codigo maquina ouassembly). A figura 1.2 ilustra os ficheiros envolvidos no processo de construcao do compilador (usandoLex e Yacc) indicando os seus nomes e extensoes obrigatorios.Assumindo como objectivo escrever um compilador, sera necessario, em primeiro lugar, especificar todasas regras com padroes lexicos num ficheiro ficheiro.l e as regras gramaticais para o Yacc num ficheiroficheiro.y. Para criar um compilador usamos os seguintes comandos:

lex ficheiro.l # criar lex.yy.c

yacc ficheiro.y # criar y.tab.h e y.tab.c

cc -o ficheiro.exe lex.yy.c y.tab.c # compilar / linkar

O Yacc le as descricoes da gramatica no ficheiro ficheiro.y e gera o parser (funcao yyparse do ficheiroy.tab.c). As declaracoes dos tokens sao incluıdas no ficheiro ficheiro.y e sao convertidas em definicoesde constantes no ficheiro y.tab.h. O Lex le descricoes dos padroes no ficheiro ficheiro.l, inclui-as noficheiro y.tab.h e cria um analisador lexico (funcao yylex do ficheiro lex.yy.c).Por fim, o scanner e o parser sao compilados e linkados para formar o executavel ficheiro.exe. A partirda funcao main, e invocada a funcao yyparse que chama automaticamente o yylex para obter os tokens.

11

Page 12: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 1. INTRODUCAO

12

Page 13: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Capıtulo 2

LEX

2.1 Teoria

A primeira fase de compilacao consiste em ler o texto de entrada e em converter as strings em tokens. Ospadroes do Lex sao especificados usando expressoes regulares e cada padrao tem uma accao associada.O Lex faz o reconhecimento do texto fonte testando cada string e verificando qual o padrao que a aceita.Tipicamente a accao associada a um padrao consiste em devolver um token que representa a string reco-nhecida e que ira ser usada no parser.

2.1.1 Algoritmo de funcionamento

O ficheiro lex.yy.c gerado inclui a funcao yylex() que executa o seguinte algoritmo:

FUNC~AO yylex() : int

REPETIR

yytext <- ‘‘’’ # yytext vai guardar o texto reconhecido

c <- input()

ENQUANTO (c cabe numa ExpRegular)

yytext <- concatenar(yytext,c)

c <- input()

FIMENQ

executar a acc~ao correspondente

ATE chegar ao fim do input

yywrap()

2.1.2 Automatos de Estados Finitos

A especificacao dos padroes e feita recorrendo a expressoes regulares. Considerando a seguinte expressaoregular:

letra(letra|digito)*

Este padrao reconhece strings que comecam por uma letra podendo os restantes caracteres serem zeroou mais letras ou dıgitos. Neste caso, estao envolvidas as operacoes de repeticao (*), de alternativa(|) ea concatenacao.Todas as expressoes regulares podem ser expressas como um automato de estados finitos. Estes automatospodem ser representados usando estados e transicoes entre estes. Ha sempre um estado inicial e um oumais estados finais.Na figura 2.1 o estado 0 e o estado inicial e o estado 2 e o final. A medida que os caracteres sao lidos

e efectuada uma transicao de um estado para o outro. Quando e lida a primeira letra transita-se para o

13

Page 14: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

0 1 2início letra

letra ou digito

outro

Figura 2.1: Automato finito

estado 1, permanece-se no estado 1 enquanto forem lidos mais caracteres ou dıgitos e transita-se para oestado final (2) quando e lido um caracter que nao e letra nem dıgito.Todos os automatos de estados finitos sao faceis de programar. O programa relativo ao automato dafigura 2.1 sera o seguinte:

inicio: goto estado0

estado0: read c

if c = letra goto estado1

goto estado0

estado1: read c

if c = letra goto estado1

if c = digito goto estado1

goto estado2

estado2: string aceite

Esta e a tecnica usada pelo Lex, portanto, as expressoes regulares sao traduzidas para um programa queimita o comportamento de um automato de estados finitos.No entanto, o Lex tem algumas limitacoes: nao consegue reconhecer estruturas aninhadas, por exemplo,o uso de parentesis. O Lex faz o reconhecimento sequencial dos caracteres sem os conseguir relacionarporque nao usa stacks. O Yacc acrescenta ao automato de estados finitos uma stack e, por isso, conseguecontrolar algumas situacoes como o uso de parentesis.

2.2 Pratica

2.2.1 Exemplo de funcionamento

Se quisermos aplicar apenas o analisador lexico a um texto teremos os seguintes passos a dar:

criar um ficheiro .l com a especificac~ao

>lex ficheiro.l (cria o lex.yy.c)

>cc lex.yy.c -ll (cria o a.out)

>a.out < entrada > saida

A opcao -ll e usada quando o ficheiro de especificacao nao invoca ele proprio a funcao yylex().

2.2.2 Divisao de um ficheiro Lex

Cada ficheiro lex esta dividido da seguinte forma:

definic~oes gerais

%%

regras de traduc~ao

14

Page 15: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2.2. PRATICA

%%

rotinas C auxiliares

A seccao de definicoes e composta por macros (associar termos de definicao as expressoes regulares),codigo (deve estar entre “%{“ e “%}”) e declaracoes de estados iniciais.O primeiro %% e sempre preciso porque inicia a seccao de regras. Se se nao especificar nenhuma regra aaccao , por defeito, e copiado tudo da entrada para a saıda. Por defeito, a entrada e sempre stdin e asaıda stdout.Cada regra vai ter a seguinte estrutura:

<ExpRegular> ’’{’’ <Accao> ’’}’’

ExpRegular vai definir uma porcao de texto sobre o qual pretendemos efectuar a Accao.Na seccao de regras as expressoes regulares que definem os padroes, precedem uma accao opcional. Estaaccao pode ser uma instrucao C entre “{“ e “}”. Todo o codigo que nao se encontra na primeira coluna(expressoes regulares) sera copiado tal como esta na entrada para o ficheiro C gerado.No entanto, se nao forem definidas accoes nao havera output, tal como no programa:

%%

. #todo o input e reconhecido

\n

As sequencias de caracteres do texto fonte podem ser emparelhadas por mais do que uma expressaoregular. O analisador lexico adopta o seguinte metodo: primeiro tenta emparelhar a sequencia de carac-teres mais longa e depois entre sequencias do mesmo comprimento escolhe a primeira regra (expressaoregular). Por esse motivo e que as palavras reservadas surgem sempre antes das expressoes regulares maisabrangentes, como por exemplo, as dos identificadores.

2.2.3 Expressoes Regulares

Na tabela 2.1 sao apresentados caracteres especiais usados nas expressoes regulares e na tabela 2.2 constamalguns exemplos de expressoes regulares.

CaracterEspecial

Corresponde a ...

. todos os caracteres excepto newline\n newline* zero ou mais copias da expressao+ uma ou mais copias da expressao? zero ou uma copia da expressaoˆ inıcio da linha (def. de contexto)$ fim da linha (def. de contexto)a/b a mas so se seguido por ba|b a ou b(ab)+ uma ou mais copias de ab (agrupados)“a+b” o literal a+b[ ] classe de caracteres

Tabela 2.1: Primitivas usadas na especificacao de padroes

2.2.4 Gramatica do Lex

TextoLex -> Definic~oes CorpoPrincipal BlocoComplementar;

Definic~oes -> Definic~ao*;

15

Page 16: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

Expressao Textoa. aa, ab, ac, ...abc abcabc* ab, abc, abcc, abccc, ...abc+ abc, abcc, abccc, ...a(bc)+ abc, abcbc, abcbcbc, ...a(bc)? a, abc[abc] a, b, c[+-]? , +, -[a-z] qualquer letra da a a z[a\-z] a, -, z[-az] -, a, z[A-Za-z0-9]+ um ou mais caracteres alfanumericos[ \t\n]+ espacos em branco[ˆab] qualquer coisa excepto a e b[aˆb] a, ˆ, b[a|b] a, |, ba|b a ou ba{5} aaaaaa{3,5} aaa, aaaa, aaaaa

Tabela 2.2: Exemplos de expressoes regulares

CorpoPrincipal -> ‘‘%%’’ Clocal Regra*;

BlocoComplementar -> ‘‘%%’’ CodCauxiliar

|

;

Definic~ao -> id ExpReg

| Def_cond_contexto

| CodigoCglobal

;

Def_cond_contexto ->’’%s’’ id+

;

CodigoCglobal -> CodigoC

;

Clocal -> CodigoC

;

Regra -> ExpReg Acc~ao

;

Acc~ao -> CodigoC

|

;

CodigoC -> ‘‘%{‘‘ codigo ‘‘%}’’

;

ExpReg -> [ContextEsq] [‘‘^’’] expR [‘‘$’’][ContextDir]

;

ContextEsq -> ‘‘<’’ id (‘‘,’’id)* ‘‘>’’

;

ContextDir -> ‘‘/’’ expR

;

CodCauxiliar -> func~oesC_declarac~oes_globais

;

16

Page 17: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2.2. PRATICA

Funcoes evariaveis pre-definidas

Descricao

int yylex(void) funcao que invoca o scanner e retorna to-

kens

int yywrap(void) funcao invocada quando se atinge o fim deficheiro (EOF)

input() le outro caracter do yyin

output(c) coloca c na saıda yyout

unputc(c) volta a colocar o caracter na entradayyless(n) volta a colocar os ultimos n caracteres na

entrada para serem posteriormente lidosyylineno variavel que contem o numero da linha que

esta a ser processadayyleng comprimento do yytext

yylval valor associado ao token

char *yytext texto reconhecido pela expressao regularyymore() a expressao seguinte e concatenada a ex-

pressao correnteFILE *yyout ficheiro de saıda (por defeito, stdout)FILE *yyin ficheiro de entrada (por defeito, stdin)ECHO escreve no output o yytext

(fprintf(yyout,’’%s’’,yytext))INICIAL definicao de estado inicialBEGIN condition mudanca de estado (activa outro estado)REJECT accao de ignorar a expressao regular cor-

rente com a qual foi feito o matching e pro-curar outra expressao regular

Tabela 2.3: Funcoes e variaveis pre-definidas do Lex

2.2.5 Variaveis pre-definidas

A tabela 2.3 apresenta um conjunto de variaveis e macros pre-definidas do Lex. Uma delas e ECHO, permiteimprimir no output o texto reconhecido (yytext) e e definida da seguinte forma:

#define ECHO fwrite(yytext,yyleng,1,yyout)

A funcao yymore() concatena a expressao reconhecida com a expressao reconhecida pela regra seguinte(pode ser a mesma ou outra). Considerando o seguinte exemplo:

%%

mega- ECHO; yymore();

festa ECHO;

Com a entrada mega-festa, o resultado sera mega-mega-festa. A funcao yyless(n) volta a colocar naentrada caracteres ja reconhecidos excepto os n primeiros. Tomando como exemplo:

%%

maria ECHO; yyless(2);

[a-z]+ ECHO;

Criando a entrada maria, a saıda sera mariaria.

17

Page 18: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

2.2.6 Alguns exemplos simples de programas Lex

O primeiro exemplo trata-se de um programa Lex para contar o numero de identificadores de um textode entrada. Por identificador entende-se uma palavra que podera conter uma ou mais letras ou dıgitosmas que comeca sempre por uma letra.

digito [0-9]

letra [A-Za-z]

%{

int contador;

%}

%%

{letra}({letra}|{digito})* contador++;

%%

int main(void){

yylex();

printf(‘‘Numero de identificadores: %d\n’’,contador);

return 0;

}

yywrap() {return 1;}

Nas expressoes regulares quando se usa termos pre-definidos devem ser postos entre “{“ e “}” para osdistinguir dos literais. Num segundo exemplo pretende-se construir um programa Lex que conta o numerode caracteres, o numero de palavras e o numero de linhas de um programa fonte.

%{

int ncar, npal, nlinha;

%}

%%

\n { nlinha++; ncar++;}

[^ \t\n]+ { npal++; ncar += yyleng;}

. { ncar++;}

%%

int main(void){

yylex();

printf(‘‘%d\t%d\t%d\n’’,ncar, npal, nlinha);

return 0;

}

yywrap() {return 1;}

Cada linha e detectada pelo caracter \n e uma palavra sera um conjunto de caracteres diferentes deespacos em branco e tudo o resto sera contabilizado como caracter.Num terceiro exemplo, pretende-se escrever um programa que leia um texto de entrada e o imprimanovamente indicando o numero da linha no inıcio de cada linha, supondo que o ficheiro de entrada eyyin.

%option lex-compat

%%

^(.*)\n printf(‘‘%4d\t%s’’, yylineno, yytext);

%%

int main(int argc,char *argv[]){

yyin=fopen(argv[1],’’r’’);

yylex();

fclose(yyin);

}

yywrap() {return 1;}

18

Page 19: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2.3. CONSTRUCAO DE UM PREPROCESSADOR

Neste ultimo exemplo, cada linha traduz-se na repeticao de zero ou mais vezes de qualquer caracterexcepto \n e termina sempre com esse caracter.

2.3 Construcao de um preprocessador

Um programa Lex pode funcionar como um preprocessador (como foi visto nos exemplos anteriores),seguindo o seguinte algoritmo:

Enquanto n~ao_fim_input

yytext <- getSimbolo()

efectuar acc~ao correspondente ao tipo de sımbolo encontrado

Mais um exemplo de um programa Lex deste tipo sera um preprocessador para uma linguagem tipo LISP,que permita converter todas as invocacoes de funcoes escritas na forma habitual f(x) para a forma (f

x) usada em LISP. Pretende-se ainda que a definicao de conjuntos {elementos} passe a ser representadada seguinte forma:

(makeset elementos)

Assim, o programa ficaria:

ALFANUM ([a-zA-Z0-9])

ID ([a-zA-Z]({ALFANUM})*)

E ([\\,\n\t]*)

%%

‘‘{‘‘ printf(‘‘( makeset ‘‘);

‘‘}’’ printf(‘‘)’’);

‘‘,’’ ;

. |

\n ECHO;

\"(.)*\" ECHO;

{ID}{E}\( {yytext[yyleng-1]=’\0’;

printf(‘‘(%s ‘‘,yytext);}

%%

Assim ao processarmos o seguinte texto:

{1, 2, 3, 4, 5}

f(a, b)

g(f(x, c)) {1 2}

...o resultado sera:

( makeset 1 2 3 4 5 )

( f a b)

( g ( f x c)) ( makeset 1 2 )

2.4 Construcao de um analisador lexico

Para funcionar como analisador lexico de um compilador ( a ser invocado por um parser), cada vez queum sımbolo e reconhecido, e necessario guardar o seu valor (numa variavel global) e retornar o respectivocodigo inteiro; para tal as regras terao o seguinte aspecto:

ExpReg {yylval <- [guardar o valor do sımbolo];

return(codigo);}

19

Page 20: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

onde yylval e uma variavel global usada para a passagem do valor e codigo e uma expressao inteiraque representa o sımbolo da gramatica que foi reconhecido. Como exemplo, e apresentado o seguinteprograma:

%{

#define INTEGER 33

%}

...

[0-9]+ {yylval=atoi(yytext);

return(INTEGER);}

...

Neste programa, quando e detectado um inteiro no texto fonte e devolvido o sımbolo INTEGER e o valore posto em yylval.

2.5 Mais acerca do Lex

Nesta seccao serao apresentados mais alguns assuntos sobre as especificacoes Lex.

2.5.1 Estados iniciais

Os estados iniciais sao usados para obter algum controlo sobre as regras a aplicar em cada situacao.Regras com a mesma label definem um mini-ambiente de reconhecimento que pode ser usado em certaspartes do texto, onde so interessa usar esse conjunto restrito de regras. Usa-se as primitivas BEGIN parasaltar de um ambiente para outro.Por exemplo, pretende-se implementar um semaforo automatico. No inıcio o semaforo esta vermelho edepois entra numa sequencia repetitiva de verde, amarelo e vermelho. O semaforo pode tambem serdesligado ou avariar. A linguagem usada consiste nos seguintes comandos: inicio, muda, avariado efim.A resolucao sem estados iniciais sera:

%{

typedef enum{zero, verde, amarelo, vermelho} estado;

estado sinal=zero;

%}

%%

inicio { printf(‘‘Vermelho\n’’); sinal=vermelho;}

muda { switch(sinal) {

case zero: break;

case verde: printf(‘‘Amarelo\n’’);

sinal=amarelo;

break;

case amarelo: printf(‘‘Vermelho\n’’);

sinal=vermelho;

break;

case vermelho: printf(‘‘Verde\n’’);

sinal=verde;

break;

}

}

avariado sinal=zero;

fim exit();

.|\n ;

Usando estados iniciais a resolucao fica mais simples:

20

Page 21: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2.5. MAIS ACERCA DO LEX

%START V A E

%%

inicio |

<A>muda {printf(‘‘Vermelho\n’’); BEGIN E;}

<E>muda {printf(‘‘Verde\n’’); BEGIN V;}

<V>muda {printf(‘‘Amarelo\n’’); BEGIN A;}

avariado BEGIN 0;

fim exit();

.|\n ;

Um outro exemplo cuja resolucao se torna muito mais simples usando estados iniciais e apresentadode seguida. Pretende-se escrever um programa em Lex que imprima todas as frases do texto fonte queestejam entre aspas e retire essas aspas:

%{

char *yylval;

#include <string.h>

%}

%%

\"[^’’\n]*[‘‘\n] { yylval = strdup(yytext+1);

if(yylval[yyleng-2] != ’’’’)

warning(‘‘string mal terminada’’);

else

yylval[yyleng-2]=0;

printf(‘‘Encontrada ’%s’\n’’,yylval);

}

O programa anterior nao permite que a frase entre aspas ocupe mais do que uma linha (nao pode contaro caracter \n). Se quisermos mudar o programa para que admita os caracteres \n e ‘‘ dentro da fraseentre aspas, a melhor solucao e usar a definicao de estados iniciais (start states). Assim, o programaficaria:

%{

char buf[100];

char *s;

%}

%x STRING

%%

\" {BEGIN STRING; s=buf;}

<STRING>\\n {*s++ = ’\n’;}

<STRING>\\t {*s++ = ’\t’;}

<STRING>\\\" {*s++ = ’\"’;}

<STRING>\" {*s = 0;

BEGIN 0;

printf(‘‘Encontrada ’%s’\n’’,buf);

}

<STRING>\n {printf(‘‘string invalida’’);exit(1);}

<STRING>. {*s++ = *yytext;}

E definido um estado inicial na seccao de definicoes. Quando o scanner detecta umas aspas, a macroBEGIN muda o processo para o estado STRING. O Lex permanece entao no estado STRING reconhecendotodos os padroes que comecam por

<STRING>

21

Page 22: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

ate que se execute um outro BEGIN. Desta forma, e criado um mini-ambiente para fazer a analise lexicade strings. Quando sao detectadas umas aspas volta-se ao estado inicial 0.

2.5.2 Palavras reservadas

Se um programa usa muitas palavras reservadas, e mais eficiente permitir que o Lex as detecte atravesdo seu proprio codigo, ou seja, que as considere como identificadores e em seguida teste se sao ou naopalavras reservadas. Assim, considerando o seguinte extracto de programa:

‘‘if’’ return IF;

‘‘then’’ return THEN;

‘‘else’’ return ELSE;

{letra}({letra}|{digito})* { yylval.id=symLookup(yytext);

return IDENTIFIER;

}

pode-se verificar que reconhece tres palavras reservadas e identificadores. Sera, portanto, mais eficientetestar se a string reconhecida se trata de uma palavra e em seguida testar se e um identificador ou umapalavra reservada (por exemplo, com a ajuda de uma funcao auxiliar). O programa ficaria entao:

{letra}({letra}|{digito})* { int i;

if ((i=resWord(yytext))!=0) return (i);

yylval.id=symLookup(yytext);

return (IDENTIFIER);

}

2.5.3 Debug de um programa Lex

O codigo gerado pelo Lex no ficheiro lex.yy.c inclui instrucoes de debug que estarao disponıveis utili-zando a opcao -d. O output do processo de debug pode ser activado ou desactivado usando a variavelyy flex debug. Este output inclui qual a regra aplicada e o texto que foi reconhecido por essa regra.

extern int yy_flex_debug;

int main(void){

yy_flex_debug=1;

yyparse();

}

2.6 Exercıcios

1. Usando o Lex, construa um filtro de texto que substitua todas as ocorrencias de s/ e qq por sem equalquer respectivamente.

2. Construa um programa Lex que calcule o numero de palavras do texto fonte.

3. Escreva um programa em Lex que reconheca um texto escrito em minusculas e que detecta a palavrareservada integer.

4. Escreva um programa Lex que detecte num texto fonte: as palavras begin e end (indicando quesao palavras reservadas), os identificadores, os operadores(+,-,* e /) e numeros inteiros.

5. Escreva um programa Lex que detecte num texto fonte as palavras reservadas begin e end e iden-tificadores, utilizando expressoes regulares pre-definidas. O reconhecedor deve aceitar minusculas emaiusculas.

22

Page 23: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2.7. EXERCICIOS DE EXAMES DOS ANOS ANTERIORES

6. Construa um programa em Lex que permita contar todas as ocorrencias das palavras aluno e aluna,todas as ocorrencias de aluno e todas as ocorrencias de aluna (aplicacao do reject).

7. Construa um programa Lex que conte o numero de ocorrencias da palavra she e he num determinadotexto de entrada.

8. Construa um programa em Lex que some todos os numeros de um texto e imprima a sua somaquando detectar o caracter + ou =.

9. Considerando que uma palavra e definida da seguinte forma:

palavra=digito* letra (letra + digito + ’-’)*

construa um programa Lex que ignorando comentarios (todas palavras entre “/*” e “*/”) apresentao comprimento de todas as palavras.

10. Construa um programa Lex que apresente todas as palavras e numeros do texto fonte, indicando alinha onde se encontram.

11. Construa um programa Lex que receba um texto de entrada e imprima todas as linhas que comecampelo caracter a.

12. Construa um programa Lex que em todas as linhas comecadas por a substi-tua a palavra ola por* e em todas as linhas comecadas por b, substitua todas as palavras tsf por +.

13. Considere uma linguagem so aceita palavras comecadas pela letra ”a”e com comprimento inferiorou igual a cinco caracteres. Pretende-se construir um programa que detecte todos os erros existentesnum texto escrito nesta linguagem.

14. Construa um programa em Lex que retire os comentarios de um programa em C.

15. Especifique um programa em Lex que sempre que reconheca a string “set number on” comeca asomar todos os numeros inteiros que encontra no texto. Se encontrar a string “set number off” oprograma devera voltar ao seu estado normal, parando de somar. Este comportamento devera seriterado ate que o ficheiro de entrada seja totalmente consumido.

16. Considere um texto com o seguinte formato:

Nome:Maria

Idade:15

Nome:Julia

Idade:18

Construa um programa que imprima os nomes das pessoas com idade superior a 16 anos.

2.7 Exercıcios de exames dos anos anteriores

1. Construa um programa em LEX que permita converter um texto escrito em Portugues num textoescrito em Alemao Debaixo dAgua. Para tal, basta substituir cada vogal por uma determinadastring definida na tabela 2.4.

2. Construa um programa em LEX que permita contar o numero de palavras de um texto que comecampor uma letra maiuscula.

Texto Fonte: Eu estou a fazer o Exame de PL

Resultado: 3

23

Page 24: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

a aitze enderi inixo overu ufux

Tabela 2.4: Correspondencia entre vogais e transformacoes

3. Escreva um programa em Lex que teste se os parenteses de um texto estao emaparelhados, ou seja,se para cada ’(’ existe um ’)’.

4. Suponha que ao fim de cada entrevista um Reporter produz um texto com as perguntas e respostas,distinguindo umas das outras porque as perguntas comecam com ”EU:”no inıcio da linha e asrespostas comecam com ”ELE:”, tambem no inıcio da linha. Nesse contexto, pretende-se desenvolverum programa em Lex para processar os questionarios que:

(a) retire do texto original as tais marcas ”EU:”e ”ELE:”(quer estejam escritas em maiusculas,quer em minusculas), devolvendo todo o resto da entrevista sem qualquer alteracao;

(b) substitua a marca ”EU”pelo nome do entrevistador (Luis) e retire do texto todas as respostas,incluindo a marca ”ELE:”

5. Construa um programa em LEX que implemente um tradutor de pronuncia nortenha, ou seja,deve devolver o texto que recebeu trocando os b’s pelos v’s e vice-versa, se estas consoantes foremseguidas pelas vogais a, e ou o.

Texto Fonte: A vaca da vizinha comeu as botas do Bernardo.

Resultado: A baca da vizinha comeu as votas do Vernardo.

6. Construa um programa em Lex que leia um texto que contem o conteudo de uma directoria (nome,bytes, mes e dia):

exercıcios.doc 234 Jun 28

contas.xls 325 Jul 1

desenhos.fig 0 Jul 1

e produza um texto de saıda com as linhas correspondentes aos ficheiros .xls.

7. Construa um programa em Lex que receba um texto e transforme todas as letras maiusculas emminusculas.

8. Considerando que um documento em XML usa as marcas <section> e </section> nos locais ondedeveria usar <chapter> e </chapter>. Construa um programa em Lex que:

(a) conte o numero de seccoes do documento

(b) efectue a substituicao de <section> e </section> por <chapter> e </chapter> respectiva-mente.

9. Construa um programa em Lex que imprima na saıda todo o texto de entrada numerado de 5 em5 linhas.

10. Construa um programa em Lex que actualize um ficheiro de texto transformando os valores emescudos em valores em euros/centimos (exemplos: 410$00 deve ser substituıdo por 2 euros e 5centimos e 50$00 deve ser substituıdo por 25 centimos).

24

Page 25: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

2.7. EXERCICIOS DE EXAMES DOS ANOS ANTERIORES

11. Considerando que as palavras de um texto podem ser especificadas da seguinte forma: letra (

letra + digito + -) onde digito representa algarismos de 0 a 9 e letra representa maiusculas eminusculas, desenvolva um programa em Lex que determine a maior palavra do texto.

12. Construa um programa em Lex que detecte erros de repeticao de consoantes (Ex: pp, tt) mas quepermita repeticoes de s e r (Ex: rr, ss).

13. Construa um programa em LEX que conte as palavras ”eu” que estao antes da palavra ”tenho” eas palavras ”eu” que estao antes da palavra ”quero”. (Sugestao: use start conditions).

Texto Fonte: Eu tenho que estudar mais porque eu quero passar no exame de PL

Resultado: No de eus antes do tenho: 1

No de eus antes do quero: 1

25

Page 26: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 2. LEX

26

Page 27: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Capıtulo 3

YACC

3.1 Teoria

As gramaticas no Yacc sao descritas usando a notacao BNF (Backus Naur Form). Uma gramatica BNFpode ser usada para expressar linguagens independentes de contexto. Por exemplo:

E -> E + E (r1)

E -> E * E (r2)

E -> id (r3)

Trata-se de uma gramatica com tres producoes que representam uma linguagem para multiplicacao eadicao de numeros. Os termos do lado esquerdo das producoes sao nao-terminais, do lado direito po-derao surgir terminais e nao-terminais. No entanto, o termo id e um nao-terminal e apenas podera surgirno lado direito das producoes.

Exemplo da geracao de uma expressao a partir de uma gramatica:

E-> E * E (r2)

-> E * Z (r3)

-> E + E * Z (r1)

-> E + Y * Z (r3)

-> X + Y * Z (r3)

Em cada passo expande-se um termo, substituindo o lado esquerdo da producao pelo seu lado direito.Mas, para fazer a analise sintactica da expressao x + y * z adopta-se uma abordagem bottom-up oushift-reduce onde se reduz a expressao a um sımbolo nao-terminal.

1. .x+y*z (shift)

2. x.+y*z (reduce r3)

3. E.+y*z (shift)

4. E+.y*z (shift)

5. E+y.*z (reduce r3)

6. E+E.*z (shift)

7. E+E*.z (shift)

8. E+E*z. (reduce r3)

9. E+E*E. (reduce r2)

10. E+E. (reduce r1)

11. E (accept)

Os termos a esquerda do ponto estao na stack enquanto o restante texto de entrada se encontra a direitado ponto. Comeca-se por ir fazendo um shift na expressao pondo os termos na stack, quando os elementos

27

Page 28: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

de topo da stack coincidem com o lado direito da producao substitui-se todos esses elementos na stack

pelo lado esquerdo dessa mesma producao (fazendo pop dos elementos substituıdos e o push do elementosubstituto).Este processo continua ate chegar ao fim do input e estar apenas um sımbolo nao terminal na stack

(sımbolo inicial da gramatica). Considerando contudo o passo 6, pode-se constatar que surge uma situacaode ambiguidade. Em vez de se optar por um shift poderia ter sido feita uma reducao pela regra r1. Istoresultaria numa maior prioridade para a operacao de adicao em relacao a multiplicacao. A isto chama-seconflito shift-reduce e diz-se que a gramatica e ambıgua (quando existem mais do que uma derivacao paraa mesma expressao). Podemos considerar duas solucoes possıveis: reescrever a gramatica (tornando-anao ambıgua) ou usar directivas na especificacao Yacc que indiquem as precedencias dos operadores.Existe, no entanto, outro tipo de conflito: reduce-reduce. Tomando como exemplo a seguinte gramatica:

E -> T (r1)

E -> id (r2)

T -> id (r3)

Quando o sımbolo id se encontrar na stack ha duas reducoes possıveis (por r2 ou por r3). O Yacc temopcoes pre-definidas para estes tipos de conflitos: no caso do shift-reduce, o Yacc faz um shift; no casodo reduce-reduce, usa a primeira regra. No entanto, o Yacc emite uma mensagem de aviso (warning)indicando o conflito.

3.2 Pratica

Nesta seccao serao apresentadas algumas notas praticas sobre especificacoes Yacc.

3.2.1 Divisao de um ficheiro Yacc

Um ficheiro Yacc esta dividido da seguinte forma:

definic~oes

%%

regras

%%

subrotinas

A seccao de definicoes serve para declaracao de tokens e codigo C entre “%{“ e “%}”. A instrucao %token

serve para definir quais os tipos de valor associados aos elementos lexicos, assim como a instrucao %type

e usada para definir os tipos de valores dos sımbolos nao-terminais. Estes tipos de valores sao declaradosusando a instrucao %union e para o Yacc reconhecer esses tipos de valores deve-se incluir o y.tab.h naespecificacao Lex. O Lex encarregar-se-a de incluir no y.tab.h informacao sobre esses tipos de valores.Esta seccao tambem e usada para definir o sımbolo inicial da gramatica usando a instrucao %start. Agramatica BNF e posta na seccao das regras e as funcoes do utilizador na ultima seccao.O Yacc e usado da seguinte forma:

especificac~ao do ficheiro.y

>yacc -dv ficheiro.y

>gcc -o exec y.tab.c -ly

Para que estas instrucoes funcionem e necessario que o ficheiro Yacc inclua o lex.yy.c (porque aqui so ecompilado o y.tab.c). A opcao -ly evita que se inclua a invocacao da funcao yyparse() na especificacaoYacc. A opcao -d indica que ira ser gerado o ficheiro y.tab.h e a opcao -v e usada para gerar o ficheiroy.output que contem informacao sobre a analise sintactica.

28

Page 29: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

3.2. PRATICA

3.2.2 Gramatica do Yacc

textoYacc -> <definic~oes> ‘‘%%’’ <produc~oes> <codigoCaux>

;

<definic~oes> -> <def>*

;

<produc~oes> -> <produc~ao>+

;

<def> -> <defAxioma>

| <defTiposdeValor>

| ‘‘%{‘‘ <codigoCglobal> ‘‘%}’’

| <defTerminais>

| <defAssociatividade>

| <defTipodeValorT_NT>

;

<defAxioma> -> ‘‘%start’’ ID

;

<defTiposdeValor> -> ‘‘%union’’ <unionDef>

;

<defTerminais> -> ‘‘%token’’ <tipo> <T>*

;

<tipo> ->

| ‘‘<’’ ID ‘‘>’’

;

<defAssociatividade> -> ‘‘%left’’ <tipo> <T_NT>*

| ‘‘%right’’ <tipo> <T_NT>*

| ‘‘%noassoc’’ <tipo> <T_NT>*

;

<defTipodeValorT_NT> -> ‘‘%type’’ <tipo> <NT>*

;

<produc~ao> -> <NT> ‘‘:’’ <rhss>

;

<rhss> -> <rhs>

| <rhs> ‘‘|’’ <rhss>

;

<rhs> -> <simb>*

| <simb>* <prec>

;

<simb> -> <T>

| <NT>

| <simbSemantico>

;

<T> -> ID_token

| ‘‘’’’ char ‘‘’’’

;

<NT> -> ID

;

<simbSemantico> -> ‘‘{‘‘ <codigoCcom$> ‘‘}’’

;

<prec> -> ‘‘%prec’’ <T>

;

<codigoCaux> -> ‘‘%%’’ <func~oesC>

|

29

Page 30: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

;

3.2.3 Ligacao entre o Lex e Yacc

A ligacao entre o Lex e o Yacc e feita definindo os tokens na area de definicoes e chamando o yylex

permite-lhe obter os tokens devolvidos pelo Lex. Os valores associados aos tokens sao devolvidos atravesda variavel yylval.Considerando novamente o exemplo do calculador de multiplicacoes e adicoes, o ficheiro Lex seria:

%{

#include ‘‘y.tab.h’’

%}

%%

‘‘program’’ return(programa);

[0-9]+ { yylval=atoi(yytext);

return INTEGER; #e devolvido o token reconhecido

}

[-+\n] return *yytext;

[ \t] ;

. yyerror(‘‘caracter invalido’’);

%%

int yywrap(void){

return 1;

}

Internamente, o Yacc mantem duas stacks em memoria: stack de parsing e stack de valores. A primeiracontem terminais e nao-terminais e representa o estado actual do processo de parsing. A stack de va-lores e um array de valores dos sımbolos da outra stack. Por exemplo, se o token INTEGER estiver nastack de parsing, o seu valor yylval estara na stack de valores. As duas stacks estao sempre sincronizadas.

%start program

%token programa

%token INTEGER

%%

program : programa expr ’\n’ {printf(‘‘%d\n’’,$2);}

|

;

expr : INTEGER {$$ = $1;}

| expr ’+’ expr {$$ = $1 + $3;}

| expr ’-’ expr {$$ = $1 - $3;}

;

%%

#include <stdio.h>

#include ‘‘lex.yy.c’’

int yyerror(char *s){

fprintf(stderr, ‘‘%s\n’’,s);

return 0;

}

int main(void){

yyparse();

return 0;

}

30

Page 31: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

3.2. PRATICA

Na gramatica BNF o caracter “:” separa o lado esquerdo da producao do lado direito da mesma. Quandoexistem diferentes producoes para o mesmo sımbolo nao terminal pode-se usar “|” para separar todos oslados direitos desse sımbolo. Cada producao termina com “;”. As accoes associadas a cada producaoencontram-se entre “{“ e “}”.Considerando a seguinte producao:

expr: expr ’+’ expr {$$ = $1 + $3;}

Quando esta regra e aplicada o lado direito da producao, na stack de parsing, e substituıdo pelo ladoesquerdo dessa producao. Significa isto que e feito o pop de expr ’+’ expr e o push de expr. Houveuma reducao na stack.Para referir as posicoes na stack de valores usa-se $1 para o primeiro termo do lado direito, $2 para osegundo e assim sucessivamente. $$ representa o topo da stack de valores depois de ter sido feita umareducao. E feito o pop de $1 e $3 e e feito o push de $$. E assim as duas stacks permanecem sincronizadas.Em seguida, a regra a aplicar sera:

expr: INTEGER {$$ = $1;}

O token INTEGER e substituıdo por expr na stack de parsing. Na stack de valores, o valor do inteiro eretirado e e posto novamente. Quando surge um \n, o valor associado ao sımbolo inicial da gramatica(expr) e imprimido. No caso de haver erros, o Yacc invoca a funcao yyerror, e a ultima funcao e sempreo main.Seguindo o mesmo exemplo, considere que se pretende incluir mais algumas funcionalidades: o operadorde subtraccao e de divisao; o uso de parentesis para contrariar a prioridade dos operadores; uso de iden-tificadores de variaveis e a operacao de atribuicao.O analisador lexico retorna os tokens VARIABLE e INTEGER. Para as variaveis, yylval especifica um ındiceda tabela de sımbolos (sym). Quando o token INTEGER e devolvido, yylval contem o numero reconhecidodo texto fonte.

%{

#include ‘‘y.tab.h’’

%}

%%

[a-z] { yylval = *yytext - ’a’;

return VARIABLE;

}

[0-9]+ { yylval=atoi(yytext);

return INTEGER;

}

[-+()=/*\n] { return *yytext;}

[ \t] ;

. yyerror(‘‘caracter invalido’’);

%%

int yywrap(void){

return 1;

}

Na especificacao Yacc sao definidos os tokens INTEGER e VARIABLE e sao definidos os operadores aritmeticos.Usa-se a primitiva %left para operadores associativos a esquerda e %right para operadores associati-vos a direita. A ultima definicao e a que tem maior precedencia. Assim, a multiplicacao e divisao temprioridade sobre a adicao e a subtraccao. Usando esta tecnica elimina-se a ambiguidade da gramatica.

%token INTEGER VARIABLE

%left ’+’ ’-’

%left ’*’ ’/’

31

Page 32: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

%{

int sym[26];

%}

%%

program : program statement ’\n’

|

;

statement : expr {printf(‘‘%d\n’’,$1);}

| VARIABLE ’=’ expr {sym[$1] = $3;}

;

expr : INTEGER

| VARIABLE {$$ = sym[$1];}

| expr ’+’ expr {$$ = $1 + $3;}

| expr ’-’ expr {$$ = $1 - $3;}

| expr ’*’ expr {$$ = $1 * $3;}

| expr ’/’ expr {$$ = $1 / $3;}

| ’(’ expr ’)’ {$$ = $2;}

;

%%

#include <stdio.h>

#include ‘‘lex.yy.c’’

int yyerror(char *s){

fprintf(stderr, ‘‘%s\n’’,s);

return 0;

}

int main(void){

yyparse();

return 0;

}

Por omissao, yylval e um inteiro. Pode surgir a necessidade de retornar para o Yacc mais do que umvalor e de tipos diferentes. Nesse caso a variavel yylval e uma estrutura com tantos campos quantos osvalores que vao ser retornados. Considerando que se pretende retornar uma string e um inteiro deve-sedeclarar:

%union{

char str[20];

int num;

}

antes da declaracao dos tokens na especificacao Yacc. No Lex estes campos sao preenchidos acedendo avariavel com yylval.str e yylval.num.Para compilar e linkar o ficheiro Lex e o ficheiro Yacc de cada exercıcio, sugere-se o uso da seguinteMakefile:

SUF=dummy

$(SUF): lex.yy.o y.tab.o

cc -o $(SUF) lex.yy.o y.tab.o -lfl

lex.yy.o: lex.yy.c y.tab.h

cc -c lex.yy.c

lex.yy.c: §(SUF).lflex $(SUF).l

32

Page 33: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

3.3. MAIS ACERCA DO YACC

y.tab.o: y.tab.c

cc -c y.tab.c

y.tab.c y.tab.h: $(SUF).y

yacc -d $(SUF).y

clean:

rm *.o

3.3 Mais acerca do Yacc

3.3.1 Recursividade

Quando se especifica uma lista deve ser usada recursividade a esquerda, da seguinte forma:

lista : item

| lista ’,’ item

;

... ou recursividade a direita:

lista : item

| item ’,’ lista

;

Se e usada recursividade a direita, todos os itens da lista sao postos na stack e depois sao feitas as reducoesnecessarias. Com recursividade a esquerda nao havera mais do que tres termos na stack (no caso destagramatica) porque se reduz logo que e possıvel reduzir. Por essa razao tem mais vantagens o uso darecursividade a esquerda.

3.3.2 Ambiguidade IF ELSE

O conflito shift-reduce ocorre frequentemente nas estruturas if-else. Por exemplo, considerando as seguin-tes producoes:

expr : IF expr stmt

| IF expr stmt ELSE stmt

...

e a seguinte frase:

IF expr stmt IF expr stmt ELSE stmt

existem duas derivacoes possıveis: fazer shift para o ELSE ou reduzir os termos IF expr stmt que estaono topo da stack. Se se optar pela reducao, o ELSE ficara associado ao primeiro IF e nao ao que estaimediatamente antes como e o pretendido. No caso do Yacc nao haveria problemas porque este optasempre pelo shift.No entanto, existe uma forma de garantir que uma instrucao do tipo IF:ELSE tenha maior precedenciado que uma instrucao IF:

%nonassoc IFX

%nonassoc ELSE

expr : IF expr stmt %prec IFX

| IF expr stmt ELSE stmt

;

33

Page 34: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

3.3.3 Mensagens de erro

Para tornar as mensagens de erro mais elucidativas poderao ser usadas funcoes como:

void yyerror(char *s){

fprintf(stderr,’’linha %d: %s \n’’,yylineno,s);

}

Quando o Yacc descobre um erro de parsing, a accao por defeito e yyerror e depois retorna do yylex como valor 1 e o processo termina. Uma outra alternativa interessante e usar o token error que permitirareconhecer todo e qualquer input ate que surja o caracter que se encontra a seguir a ele. Assim, quandofor detectado um erro e ignorado e a analise sintactica continua para o restante texto ( a partir de umcaracter previamente estipulado na gramatica).

stmt : ’;’

| expr ’;’

| PRINT expr ’;’

| VARIABLE ’=’ expr ’;’

| WHILE ’(’ expr ’)’ stmt

| IF ’(’ expr ’)’ stmt %prec IFX

| IF ’(’ expr ’)’ stmt ELSE stmt

| ’{’ stmt_list ’}’

| error ’;’

| error ’}’

;

3.3.4 Atributos herdados

Nos exemplos apresentados apenas surgiram ate agora atributos sintetizados, por exemplo:

expr : expr ’+’ expr {$$ = $1 + $3;}

Um atributo sintetizado e calculado com base nos atributos dos nodos filhos. Ao fazer o parsing numprocesso bottom-up os valores $1 e $3 sao conhecidos e e calculado o atributo do sımbolo do lado esquerdoda producao. O atributo herdado de um nodo, depende dos atributos do nodo pai, ou seja, dos atributosdo sımbolo do lado esquerdo da producao.

decl : type varlist

type : INT | FLOAT

varlist: VAR {setType($1,$0);}

| varlist ’,’ VAR {setType($3,$0);}

$0 referencia o atributo do sımbolo varlist.

3.3.5 Accoes intermedias

list : item1 {do_item1($1);} item2 {do_item2($3);} item3

quando uma accao esta associada ao reconhecimento apenas de parte do lado direito da producao, podeser definida nesse ponto. E de notar, no entanto, que a accao ocupa tambem um slot na stack e, por isso,quando nos referimos ao valor do item2 temos que utilizar o $3.

34

Page 35: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

3.4. EXERCICIOS

3.3.6 Debug de um programa Yacc

Para activar facilidades de debug no Yacc basta declarar a variavel YYDEBUG e atribuir-lhe um valordiferente de zero. Isto tambem pode ser feito usando a opcao -t. O output contera os tokens que foramreconhecidos e as accoes de shift-reduce.

%{

#define YYDEBUG 1

%}

...

%%

int main(void){

#if YYDEBUG yydebug=1;

#endif

yyparse();

}

3.4 Exercıcios

1. Considere um texto que pretende representar um conjunto de alunos da seguinte forma:

joao 1233 (15,14,16,10)

teresa 1478 (12,11,17,12)

Para cada aluno consta o seu nome, o seu numero de identificacao e uma sequencia de notas. Oprograma devera reconhecer este texto e devera:

(a) calcular o numero total de alunos;

(b) indicar para cada aluno o seu nome e a media das notas;

(c) calcular a melhor media.

2. Considere uma linguagem de descricao de maquinas de estados:

ROLDANA

parada e1 (x>3) = andar

andar e2 (x<3) = parada;

BOTAO

activo e2 (a<5) = desactivo;

Esta linguagem permite a descricao de varias maquinas, indicando para cada uma delas o nomee um conjunto de transicoes de estado. Cada transicao de estado e caracterizada por um estadoinicial, por um evento que deve ocorrer para que a transicao seja efectuada (opcional), por umacondicao e por um estado final.Pretende-se construir um tradutor que reconheca um texto fonte com estas caracterısticas e produzaum texto final com o seguinte formato:

ROLDANA(){

if ( estado==parada && e1 && x>3) {estado=andar;}

if ( estado==andar && e2 && x<3) {estado=parada;}

}

BOTAO(){

if ( estado==activo && e2 && a<5) {estado=desactivo;}

}

35

Page 36: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

3. Altere o programa anterior de forma a que para cada maquina surja apenas o seu conjunto deestados:

Nome: ROLDANA

Estados: parada, andar

Nome: BOTAO

Estados: activo, desactivo

a) Implemente este exercıcio sem recorrer a nenhuma estrutura auxiliar.

b) Implemente este exercıcio recorrendo a uma lista ligada simples para coleccionar os estados.

4. Construa um programa LEX/YACC que implemente uma calculadora. Alguns exemplos de textofonte e texto final sao apresentados na tabela abaixo. Considere que sao apenas possıveis operacoes

Inicial Final(* 2 (+ 4 5)) 18(* (+ 1 2 3) 4 5) 120

de soma e multiplicacao, que o numero de operandos pode tomar qualquer valor acima de dois esao do tipo inteiro.

5. Construa um interpretador usando LEX/YACC que receba como texto fonte:

GRAFO mapa

Braga - Guimaraes - Felgueiras - Amarante - Vila Real;

Porto - Penafiel - Amarante - Vila Real

E que liste o caminho mais longo (considerando que o caminho mais longo e aquele que inclui maisparagens). No exemplo apresentado, o resultado do interpretador sera:

O caminho mais longo: Braga, Guimar~aes, Felgueiras, Amarante, Vila Real

6. Pretende-se construir um reconhecedor de uma linguagem de descricao de desenhos que permitaguardar toda essa informacao numa estrutura para mais tarde se proceder ao seu desenho. O textofonte tera que ter o seguinte formato:

janela: Q 20 * 20

porta: R 40 * 20

sol: C 100 * 100

Q (quadrado); R (rectangulo); C (cırculo)

7. Construa um calculador de expressoes usando programas LEX/YACC para reconhecer as expressoesde entrada. Os operadores disponıveis serao: % (percentagem); +,-,*,/ , permitindo o uso deparentesis para forcar prioridades; a expressao devera finalizar com “.” e os operandos devem serdo tipo inteiro.

8. Considere uma linguagem que permite definir as posicoes de segmentos de recta e de pedacos detexto. Cada segmento de recta e definido pelas coordenadas do ponto inicial, pelo declive e pelocomprimento. Cada texto e um conjunto de caracteres entre aspas que poderao ocupar mais do queuma linha. Para cada texto sao tambem indicadas as coordenadas da posicao inicial.Pretende-se construir um reconhecedor para esta linguagem e um tradutor que imprima na saıdaas coordenadas iniciais e finais de cada segmento de recta, assim como, as coordenadas iniciais dostextos. As coordenadas finais de um segmento sao calculadas da seguinte forma:

36

Page 37: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

3.5. EXERCICIOS DE EXAMES DOS ANOS ANTERIORES

xf = xi + comprimento * cos(declive)

yf = yi + comprimento * sin(declive)

Nota: As unidades do comprimento poderao ser em centımetros ou polegadas (polegada=3,5cm).Exemplo de um texto fonte:

LINHA (3,5) (0.5) (20 cm);

TEXTO (10,15) ‘‘Ola’’;

LINHA (10,20) (1.7) (10 inch);

Texto de saıda:

Recta [(3.00,5.00),(20.55,14.59)]

O texto ‘‘Ola’’ comeca na posic~ao (10.00,15.00)

Recta [(10.00,20.00),(5.49,54.71)]

3.5 Exercıcios de exames dos anos anteriores

1. Construa um programa em LEX/YACC que receba uma lista telefonica do IPB, onde consta onome, extensao telefonica, departamento, gabinete e email de todos os docentes da instituicao.Sabendo que a lista telefonica do instituto esta dividida por escolas, considere o seguinte exemplode texto de entrada:

Estig

Luisa, 3380, Matematica,34,[email protected];

Jorge, 3456, Informatica,45,[email protected]

Ese

Ana, 2332, Musica, 87, [email protected]

O programa deve produzir como saıda algumas informacoes, tais como:

(a) Nome e a extensao dos docentes da ”Estig”.

(b) Numero de docentes do departamento de ”Musica” da ”Ese”

2. Pretende-se implementar em LEX/YACC um programa que, dada uma frase constituıda por umalista de palavras e numeros, determine quantas palavras existem antes da palavra ”agora”. Consi-dere o seguinte exemplo:

Texto Fonte: LISTA 3 ou 4 tentativas permitem contar as palavras antes da

palavra agora para depois chegarmos ao resultado final.

Resultado: No de palavras = 9

3. Pretende-se implementar um interpretador em LEX/YACC que receba um texto fonte com a des-cricao dos jogos da 1a fase do Campeonato Mundial de Futebol. O campeonato esta dividido emvarios grupos e que em cada grupo sao disputados 6 jogos. Para cada jogo deve constar a data,local e as duas equipas envolvidas. Considere o seguinte exemplo de texto fonte:

CAMPEONATO

GRUPO A

JOGO 23/7/2004 Braga Portugal Brasil

JOGO 26/7/2004 Porto Brasil Argentina

GRUPO B

JOGO 15/7/2004 Braga Grecia Espanha

37

Page 38: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

O interpretador ao receber o texto com toda esta informacao, deve produzir os resultados dasseguintes pesquisas:

(a) Data e local dos jogos onde ”Portugal” entrou.

(b) Jogos do grupo ”A”.

4. Considere um texto onde, para cada palavra, e indicado um conjunto de sinonimos. Por exemplo:

Palavra: roer

Sinonimos: ruminar, trincar, mastigar

Palavra: rir

Sinonimos: sorrir

Construa um reconhecedor / tradutor que receba um texto deste tipo e indique:

(a) o numero total de palavras definidas no dicionario.

(b) todos os sinonimos das palavras comecadas por ’r’.

5. Defina uma linguagem que represente a informacao sobre os ficheiros contidos numa directoria(nome, bytes, mes e dia), de acordo com o seguinte exemplo:

exercıcios.doc 234 Jun 28

contas.xls 325 Jul 1

desenhos.fig 0 Jul 1

e construa um interpretador que indique:

(a) todos os ficheiros com zero bytes.

(b) numero de ficheiros com extensao .xls ou .fig.

6. Construa um interpretador usando LEX/YACC que receba como texto fonte declaracao de cons-tantes em Pascal:

CONST a=100;

b=200;

e que:

(a) calcule a soma de todas as constantes declaradas.

(b) crie uma estrutura (uma lista ligada) que contenha os nomes de todas as constantes declaradas.

7. Construa um interpretador usando LEX/YACC que receba como texto fonte referencias bibli-ograficas:

J. Andrade, A. Pereira, G. Jardim. Apontamentos sobre Java. Universidade do Oeste, 1997.

H. Coelho, R. Ramalho. Processamento de Linguagens. Universidade do Interior,1998.

E que:

(a) liste todas as instituicoes envolvidas nas referencias

(b) conte o numero de autores de cada artigo.

(c) crie um ficheiro de referencias (.bib) para ser usado no Latex. O texto de entrada apresentadodeve entao ser convertido para o formato do texto seguinte e guardado num ficheiro comextensao .bib:

38

Page 39: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

3.5. EXERCICIOS DE EXAMES DOS ANOS ANTERIORES

@book{J97 ,

author = " J. Andrade, A. Pereira, G. Jardim",

title = " Apontamentos sobre Java",

year = 1997,

publisher = " Universidade do Oeste"

}

@book{S97,

author = " H. Coelho, R. Ramalho",

title = " Processamento de Linguagens",

year = 1998,

publisher= " Universidade do Interior",

}

Tenha em atencao que as chaves J97 e S97 sao criadas com base no primeiro caracter dosautores e nos dois ultimos algarismos do ano.

8. Um determinado horto da cidade de Braganca faz propostas de fornecimento de plantas (arvores earbustos) para construir, ou reconstruir, jardins exteriores, publicos ou particulares. Nesse contextopretende-se definir uma linguagem para descrever as propostas de um determinado dia (identificadoinicialmente), indicando a sigla de cada planta sugerida e a respectiva quantidade, de modo acalcular o respectivo orcamento (custo total dessas plantas, acrescido de um lucro de 30%). Nadescricao de cada proposta indica-se, a cabeca, o respectivo numero de serie e o nome do destinatario.Para se poder fazer o calculo, cada texto (com as proposta de jardins do dia referido) comeca coma listagem das plantas existentes, indicando para cada uma, alem da sigla, o nome por extenso, opreco unitario e a quantidade em stock. O que se pede nesta questao e que :

(a) desenhe a Gramatica Independente de Contexto que especifica a sintaxe da linguagem preten-dida.

(b) associe a gramatica as accoes semanticas necessarias para que seja possıvel calcular o orcamentode cada proposta.

Nota: Considere o uso de uma lista ligada para guardar o preco de cada planta:

typedef struct c{

char * sigla;

float preco;

struct c *next;} planta;

planta horto;

Considere tambem que ja foram definidas as seguintes funcoes:

planta insere_lista (char * ,float ,planta);

/* insere siglas e precos na lista ligada */

float consulta(char *, planta);

/*consulta a lista ligada e para uma dada sigla devolve o respectivo preco.*/

9. De modo a facilitar o trabalho de uma equipa de historiadores que esta a levantar informacao,nos varios arquivos do Paıs, sobre individualidades do Clero Catedralıcio portugues, pretende-sedefinir uma linguagem que permita processar automaticamente (no sentido de validar, normalizar ecriar uma base de dados) as notas extraıdas de cada documento consultado. Para isso sera precisodescrever um ou mais documentos consultados. Cada documento tem um Identificador, a data deredaccao, o redactor, o tipo de documento (certidao, registo de compra ou de venda, testamento,doacao, etc.), a data de leitura e a descricao do evento, ou facto, a que diz respeito. Alem dessainformacao de base, a cada documento estara associada uma lista de clerigos. Sobre cada clerigo,referido no documento em causa, regista-se o nome proprio, o apelido de famılia e a alcunha, a

39

Page 40: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

CAPITULO 3. YACC

diocese onde ele exercia, a categoria eclesiastica (arcebispo, bispo, conego, presbıtero, chantre) e opapel que ele desempenhou no evento, ou facto, narrado. O que se pede nesta questao e que:

(a) desenhe a Gramatica Independente de Contexto que especifica a sintaxe da linguagem preten-dida.

(b) calcule o numero de documentos onde sao referidos bispos ou arcebispos.

10. Considere a seguinte situacao:Para facil acesso por todos atraves da internet, pretende-se produzir, automaticamente, um di-cionario em html, com a classificacao gramatical de cada palavra, origem (quando conhecida),significados e (para cada caso semantico) sinonimos e exemplos de utilizacao.Para o efeito deve ser:

a) definida uma linguagem que permita declarar cada palavra, descrevendo toda a informacaoconhecida (relatada no paragrafo acima) e disponıvel sobre ela;

b) desenvolvido um processador para essa linguagem que, apos ler e validar as declaracoes referidas,faca o seu reconhecimento e gere uma pagina html para cada palavra definida, bem como umapagina inicial com o ındice (por ordem alfabetica) de todas as palavras introduzidas (ligandocada uma a respectiva pagina).

O gerador das paginas html correspondentes ao ındice e a cada palavra, tera de dotar cada paginacom os botoes de navegacao (realizados na forma de links) necessarios para avancar para a palavraseguinte ou anterior e saltar para a pagina inicial, bem como saltar para as palavras indicadas comosinonimos (caso tambem estejam definidas no dicionario) . Alem disso, deve validar que o dicionariotenha pelo menos uma palavra e que nao hajam repeticoes de definicoes da mesma palavra.

40

Page 41: Notas Pr´aticas e Exerc´ıcios para apoio `a …mjoao/plingaluno06.pdfprogramar em C e compreendem estruturas de dados como listas ligadas e arvores. At´e 1975, construir um compilador

Bibliografia

[ABH91] Jose Joao Almeida, Jose Bernardo Barros, and Pedro Rangel Henriques. Lex. Technicalreport, Universidade do Minho, 1991.

[AF91] Jose Joao Almeida and Fernando Jorge Ferreira. Yacc. Technical report, Universidade doMinho, 1991.

[ASU86] Alfred V. Aho, Ravi Sethi, and Jeffrey D. Ullman. Compilers - Principles, Techniques and

Tools. Addison-Wesley, 1986.

[Bis93] Kurt M. Bischoff. Ox - an ag compiling system based on lex, yacc and c: Toturial information.Technical report, Iowa State University, November 1993.

[GHK90] R. Gray, V. Heuring, and S. Kram. Eli:a complete, flexible compiler construction system.Technical report, Univ. Colorado, Boulder, 1990.

[Hen92] Pedro Henriques. Atributos e Modularidade na Especificacao de Linguagens Formais. PhDthesis, Universidade do Minho, 1992.

[Joh75] Stephen C. Johnson. Yacc:yet another compiler compiler. Computing Science 32, Bell Labo-ratories, New Jersey, 1975.

[MLAZ00] Marjan Mernik, Mitja Lenic, Enis Avdicausevic, and Viljem Zumer. Compiler/interpretergenerator system lisa. In IEEE Proceedings of 33rd Hawaii International Conference on System

Sciences, 2000.

[Nie] Thomas Niemann. A guide to lex & yacc. Portland, Oregon.

[PDC93] T. J. Parr, H. G. Dietz, and W. E. Cohen. Advanced tutorial pccts. Technical report, Schoolof Electrical Engineering, Purdue University, 1993.

[RT89] Thomas Reps and Tim Teitelbaum. The Synthesizer Generator: A System for Constructing

Language-based Editors. Springer-Verlag, 1989.

[SL75] E. Schmidt and M. E. Lesk. Lex - a lexical analyser generator. Computing Science 39, BellLaboratories, New Jersey, 1975.

41