• Nenhum resultado encontrado

Compiladores. Lex e Yacc / Flex e Bison. Ferramentas Flex/Bison

N/A
N/A
Protected

Academic year: 2021

Share "Compiladores. Lex e Yacc / Flex e Bison. Ferramentas Flex/Bison"

Copied!
13
0
0

Texto

(1)

Compiladores

Ferramentas Flex/Bison

Prof. Sergio F. Ribeiro

Lex e Yacc / Flex e Bison

 São ferramentas de auxílio na escrita de programas

que promovem transformações sobre entradas estruturadas.

 São ferramentas desenvolvidas para programadores

de compiladores e interpretadores.

 Permitem um rápido desenvolvimento de

protótipos e uma manutenção simples do software.

 Tanto o Lex como o Yacc foram desenvolvidos nos

(2)

Compiladores

Lex e Yacc / Flex e Bison

 Papel do Lex: toma um conjunto de expressões

regulares e produz uma rotina C que irá executar a análise léxica identificando os tokens.

 Papel do Yacc: toma uma descrição concisa de uma

gramática e produz uma rotina C que irá executar a análise sintática ou parsing.

3

Gerador de Analisador Sintático

 É uma ferramenta similar e complementar ao

gerador de analisador léxico.

Ferramentas mais comuns: yacc (yet another

compiler-compiler) ou bison.

Lex gera a função yylex() que retorna o

identificador de um item léxico reconhecido.

Yacc gera a função yyparse() que analisa os itens

léxicos e decide se eles formam ou não uma sentença válida.

(3)

Compiladores

Gerador de Analisador Sintático

 Criando um tradutor de entrada/saída com Yacc:

Compilador Yacc Compilador C a.out Especificação Yacc translate.y y.tab.c entrada y.tab.c a.out saída 5 Compiladores

Formato Geral do Programa Yacc

 Constituído de três seções:

definições (declaração de nomes e tipos de tokens, de variáveis, etc.)

%%

regras de tradução (contém as produções da gramática) símbolo : derivações {ações semânticas}

%%

rotinas do usuário (contém o main(l) e outras rotinas de suporte em C)

(4)

Compiladores

Especificação Bison

 Uma especificação bison descreve uma gramática

livre do contexto que pode ser usada para gerar um parser.

 Ela possui elementos membros de 4 classes:

 Elementos léxicos ou tokens, que é o conjunto de símbolos

terminais;

 Elementos sintáticos, que são símbolos não-terminais.  Regras de produção, que definem símbolos não-terminais

em termos de sequência de terminais e não-terminais;

 Uma regra start, que reduz todos os elementos da

gramática para uma regra.

7

Especificação Bison

 A cada regra está associado um símbolo não-terminal

(lado esquerdo).

 As definições (lado direito) consistem de zero ou

mais símbolos terminais (tokens ou caracteres literais) ou não-terminais.

 Tokens são símbolos terminais reconhecidos pelo

analisador léxico, apenas no lado direito das regras.

 A cada regra pode ser associada uma ação em C.

Estas ações ficam entre chaves ( { } ) e ditam o que deve ser feito pra cada produção reconhecida.

(5)

Compiladores

Especificação Bison

 Os nomes de símbolos podem ter qualquer tamanho,

consistindo de letras, ponto, sublinhado e números (exceto na primeira posição).

 Os nomes de não-terminais são usualmente

especificados em minúsculos.

 Os terminais ou tokens, em maiúsculos.

 O bison transforma esta descrição da gramática, e

ações associadas, em um parser (programa capaz de analisar uma sequência de tokens de entrada, detectar produções e agir sobre elas).

9

Especificação Bison

 Na seção de declarações (1ª seção):

 Códigos em C entre %{ e %} (como no flex).  Definição de tokens: %token T1

 Definição de regras auxiliares para a solução de

ambiguidades, como por exemplo: %left MAIS MENOS

%left VEZES DIVIDIR %left MENOS_UNARIO

(6)

Compiladores

Especificação Bison

 Na seção de regras de produção (2ª seção):

uma gramática definida assim:

lado_esquerdo  alt1 | alt2 |...| altN

transforma-se na seguinte especificação yacc

Lado_esquerdo : alt1 {/*ação 1*/} | alt2 {/*ação 2*/} ... | altN {/*ação N*/} ; 11

Especificação Bison

 Na seção de regras de produção (2ª seção):

 Cada símbolo (terminal ou não) tem associado a ele uma

pseudo variável;

 O símbolo do lado esquerdo tem associada a ele a

pseudo variável $$;

 Cada símbolo i da direita tem associada a ele a variável $i;  $i contém o valor do token (retornado por yylex()) se o

símbolo i for terminal, caso contrário contém o valor do $$ do não terminal;

(7)

Compiladores

Usando o Bison

 São 4 passos para criar um parser:

 Escrever uma especificação de uma gramática no formato

do bison. O arquivo terá a extensão .y.

 Escrever uma especificação de um analisador léxico que

