next up previous contents
Next: Integração com código C Up: Analisadores léxicos Previous: Geradores de analisadores léxicos   Sumário

Especificação das sentenças regulares

O ponto de partida para a criação de um analisador léxico usando lex é criar o arquivo com a especificação das expressões regulares que descrevem os itens léxicos que são aceitos. Este arquivo é composto por até três seções: definições, regras e código do usuário. Essas seções são separadas pelos símbolos %%.

A seção mais importante é a seção de regras, onde são especificadas as expressões regulares válidas e as correspondentes ações do programa. Cada regra é expressa na forma de um par padrão-ação,

  pattern   action

Para a descrição do padrão, lex define uma linguagem para descrição de expressões regulares. Esta linguagem mantém a notação para expressões regulares apresentada na Seção 3.1.4, ou seja, a presença de um caráter $ a$ indica a ocorrência daquele caráter; se $ R$ é uma expressão regular, $ R*$ indica a ocorrência dessa expressão zero ou mais vezes; e se $ S$ também é uma expressão regular, então $ R S$ é a concatenação dessas expressões e $ R \vert S$ indica a ocorrência da expressão $ R$ ou da expressão $ S$. Além dessas construções, a linguagem oferece ainda as seguintes extensões:

. qualquer caráter exceto \n
[xyz] uma classe de caracteres, 'x' ou 'y' ou 'z'
[a-f] classe de caracteres, qualquer caráter entre 'a' e 'f'
[^xyz] classe de caracteres negada, qualquer caráter exceto 'x' ou 'y' ou 'z'
R+ uma ou mais ocorrências da expressão regular R
R? 0 ou uma ocorrência da expressão regular R
R{4} exatamente quatro ocorrências da expressão regular R
R{2,} pelo menos duas ocorrências da expressão regular R
R{2,4} entre duas e quatro ocorrências da expressão regular R
^R a expressão regular R ocorrendo apenas no início de uma linha
R$ a expressão regular R ocorrendo apenas no final de uma linha
<<EOF>> fim de arquivo

Caso deseje-se usar um dos caracteres que têm significado especial nessa linguagem como um caráter da expressão, é possível usar a construção \X; por exemplo, \. permite especificar a ocorrência de um ponto na expressão regular. Se $ X \in
\{0,a,b,f,n,r,t,v\}$, então o caráter recebe a mesma interpretação associada às definições da linguagem C (Tabela 2.2). Outra forma de indicar que uma string deve ser interpretada literalmente é representá-la entre aspas na regra.

A ação associada a cada padrão na regra é um bloco de código C definido pelo usuário. Esse código será incorporado ao código do analisador léxico, sendo executado quando a seqüência de caracteres de entrada for reconhecida pelo padrão especificado. Como qualquer bloco em C, se apenas uma linha de código for especificada então as chaves de início e fim de bloco podem ser omitidas; caso contrário, devem obrigatoriamente estar presentes.

O exemplo abaixo de especificação de regras no padrão lex determina o reconhecimento de constantes numéricas inteiras, segundo o padrão da linguagem C:
\begin{listing}{1}
[1-9][0-9]* printf(''Dec'');
0[0-7]* printf(''Oct'');
0x[0-9A-Fa-f]+ printf(''Hex'');
\end{listing}
A primeira linha do arquivo começa com o separador de seções, ou seja, a seção de definições, assim como a seção de código do usuário, é vazia.

O analisador léxico gerado por esse arquivo de especificação irá receber como entrada strings que eventualmente irão conter constantes inteiras. Se uma constante inteira for encontrada, ela será substituída na saída pela string correspondente especificada na ação, para cada um dos formatos de constantes reconhecidos. Assim, se a string for

abc 10 def 017 ghi 0xAF0
o analisador léxico gerará a string
abc Dec def Oct ghi Hex

Esse exemplo ilustra a utilização da regra padrão -- quando nenhum padrão especificado combina com a seqüência de caracteres analisada, então esses caracteres são simplesmente ecoados para a saída.

A seção de definições permite criar representações simbólicas que podem ser posteriormente utilizadas nas seções de regras. Por exemplo, se nessa seção houver a definição

  DIGIT    [0-9]
então o padrão da regra que reconhece constantes decimais poderia ter sido escrito na forma
  [1-9]{DIGIT}*
A forma {name} é substituída no padrão pela expansão da definição name.

Outro tipo de especificação que pode estar presente na seção de definições são trechos de código C que devem ser incluídos ao início do arquivo. Esse código, especificado nessa seção entre os símbolos %{ e %}, normalmente é utilizado para incluir diretrizes para o pré-processador C, como #define e #include.


next up previous contents
Next: Integração com código C Up: Analisadores léxicos Previous: Geradores de analisadores léxicos   Sumário
Ivan L. M. Ricarte 2003-02-14