lex
Este artigo ou secção contém uma lista de referências no fim do texto, mas as suas fontes não são claras porque não são citadas no corpo do artigo, o que compromete a confiabilidade das informações. (Setembro de 2023) |
Em ciência da computação (linguagens de programação), lex é um programa que gera analisadores léxicos. Ele é geralmente usado com o yacc, um gerador de analisador sintático. Escrito originalmente por Eric Schmidt e Mike Lesk, ele é o gerador de analisador léxico padrão em diversos sistemas Unix.
O lex lê um fluxo de entrada especificando um analisador que mapeia expressões regulares em blocos de código, e retorna um código fonte implementando o analisador. Apesar do gerador ser genérico e poder se adequar a diferentes linguagens de programação, atualmente, somente a geração de código C é suportada.
Apesar de ser software proprietário, versões do lex baseadas no código original da AT&T estão disponíveis em código aberto, como parte de sistemas como OpenSolaris e Plan 9. Outra versão popular e livre do lex é o flex.
Estrutura do arquivo
[editar | editar código-fonte]A estrutura de um arquivo lex é intencionalmente similar ao de um arquivo yacc. Os arquivos são divididos em três seções, separadas por linhas que contém somente dois símbolos de percentagem, como a seguir:
definições %% regras %% subrotinas
Na seção de definições são definidas as macros e são importadas as bibliotecas escritas em C. É também possível escrever código C na mesma seção. Já a seção de regras associa padrões com instruções C, padrões escritos na forma de expressões regulares. Quando o analisador léxico identifica algum texto da entrada casando com um padrão, ele executa o código C associado. A tentativa do casamento é sempre gananciosa, isto é, no caso de dois padrões distintos casando a mesma entrada, o maior deles será usado. O maior deles é o que consome mais caracteres da entrada. Caso os padrões ambíguos consumam a mesma quantidade de caracteres, o padrão definido antes é escolhido. Por fim, a seção de subrotinas contém blocos de código C que serão apenas copiados ao arquivo final. Assume-se que tal código será invocado a partir das regras da seção de regras. Em programas maiores, é mais conveniente separar esse código final noutro arquivo.
Exemplo de um arquivo lex
[editar | editar código-fonte]O seguinte exemplo reconhece inteiros da entrada de dados e os imprime na saída padrão.
/*** seção de definição ***/ %{ # include <stdio.h> %} %% /*** seção de regras ***/ /* [0-9]+ casa uma cadeia de um ou mais dígitos */ [0-9]+ { /* yytext é a cadeia contendo o texto casado. */ printf("Inteiro: %s\n", yytext); } . { /* Ignora outros caracteres. */ } %% /*** seção de código C ***/ int main(void) { /* executa o analisador léxico. */ yylex(); return 0; }
Com a entrada acima, será feita a conversão para um arquivo C. Para a seguinte entrada:
abc123z.!&*2ghj6
O programa imprimirá:
Inteiro: 123 Inteiro: 2 Inteiro: 6
Relacionamento com yacc
[editar | editar código-fonte]O lex e o gerador de analisador sintático yacc são geralmente usados em conjunto. O Yacc usa uma gramática formal para analisar sintaticamente uma entrada, algo que o lex não consegue fazer somente com expressões regulares (o lex é limitado a simples máquinas de estado finito). Entretanto, o yacc não consegue ler a partir duma simples entrada de dados, ele requer uma série de tokens, que são geralmente fornecidos pelo lex. O lex age como um pré-processador do yacc. Segue abaixo dois diagramas do relacionamento entre lex e yacc:
|
|
A partir do diagrama 1, percebe-se que o lex gera a subrotina yylex()
a partir de regras léxicas, e que o yacc gera a subrotina yyparse()
a partir de regras gramaticais. A partir do diagrama 2, percebe-se que um programa qualquer invoca o analisador sintático para uma fluxo de entrada. O analisador sintático não consegue analisar entradas, mas sim tokens. Portanto, cada vez que ele precisa dum token, ele invoca o analisador léxico. O analisador léxico processa o fluxo de entrada e retorna o primeiro token que encontrar. Esse processo de requisição é contínuo e só termina quando o analisador léxico identifica o fim o fluxo de entrada ou quando o analisador sintático identifica uma falha gramatical.
Referências gerais
[editar | editar código-fonte]- M. E. Lesk e E. Schmidt. «Lex - A Lexical Analyzer Generator». The Lex & Yacc Page (em inglês). Consultado em 22 de julho de 2008
- Ivan L. M. Ricarte (14 de fevereiro de 2003). «Desenvolvimento de uma aplicação». Programação de Sistemas: Uma Introdução. Universidade Estadual de Campinas. Consultado em 22 de julho de 2008