Skip to content

Commit

Permalink
Inclusão de algumas ilustrações #14
Browse files Browse the repository at this point in the history
  • Loading branch information
edusantana committed Nov 14, 2014
1 parent 9d1b274 commit f63c8dc
Showing 1 changed file with 27 additions and 54 deletions.
81 changes: 27 additions & 54 deletions livro/capitulos/2-lexica.asc
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,9 @@ ____
[NOTE]
.Organização prévia
====
Instalação do flex::
Para acompanhar as explicações do capítulo é recomendado que você
instale o software *flex* no seu computador, as intruções de instalação
se encontram no <<app_instalacao>>.
Linguagem de programação C::
Este capítulo requer conhecimentos básicos sobre a linguagem de programação C,
recomendamos ter acessível o livro de
https://github.com/edusantana/linguagem-de-programacao-i-livro/releases/latest[Linguagem de Programação I],
caso sinta dificuldades em compreender os códigos apresentados.
se encontram em <<sec_install_flex>>.
====

A análise léxica é a primeira etapa do compilador, e recebe o arquivo de
Expand Down Expand Up @@ -160,10 +150,6 @@ typedef struct
} Token;
----

[[fig_token]]
.Representação gráfica de um Token
image::images/lexica/token.eps[]

Como vimos, um _token_ tem dois campos: o tipo do _token_ e um valor associado. Ambos
os campos são inteiros, então definimos algumas constantes para representar os valores
possíveis desses campos. As primeiras constantes especificam o tipo de _token_:
Expand Down Expand Up @@ -193,10 +179,6 @@ de pontuação:
#define PARDIR 1
----

[[fig_tokens]]
.Tokens de números, operadores e pontuação
image::images/lexica/tokens.eps[]

O código do analisador léxico usa algumas variáveis globais, para facilitar o
entendimento. O programa funciona recebendo o programa de entrada como uma
_string_ (normalmente um compilador recebe o programa de entrada em um arquivo).
Expand Down Expand Up @@ -234,11 +216,7 @@ void inicializa_analise(char *prog)
A função +inicia_analise+ recebe uma _string_ contendo o código do programa
de entrada como parâmetro (+prog+), e armazena um ponteiro para essa _string_
na variável global +codigo+; a função também estabelece o valor da variável
global +tamanho+ e inicializa a posição atual na análise com valor zero.

[[fig_inicia_analise]]
.Representação da função `inicia_analise()`
image::images/lexica/inicia_analise_exemplo.eps[]
global +tamanho+ e inicializa a posição atual na análise com valor zero.

A análise léxica em si funciona de maneira incremental: ao invés de analisar
todo o código de entrada de uma vez e retornar todo o fluxo de _tokens_, a
Expand Down Expand Up @@ -1392,9 +1370,6 @@ a linguagem Mini C é a necessidade de usar tabelas para
armazenar as __strings__ e os nomes de identificadores que ocorrem no
programa.

TIP: Lemebre-se que você pode consultar os códigos completos destes
arquivos no <<app_code>>.

Constantes para os tipos e valores de __tokens__ são definidos no arquivo de
cabeçalho `minic_tokens.h`.

Expand All @@ -1403,7 +1378,7 @@ cabeçalho `minic_tokens.h`.
.Código fonte
{online}/{srcfile}[{local}/{srcfile}]

A parte mais importante do conteúdo deste arquivo é mostrada a seguir:
A parte mais importante do conteúdo deste arquivo é mostrada abaixo:

[source, c]
.Definição de constantes para o analisador léxico
Expand Down Expand Up @@ -1453,7 +1428,13 @@ typedef struct
----

Agora vamos analisar o arquivo de especificação do flex para a linguagem
Mini C, uma seção de cada vez.
Mini C, uma seção de cada vez. O arquivo completo pode ser encontrado no
endereço abaixo.

:srcfile: minic/lex.ll

.Código fonte
{online}/{srcfile}[{local}/{srcfile}]

A seção inicial contém opções e definições, além de trechos de código que
são adicionados no começo do arquivo do analisador gerado:
Expand All @@ -1479,31 +1460,23 @@ STRING \"[^\"\n]*\"
----

As opções são as mesmas que já vimos no exemplo anterior. Temos um trecho de
código incluído no começo do analisador (a parte começando com (((%top))) `%top`) que
código incluído no começo do analisador (a parte começando com `%top`) que
realiza a inclusão de dois arquivos de cabeçalho e define o protótipo da
função `token` (definida na seção de código).

image::images/lexica/lex_ll_include_top.eps[]