pode produzir tokens; extensão .l.

Executar o bison sobre a especificação .y e o flex sobre a

especificação .l.

 Compilar e linkar os códigos fontes do parser, do

analisador léxico e suas rotinas auxiliares.

13

Usando o Bison

A saída do bison, yy.tab.c, contém a rotina yyparse

que chama a rotina yylex para obter tokens.

 Como o Lex, o Bison não gera programas completos.

A yyparse deve ser chamada a partir do main.

 A rotina léxica lê a entrada, e a cada token

encontrado, retorna o número do token ao parser.

 A rotina léxica pode também passar o valor do token

usando a variável externa yylval (entre outras).

 Um programa completo também requer uma rotina

(8)

Fluxo de Controle de um Tradutor

main yyparse( ) yylex( ) yylval input Entrada avaliada Valor da ação do processo Requerer próximo token Retornar o token ou 0 se EOF Valor passado do token Ler chars da entrada Retorna 0 se entrada é valida 1 se não 15

Tradutor com Flex/Bison

 Veremos agora um exemplo de implementação de

um analisador léxico e sintático usando as ferramentas Flex e Bison, respectivamente.

 No programa bison, será acrescentado regras

semânticas de forma a termos no final a implementação de um tradutor.

 O objetivo é implementar um tradutor que calcule e

traduza expressões aritméticas da forma infixa para a forma posfixa.

(9)

Gramática

cmd  ID = expr ; expr  expr + termo

| expr – termo | termo

termo  termo * fator | termo / fator | fator fator  ( expr ) | NUM | ID Compiladores 17

Esquema de Tradução

cmd  ID{imprimir ID.atr} = expr ; {imprimir(′=′)} expr  expr + termo {imprimir(′+′)}

| expr – termo {imprimir(′–′)} | termo

termo  termo * fator {imprimir(′*′)} | termo / fator {imprimir(′/′)} | fator

fator  ( expr )

(10)

Ferramentas

 As ferramentas Flex e Bison são projetos GNU

obtidas no site:

https://sourceforge.net/projects/gnuwin32/files/flex/2.5.4a-1/flex-2.5.4a-1.exe/download

http://downloads.sourceforge.net/gnuwin32/bison-2.4.1-setup.exe

 As ferramentas rodam em linha de comando no DOS.

 Os arquivos .lex e .y devem estar na pasta bin para

serem reconhecidos pelas ferramentas.

Compiladores 19

Compilação

 Na linha de prompt, deve-se entrar com os seguintes

comandos:

flex arquivo1.lex bison –d arquivo2.y

Deve-se abrir o arquivo2.tab.c no DevC++ e compilar

para gerar o executável arquivo2.tab.exe

 Este executável é o analisador/tradutor desejado.

 Depois de executado, entra-se com uma expressão

infixa e o tradutor devolve a expressão posfixa correspondente e o valor resultante.

obs:o parâmetro d é usado para se gerar arquivo .h

(11)

Programa .lex – Analisador Léxico

%{

#include "ypos.tab.h" #include <stdlib.h> extern int yylval; %}

digito [0-9]

letra [a-zA-Z]

%%

"+" {yylval = yytext[0]; return MAIS;}

"-" {yylval = yytext[0]; return MENOS;}

"*" {yylval = yytext[0]; return MULT;}

"/" {yylval = yytext[0]; return DIV;}

Compiladores 21

Programa .lex – Analisador Léxico

"=" {yylval = yytext[0]; return ATRIB;}

";" {return PV;}

"(" {return ABREPAR;}

")" {return FECHAPAR;}

{digito} {yylval = atoi(yytext); return NUM;}

{letra} {yylval = yytext[0]; return ID;}

(12)

Programa .y – Analisador Sintático

%{

#include <stdio.h>

// To avoid warning, we include below definitions: int yylex();

void yyerror(const char *s); %}

%token MAIS MENOS MULT DIV NUM ID ATRIB PV ABREPAR FECHAPAR

%left ATRIB // Operator precedence and associativity

%left MAIS MENOS

%left MULT DIV

Compiladores 23

Programa .y – Analisador Sintático

%%

cmd : ID ATRIB {printf("%c", $1);} expr PV {printf("%c", $2);

printf("\n%d\n", $4);} ;

expr : expr MAIS termo {$$ = $1 + $3; printf("%c", $2);}

| expr MENOS termo {$$ = $1 - $3; printf("%c", $2);} | termo

;

termo : termo MULT fator {$$ = $1 * $3; printf("%c", $2);}

| termo DIV fator {$$ = $1 / $3; printf("%c", $2);}

| fator ;

(13)

Programa .y – Analisador Sintático

fator : ABREPAR expr FECHAPAR {$$ = $2;}

| NUM {printf("%d", $1);} | ID {printf("%c", $1);} ; %% #include "lex.yy.c" int main(){ yyparse(); return(0); }

void yyerror(const char *s){ printf("\nERROR\n"); } int yywrap(){ return 1; }

Referências

Documentos relacionados