Identificação do discente: Nome completo: Douglas Godeguez Nunes Matrícula: 547927 Curso: Ciência da Computação Identificação do professor-orientador: Nome completo: Maria do Carmo Garcia Noronha Curso: Ciência da Computação Nome do projeto de pesquisa ao qual o aluno inscrito está vinculado: Identificação do Projeto: Título: Estudando um gerador automático de analisadores léxicos Curso: Graduação em Sistemas de Informação Linha de pesquisa do curso a qual o projeto está vinculado: Palavras-chave (três): Desenvolvimento e Aplicação de Algoritmos Flex Expressões regulares Analisador léxico
Título do Projeto de Iniciação científica: Estudando um gerador automático de analisadores léxicos Justificativa e Relevância do Tema Em um sistema moderno de TI, a necessidade de obter determinadas informações sobre arquivos de dados rapidamente é a diferença entre o sucesso e o fracasso de uma empresa. Para tal, os desenvolvedores de sistemas têm oferecido softwares que aceleram o recebimento de respostas, e ainda reduzem o trabalho do programador ao mínimo necessário, construindo ferramentas de auxílio na escrita de programas que promovem transformações de entradas estruturadas. Um analisador léxico ( scanner ) é um programa que permite ler os caracteres de um arquivo de texto (e.g., programa-fonte) e produzir uma sequência de componentes léxicos (tokens) que serão utilizados pelo analisador sintático ( parser ) e/ou identificar erros léxicos na entrada. Além de sua função básica, o analisador léxico em geral está encarregado de fazer algumas tarefas secundárias, designadamente, a eliminação de comentários, espaços em branco e tabulações. Um token representa um conjunto de cadeias de entrada possível e por sua vez, um lexema é uma determinada cadeia de entrada associada a um token. A ferramenta Lex 1 ou Flex 2 (LEVINE; MASON; BROWN, 1995) é um gerador de programas projetado para o processamento léxico 3 de sequências de caracteres. Segundo Price et al (2000), o analisador léxico pode ser implementado através de um gerador automático de analisadores léxicos como o Flex. Foi desenvolvida nos Bell Laboratories em meados dos anos 70, para programadores de compiladores e interpretadores, com a finalidade de separar a entrada em unidades léxicas, como preparação para um analisador sintático. Entretanto, a ferramenta é válida 1 lex-. [Do gr. lexix, eos.] El. comp. = 'ação de falar', 'palavra',... 2 flex=fast lexical analyser generator 3 léxico [Do gr. lexikón.] S.m. 1. Dicionário de línguas clássicas antigas.... 5. Conjunto de vocábulos de um idioma....
também para outras aplicações, como detecção de padrões em arquivos de dados, linguagens de comandos, auditorias etc. O FLEX é uma ferramenta que permite gerar analisadores léxicos. Estes analisadores são capazes de reconhecer padrões léxicos em texto (e.g., números, identificadores e palavras-chave de uma determinada linguagem de programação). O analisador é construído com base num conjunto de regras. Uma regra é constituída por um par, padrão ação, o padrão (expressão regular) descreve o elemento a reconhecer e ação (ou conjunto de ações) define o procedimento que será realizado no caso de identificação positiva do padrão. Com base num arquivo-fonte escrito de acordo com a sintaxe do FLEX, o programa FLEX gerará um analisador léxico descrito na linguagem C. Em caso de existirem erros de codificação, o FLEX gerará uma listagem de erros. O código-fonte em C terá de ser compilado para a plataforma em utilização utilizando um compilador da linguagem C adequado (no caso do Linux, o GCC). O resultado final da compilação será um programa executável capaz de identificar os padrões definidos pelo programador e levar o conjunto de ações previsto. Como entrada para o analisador gerado, podem ser fornecidos arquivos de texto ou alternativamente fornecer os dados diretamente pela entrada-padrão do sistema. No exemplo seguinte são apresentados os comandos do Shell do sistema que compõem os passos necessários à compilação e utilização de um programa FLEX. Considere-se a existência de um arquivo arquivo.flex com o programa FLEX já escrito. flex arquivo.flex gcc lex.yy.c -lfl./a.out O comando flex gera, por omissão, um arquivo com o nome lex.yy.c que deverá ser compilado, por exemplo com o gcc. Na utilização do gcc é necessário indicar a utilização da biblioteca FLEX
adicionando o parâmetro -lfl. Por sua vez, o compilador de C gera, por omissão, um arquivo com o nome a.out. Por último, para a execução deste programa basta a evocação do seu nome na linha de comandos. Neste caso, a introdução dos dados terá de ser realizada via teclado (terminando obrigatoriamente com Ctrl+D). flex -oexemplo.c Exemplo.flex gcc Exemplo.c -o Programa -lfl./programa < Dados.txt Neste exemplo, o comando flex gera a partir do arquivo Exemplo.flex, o arquivo com o nome Exemplo.c que deverá ser compilado. Nesta utilização apresentada do gcc, é indicado o nome do executável a ser gerado, neste caso, Programa. Na execução do Programa, a introdução dos dados é realizada a partir do arquivo Dados.txt. Um programa em FLEX é constituído por três seções, a saber, declarações, regras e rotinas auxiliares. A separação entre as seções é feita inserindo uma linha com o símbolo %%. Considere-se o seguinte exemplo: %{ int numchars=0; %} %%. { numchars++; printf ( "%s", yytext ) ; } \n { numchars++; printf ( "\n" ) ; } %% main ( ) { yylex ( ) ; printf ( "Número de caracteres %d\n", numchars ) ; } A primeira seção, declarações, compreende duas partes:
(a) Instruções C nesta parte, delimitada pelos símbolos %{ e %}, são colocadas as instruções da linguagem C que posteriormente serão incluídas no início do arquivo C a gerar pelo FLEX. Os exemplos mais comuns são a inclusão de arquivos de cabeçalhos (headers.h), declarações de variáveis e constantes. (b) Expressões regulares nesta parte, podem ser declaradas macros para as expressões regulares mais comuns, como por exemplo, algarismo ou letra do alfabeto. /_ Definição de macros _/ ALGARISMO [0 9] /_ Algarismo _/ ALFA [ a za Z ] /_ Letra do alfabeto _/ Na segunda seção são apresentadas as regras (definição de padrões e ações) onde são definidas as expressões regulares (padrões) e as respectivas ações que se pretendem realizar no caso da identificação positiva ( pattern matching ) do referido padrão. No caso de um caractere qualquer, exceto mudança de linha (representado por. ) é incrementada a variável num_chars e impresso o referido caractere na saída-padrão. A mudança de linha (representado por \n ) é também contabilizada como um caractere e escrita na saídapadrão. O analisador léxico gerado funciona de acordo com as seguintes regras: Apenas uma regra é aplicada à entrada de dados; A ação executada corresponde à expressão que consome o maior número de caracteres; Caso existam duas ou mais expressões que consumam igual número de caracteres, tem precedência a regra que aparece em primeiro no arquivo. Quando um padrão é reconhecido, a sequência de caracteres consumida (token) na identificação do padrão é guardada na variável yytext (do tipo char *). Para além disso, o comprimento da referida sequência é guardado na variável yylengt (do tipo int).
Na terceira seção são escritas as rotinas de suporte em linguagem C que se pretende que seja adicionado ao programa a gerar pelo FLEX. Tipicamente este código inclui o corpo do programa, designadamente, a função main() da linguagem C. A função yylex() evoca o analisador léxico gerado pelo flex que processará as expressões regulares anteriormente descritas na seção anterior. Consideremos um exemplo mais elaborado, no qual é contabilizada a quantidade de números e de linhas existentes no arquivo. Neste exemplo, recorre-se à utilização de um macro para a definição de algarismo. %{ int qtdnumeros=0, nlinhas=0; %} ALGARISMO [0 9] %% /_ Se a ação for descrita numa só linha as chaves podem ser omitidas _/ \n { nlinhas++; } {ALGARISMO}+ { printf ( "d %s \n", yyt ext ) ; qtdnumeros++;}. { } %% main ( ) { yyl ex ( ) ; printf ( "# l i n h a s=%d\n", nlinhas ) ; printf ( "# numeros=%d\n", qtdnumeros ) ; } Todos os caracteres não processados pelas duas primeiras expressões regulares são consumidos pela última à qual não corresponde nenhuma ação particular. Quanto ao ambiente de trabalho, o acesso a uma máquina LINUX pode ser realizado utilizando o programa flex que deverá estar instalado no Shell. A edição dos arquivos fonte pode ser realizada a partir de qualquer editor de texto básico (e.g., no ambiente Windows existe o Bloco de Notas) desde que os arquivos sejam gravados em formato txt. A seguir, são apresentados alguns dos padrões mais relevantes utilizados pelo FLEX.
Padrão x Universidade Municipal de São Caetano do Sul Descrição O caractere x. Qualquer caractere exceto mudança de linha \n Mudança de linha [xyz] xyz Um dos caracteres x, y ou z A cadeia de caracteres xyz [a-za-z] Um dos caracteres no intervalo de a a z ou de A a Z [-+*/] Qualquer um dos operadores -, +, * ou /, sendo que o símbolo - tem de aparecer em primeiro lugar dada a possibilidade de ambiguidade com a definição de intervalo [abj-oz] Um dos caracteres a, b ou de j a o ou Z [ˆA-Z\n] Qualquer caractere exceto no intervalo de A a Z ou mudança de linha r* O caractere r zero ou mais vezes r+ O caractere r uma ou mais vezes r? O caractere r zero ou uma vez r{2,5} r{2,} r{4} O caractere r repetido de duas a cinco vezes O caractere r repetido pelo menos duas vezes O caractere r repetido exatamente quatro vezes {macro} Substituição/Expansão da macro definida anteriormente (r) xyz* (xyz)* r s ˆr O caractere r, sendo que os parêntesis permitem estipular precedências A sequência xy seguida de zero ou mais z s A sequência xyz repetida zero ou mais vezes O caractere r ou s (alternativa) O caractere r apenas se no início da linha r$ O caractere r apenas se no final da linha (não consome o \n) ˆxyz$ Uma linha que contém apenas a cadeia de caracteres xyz <<EOF>> Fim de arquivo Objetivos
As vantagens desse sistema sobre as ferramentas alternativas estão em permitir um rápido desenvolvimento de protótipos e na manutenção simples do software, além de favorecer a tomada de decisão e de providências importantes e imprescindíveis no desenvolvimento de um sistema de TI. Nossa proposta está no desenvolvimento de estudos de caso usando a ferramenta Lex na geração automática de códigos a partir de arquivos diversos, para transformações simples e extração de padrões em textos. Metodologia A metodologia utilizada no desenvolvimento desse trabalho ainda em andamento segue as seguintes etapas: (a) Levantamento de material bibliográfico relativo aos conceitos envolvidos; (b Familiarização com a ferramenta FLEX; (c) Pesquisa sobre ferramentas de geração de analisadores de padrões existentes; (d) Estudos: Introdução ao reconhecimento de padrões e expressões regulares; (e) estudo do ambiente de trabalho proposto, reforçando alguns comandos básicos de Linux importantes para a utilização do FLEX; (f) Aprendizagem dos conceitos através da realização de alguns exercícios práticos e implementação no ambiente escolhido; (g) Testes de funcionalidade; e análise dos resultados. Os métodos estão apresentados no cronograma proposto. Estaremos trabalhando tempo integral nas dependências da Universidade. Serão necessários para o desenvolvimento do projeto: Um microcomputador onde estará instalado o sistema operacional Linux; A ferramenta Flex ou Lex instalada nos comandos do Shell; e Papel sulfite para elaboração dos relatórios. Cronograma de Atividades do Projeto
Tabela 1 Plano de Atividades (agosto 2009 julho 2010) PERÍODO ATIVIDADE 2009 Agosto Setembro Outubro Novembro Dezembro Pesquisa e Estudo da ferramenta Flex ou Lex Estudos referentes aos pré-requisitos Linguagens Formais Construção de cenários que permitam testar as funcionalidades da ferramenta. Implementação e análise dos testes. Análise dos resultados dos testes. 2010 Janeiro Fevereiro Março Abril Maio Junho Julho Elaboração de relatório parcial Montagem de um conjunto significativo de testes Participação em Workshop de Iniciação Científica Elaboração da documentação dos experimentos práticos efetuados dos cenários de testes criados Elaboração da documentação dos experimentos práticos efetuados Montagem final da documentação Elaboração do relatório final Bibliografia Básica
LEVINE, R. John; MASON, Tony; BROWN, Doug. Lex & Yacc. Beijing: O Reilly, 1995. 363p. PRICE, Ana Maria de Alencar; TOSCANI, Simão Sirineo. Implementação de linguagens de programação: compiladores. Porto Alegre: Sagra-Luzzatto: 2000. 216p. Jandl, Peter Jr. Flex - Um Tutorial. Disponível no endereço: http://docente.saofrancisco.edu.br/peter/aulas/comp/flextutorial.html. Acesso em: 2 junho 2009