next up previous contents
Next: Geração de código e Up: Geradores de analisadores sintáticos Previous: Manipulação das sentenças reconhecidas   Sumário

Desenvolvimento de uma aplicação

Nesta seção descreve-se o procedimento para desenvolver uma aplicação, usando a ferramenta bison, que realiza a análise sintática de um arquivo de entrada. A ferramenta bison é uma implementação de yacc disponível para diversas plataformas e distribuída, assim como flex, sob a licença de software GNU da Free Software Foundation.

A execução de bison requer como argumento o nome do arquivo com a gramática especificada. Se esse arquivo recebeu, por exemplo, o nome mygram.y, então a linha de comando

  bison mygram.y
gera um módulo-fonte em C de nome mygram.tab.c que contém a definição das tabelas para a análise sintática e a rotina de reconhecimento, cujo nome é yyparse().

A rotina yyparse() deve ser invocada pela aplicação para que a análise sintática do arquivo de entrada seja realizada. Esta rotina retorna um valor inteiro, que será 0, se toda a entrada pode ser reconhecida sem erros pela gramática especificada, ou 1, caso algum erro sintático tenha sido detectado no arquivo de entrada.

A rotina yyparse() irá invocar uma rotina yylex() que irá varrer o arquivo de entrada e retornar os tokens para o analisador sintático. Essa rotina não é criada automaticamente e deve ser fornecida pelo usuário. Tipicamente, mas não necessariamente, essa rotina é gerada por uma ferramenta lex.

Caso a rotina yylex() fornecida seja simples o suficiente para ser definida manualmente, então seu código pode ser incluído na seção de usuário do arquivo de especificação da gramática e todas as definições de tipos de tokens podem ser usadas diretamente. Caso contrário -- por exemplo, se flex for ser utilizada para gerar a rotina de análise léxica -- então é preciso transportar essas definições para os demais módulos da aplicação. Para tanto, utiliza-se a chave de execução -d, que gera um arquivo de cabeçalho com essas definições:

  bison -d mygram.y
Com essa opção, além do arquivo-fonte C um arquivo de nome mygram.tab.h é gerado com as definições necessárias, podendo ser incluído em outros módulos para realizar a integração. Por exemplo, um arquivo mylex.l contendo a especificação para reconhecimento de tokens usando flex poderia conter, na sua seção de definições, a declaração
 %{
  #include "mygram.tab.h"
 %}
 %%  /* definições das expressões regulares: */

Outro aspecto importante na integração das rotinas yyparse() e yylex() é na forma de definição dos valores semânticos e dos tipos dos tokens. A definição do tipo de token é determinada pelo valor de retorno de yylex(). Por exemplo, se no arquivo mygram.y houvesse a declaração

  %token INTEGER
então a ação associada ao reconhecimento de um padrão regular que reconhecesse esse tipo de token deveria concluir com a expressão
  return INTEGER;

O outro ponto de ligação entre as duas rotinas é a definição do valor semântico, que é realizado através de uma variável global yylval, definida no módulo mygram.tab.c. Para aplicações que trabalham com um único tipo de valor, basta atribuir na ação associada ao reconhecimento do token o valor semântico resultante, como em

    ...
    yylval = atoi(yytext);
    return INTEGER;
    }

Se a aplicação opera com múltiplos tipos de valores semânticos, então será preciso qualificar a atribuição, indicando qual componente da união de tipos está sendo utilizada:

    ...
    yylval.ival = atoi(yytext);
    return INTEGER;
    }

A Figura 3.13 ilustra a forma de operação integrada das rotinas yyparse() e yylex(). A partir do código principal da aplicação, a rotina yyparse() é invocada. Eventualmente, o código main() pode alterar os valores das variáveis globais yyin e yyout, definidas no módulo do analisador léxico, para determinar quais arquivos serão utilizados para a entrada e a saída de yylex(). A rotina yyparse() irá solicitar de rotina yylex() que obtenha os tokens do arquivo de entrada; para tanto, yylex() lê os caracteres desse arquivo, compondo os tokens segundo as expressões regulares definidas. Uma vez reconhecido um token, yylex() atribui seu valor semântico (através da variável global yylval, definida no módulo do analisador sintático) e qual a string correspondente (através da variável global yytext, definida pelo analisador léxico).

Figura: Operação integrada dos analisadores léxicos e sintáticos.
\includegraphics{lexyacc.eps}


next up previous contents
Next: Geração de código e Up: Geradores de analisadores sintáticos Previous: Manipulação das sentenças reconhecidas   Sumário
Ivan L. M. Ricarte 2003-02-14