O arquivo de cabeçalho `tabelas.h` declara as funções para
função `token` (definida na seção de código). Os cabeçalhos incluídos são
`minic_tokens.h`, visto acima, e `tabelas.h`, que declara as funções para
tabelas de __strings__ e de símbolos: as funções são chamadas de
`adiciona_string()` para adicionar uma nova __string__ na tabela, e
`adiciona_simbolo()` para um novo identificador na tabela de símbolos.
Essas funções são implementadas no arquivo `tabelas.c` e retornam o índice da
`adiciona_string` para adicionar uma nova __string__ na tabela, e
`adiciona_simbolo` para um novo identificador na tabela de símbolos.
Essas funções são definidas no arquivo `tabelas.c` e retornam o índice da
__string__ ou símbolo na tabela respectiva; esse índice pode ser usado como
valor do __token__.footnote:[O uso de tabelas de __strings__ e de símbolos é importante
valor do __token__. O uso de tabelas de __strings__ e de símbolos é importante
por vários motivos, entre eles a eficiência do código do compilador. Em capítulos
seguintes veremos como a tabela de símbolos é uma estrutura de importância
central em um compilador.]

A especificação do analizador em `lex.ll` possui três definições:

`NUM`:: É o padrão para constantes numéricas
inteiras, idêntica à que vimos no exemplo anterior (<<fig_tokens>>);

`ID`:: É o padrão que especifica os identificadores da linguagem;
central em um compilador.

`STRING`:: É o padrão que determina o que é uma
A especificação tem três definições: `NUM` é o padrão para constantes numéricas
inteiras, idêntica à que vimos no exemplo anterior; `ID` é o padrão que especifica
os identificadores da linguagem e `STRING` é o padrão que determina o que é uma
literal __string__ em um programa Mini C: deve começar e terminar com aspas
duplas, contendo no meio qualquer sequência de zero ou mais caracteres que não sejam
aspas duplas nem caracteres de nova linha (`\n`).
Expand All @@ -1514,7 +1487,7 @@ As regras da especificação são mostradas abaixo:
.Regras na especificação para o analisador da linguagem Mini C
----
[[:space:]] { } /* ignora espacos em branco */
\/\/[^\n]* { } /* elimina comentarios de linha */
\/\/[^\n]* { } /* elimina comentarios */
"#include <stdio.h>" { return token(TOK_PROLOGO, 0); }
Expand Down Expand Up @@ -1549,13 +1522,13 @@ printf { return token(TOK_PCHAVE, PC_PRINTF); }
. { return token(TOK_ERRO, 0); }
----

A primeira regra (`[[:space:]]`) ignora os espaços, como vimos no exemplo anterior. A segunda é
A primeira regra ignora os espaços, como vimos no exemplo anterior. A segunda é
para ignorar os comentários. Um comentário é qualquer sequência que começa com duas
barras e vai até o fim da linha. Como a barra é um caractere especial no flex, ele
precisa ser especificado com a contrabarra antes, e portanto `//` vira `\/\/` no
padrão. As outras regras não têm novidade, exceto que a regra para __strings__ e
a regra para identificadores obtêm o valor do __token__ chamando as funções
`adiciona_string()` e `adiciona_simbolo()`, como discutimos antes.
`adiciona_string` e `adiciona_simbolo`, como discutimos antes.

O analisador léxico normalmente não vai ser usado de forma isolada: ele é chamado
pelo analisador sintático para produzir __tokens__ quando necessário, como veremos
Expand All @@ -1571,7 +1544,7 @@ chama o analisador léxico. Esse programa está no arquivo `lex_teste.c`:
O programa principal é seguinte:

[source, c]
.Função main do programa de teste do analisador léxico
.Função do principal do programa de teste do analisador léxico
----
int main(int argc, char **argv)
{
Expand Down Expand Up @@ -1658,7 +1631,7 @@ include::{local}/{srcfile}[]
Compilando o programa principal `lex_teste.c` para gerar um executável `mclex`,
obtemos a seguinte saída para o arquivo `teste.c`:

.Saída do teste do analisador léxico para o arquivo de teste
.Execução do analisador `mclex` sobre o arquivo `teste.c`
....
andrei$ ./mclex teste.c
Tipo: prologo - Valor: 0
Expand All @@ -1678,7 +1651,7 @@ Tipo: pontuacao - Valor: 6
Tipo: pontuacao - Valor: 4
....

É interessante ver que o analisador ignorou a primeira linha com um comentário, e
NOTE: É interessante ver que o analisador ignorou a primeira linha com um comentário, e
o primeiro __token__ mostrado é o prólogo. A sequência de __tokens__ segue corretamente
do conteúdo do arquivo fonte. Também deve ser observado que o valor dos __tokens__
de tipo __string__ e identificador são os índices deles nas tabelas correspondentes.
Expand Down

0 comments on commit f63c8dc

Please sign in to comment.