SlideShare une entreprise Scribd logo
1  sur  51
Télécharger pour lire hors ligne
Análise léxica

  Ivan Ricarte


     2008




                 I NTRODUÇÃO À COMPILAÇÃO
Sumário

  Varredura de tokens

  Classificação de tokens
     Autômatos finitos
     Construção dos autômatos finitos
        Algoritmo de Thompson
        Conversão para autômato finito determinístico
        Minimização de estados


  Analisadores léxicos
    Visão conceitual
    Aspectos de implementação

  Geradores de analisadores léxicos

                                                       I NTRODUÇÃO À COMPILAÇÃO
Compiladores: análise léxica




   Reconhecimento, a partir dos caracteres, das palavras básicas
   do “vocabulário” do programa

       palavras-chaves da linguagem, operadores,
       identificadores, constantes
       elementos que podem ser adequadamente descritos por
       meio de gramáticas regulares




                                                      I NTRODUÇÃO À COMPILAÇÃO
Análise léxica




   Arquivo de        análise
                                                                    Arquivo de
                                     ...                síntese      destino
     origem           léxica
                               análise


                                           Estruturas
                Gramáticas                  internas




                                                                  I NTRODUÇÃO À COMPILAÇÃO
Gramática regular ou tipo 3
Revisão




          Apenas um símbolo não-terminal no lado esquerdo de
          cada produção
          Produções recursivas não apresentam auto-incorporação
              Produção recursiva: mesmo símbolo aparece do lado
              esquerdo e do lado direito
              Sem auto-incorporação: o símbolo do lado esquerdo
              aparece apenas no início ou no final da seqüência de
              símbolos do lado direito
          A linguagem regular descrita por uma gramática tipo 3
          também pode ser descrita por meio de uma expressão
          regular



                                                           I NTRODUÇÃO À COMPILAÇÃO
Analisadores léxicos




   Programas que realizam a análise léxica

       Duas atividades básicas
        1. Obter grupos de caracteres, a partir do arquivo com
           conteúdo a ser analisado, que constituem strings válidas
           em uma dada linguagem
                Cada grupo de caracteres é um token
        2. Identificar qual é o tipo de token




                                                          I NTRODUÇÃO À COMPILAÇÃO
Varredura de tokens




      Leitura seqüencial dos caracteres da entrada
          Agrupamento de caracteres reconhecido como um token
          da entrada
      Utiliza as facilidades oferecidas pelas linguagens de
      programação para leitura de arquivos




                                                       I NTRODUÇÃO À COMPILAÇÃO
Varredura de tokens
Recursos da linguagem C++




         Definições no arquivo de cabeçalho <fstream>
         Leitura seqüencial de arquivos com a classe ifstream
             Métodos open, eof
         Cada token é um objeto da classe string (arquivo de
         cabeçalho <string>)
         Leitura de tokens separados por brancos com o operador »




                                                      I NTRODUÇÃO À COMPILAÇÃO
Varredura de tokens
Exemplo básico




        #include <fstream>
        #include <string>
        ...
        ifstream arq;
        string token;
        ...
        arq.open("nome_arquivo");
        ...
        while (! arq.eof() )
            arq >> token;



                                    I NTRODUÇÃO À COMPILAÇÃO
Classificação de tokens




      Token obtido precisa ser classificado
           É um identificador, uma palavra-reservada, uma constante?


                             Extrair            Classificar
      Entrada   caracteres   tokens    string     token           tipo de
                                                                   token




                                                              I NTRODUÇÃO À COMPILAÇÃO
Autômatos finitos



      O núcleo do analisador léxico é uma implementação de
      um autômato finito
          máquina de estados finitos que aceita símbolos de uma
          sentença
          ao final da sentença, indica se ela é válida para a
          gramática ou não
          autômato é definido para cada conjunto de símbolos que
          deve ser reconhecido
      Cada tipo de token é definido por uma lista ou por uma
      gramática regular




                                                      I NTRODUÇÃO À COMPILAÇÃO
Autômato finito
Definição formal




    Autômato é descrito por uma quíntupla
                              M = (K , Σ, δ, s, F )

                  K conjunto (finito) de estados
                  Σ alfabeto (finito) de entrada
                  δ conjunto de transições
                  s estado inicial, s ∈ K
                  F conjunto de estados finais, F ⊆ K




                                                       I NTRODUÇÃO À COMPILAÇÃO
Autômato finito
Representação gráfica




    Estados e transição


                       si   a   sf




                                     I NTRODUÇÃO À COMPILAÇÃO
Autômato finito
Representação gráfica



    Estados inicial e finais



                       s0         a        s1

                              b


                                      s2



                                                I NTRODUÇÃO À COMPILAÇÃO
Autômato finito
Representação tabular




                                 s0   s1   s2
                             a   s1   —    —
                             b   s2   —    —

    Estado inicial: s0
    Estados finais: s1 , s2




                                                I NTRODUÇÃO À COMPILAÇÃO
Tipos de autômatos
Não determinísticos




    A partir de um estado:
        pode haver transições para dois ou mais estados
        diferentes pela ocorrência de um mesmo símbolo na
        entrada
               uma das transições é escolhida se ocorrer aquele símbolo
         pode haver transição para outro(s) estado(s) sem a
         ocorrência de nenhum símbolo
               transição pela string vazia




                                                             I NTRODUÇÃO À COMPILAÇÃO
Tipos de autômatos
Determinísticos




          Transição sempre ocorre pela ocorrência de um símbolo
          de entrada
                  Não há transições pela string vazia
          Não há alternativas distintas para a transição a partir de
          um dado estado e com um dado símbolo de entrada




                                                            I NTRODUÇÃO À COMPILAÇÃO
Construção dos autômatos finitos

      Há um procedimento sistemático para construir um
      autômato que reconhece strings de uma linguagem
      regular:
      Algoritmo de Thompson construção de um autômato finito
                  não determinístico a partir de uma expressão
                  regular
      Método da construção de subconjuntos conversão do
                  autômato finito não determinístico para um
                  autômato finito determinístico equivalente
      Minimização de estados combinação de estados
                  redundantes do autômato para construir o
                  menor autômato finito determinístico que
                  reconhece as strings da linguagem regular
                  especificada

                                                    I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson



  Compõe um autômato finito não determinístico pela
  combinação de pequenos autômatos que reconhecem os
  elementos primitivos de uma expressão regular:
     Um símbolo do alfabeto da linguagem
     Concatenação de duas expressões regulares
     Alternativa de duas expressões regulares
     Repetição (zero ou mais vezes) de uma expressão regular




                                                  I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson
Autômato que reconhece um símbolo do alfabeto




                                         σ
                              i                 f




                                                    I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson

     Para as demais construções, dois autômatos serão
     combinados, um para a expressão regular R e outro para
     a expressão regular S:


                     iR       .....        fR




                     iS       .....        fS


                                                  I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson
Concatenação de duas expressões regulares




         Autômato que reconhece RS

                                        ε
            iR      .....        fR         iS   .....           fS




                                                         I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson
Alternativa de duas expressões regulares



          Autômato que reconhece R|S


                               iR          .....   fR
                      ε                                 ε

                  i                                            f
                      ε        iS          .....   fS   ε


                                                            I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson
Repetição de uma expressão regular




         Autômato que reconhece R∗

                                      ε

                       ε       iR            fR
                                                  ε
                 i                   .....                f

                                      ε



                                                      I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson
Exemplo




    Autômato finito não-determinístico para reconhecer tokens da
    linguagem (0|1)*0:
     1. Combinação de autômatos para reconhecer a
        concatenação de (0|1)* e 0
     2. Para reconhecer (0|1)*, um autômato para reconhecer a
        repetição de 0|1
     3. Para reconhecer 0|1, um autômato para reconhecer a
        alternativa entre 0 e 1




                                                      I NTRODUÇÃO À COMPILAÇÃO
Algoritmo de Thompson
Exemplo



           Autômato para (0|1)*0
                                         ε


                                 0
                            e3               e5
                                                  ε
                        ε
               ε                                           ε        ε          0
          e1       e2                                 e7       e8       e9             e10
                        ε                         ε
                                 1
                            e4               e6




                                     ε




                                                                             I NTRODUÇÃO À COMPILAÇÃO
Conversão para autômato finito determinístico
O método da construção de subconjuntos




         Procedimento para conversão de autômato finito
         não-determinístico (AFND) para autômato finito
         determinístico (AFD) que reconhece strings da mesma
         expressão regular
         Estados que podem ser alcançados a partir de outro por
         meio de transições pela string vazia são combinados num
         único estado
              Conceito de ε∗ de um subconjunto de estados do AFND




                                                         I NTRODUÇÃO À COMPILAÇÃO
O método da construção de subconjuntos


  1. Obter estado inicial
      O estado inicial do AFD é definido como a ε∗ do conjunto
      contendo apenas o estado inicial do AFND

  2. Obter novos estados e transições
      Cada estado obtido para o AFD é analisado para
      descobrir, para cada símbolo do alfabeto, suas transições
      de saída e novos estados que são gerados

  3. Marcar estados finais
      Cada estado do AFD que contenha em seu subconjunto
      um estado final do AFND será um estado final do AFD


                                                     I NTRODUÇÃO À COMPILAÇÃO
Conversão para autômato finito determinístico
Exemplo



           Conversão do autômato para (0|1)*0
                                         ε


                                 0
                            e3               e5
                                                  ε
                        ε
               ε                                           ε        ε          0
          e1       e2                                 e7       e8       e9             e10
                        ε                         ε
                                 1
                            e4               e6




                                     ε




                                                                             I NTRODUÇÃO À COMPILAÇÃO
Conversão para autômato finito determinístico
Exemplo


          Estado inicial ε∗ {e1}
              {e1, e2, e3, e4, e8, e9} : s0
          Transições a partir do estado s0
                      s0 e1 e2 e3 e4            e8   e9
                       0 — — e5 —               —    e10
                       1 — — — e6               —     —
                s0/0: ε∗ {e5, e10} =
                      {e2, e3, e4, e5, e7, e8, e9, e10}   (s1) (final)
                s0/1: ε∗ {e6} =
                      {e2, e3, e4, e6, e7, e8, e9}          (s2)
          Estados s1, s2 devem ser analisados da mesma forma,
          assim como novos estados que surjam desta análise

                                                            I NTRODUÇÃO À COMPILAÇÃO
Conversão para autômato finito determinístico
Exemplo: resultado



                                           0


                                      s1
                          0

                     s0       1                0

                          1
                                      s2

                                  1

                                                   I NTRODUÇÃO À COMPILAÇÃO
Minimização de estados




     Método da construção de subconjuntos gera autômato
     finito determinístico
         Possivelmente, com estados redundantes
     Procedimento de minimização permite obter autômato
     equivalente com menor número de estados
         Baseado no particionamento sucessivo do conjunto de
         estados




                                                     I NTRODUÇÃO À COMPILAÇÃO
Procedimento de minimização de estados

  1. Particione o conjunto de estados do autômato
      Em um grupo, estados que são finais
      No outro grupo, todos os demais estados

  2. Avalie transições para os estados de cada grupo
      Refinar particionamento: estados que têm transições para
      grupos diferentes têm que ser colocados em (novos)
      grupos diferentes

  3. Combinar estados redundantes
      Quando todos os estados do grupo não mudam os grupos
      de destino quando transições são avaliadas, estados são
      redundantes — um único estado é suficiente para
      descrever esse comportamento
                                                   I NTRODUÇÃO À COMPILAÇÃO
Minimização de estados
Exemplo




          Para o autômato obtido para a expressão (0|1)*0
           1. Partição inicial P1 = {C1 , C2 }, com

                            C1 = {s1}           C2 = {s0, s2}

           2. Para a partição C2 :
                                        s0 s2
                                    0 C1 C1
                                    1 C2 C2
              ⇒ Estados s0, s2 são redundantes




                                                                I NTRODUÇÃO À COMPILAÇÃO
Minimização de estados
Exemplo: resultado




                          1
                     C2       C1
                          0
                     1        0



                                   I NTRODUÇÃO À COMPILAÇÃO
Analisadores léxicos

       Autômato de reconhecimento de strings é o núcleo do
       programa que faz a análise léxica

   Analisador léxico
   O analisador léxico recebe o nome de um arquivo que contém
   uma seqüência de caracteres.
   Para cada token que é extraído desse arquivo, retorna a
   indicação de se o token é válido e qual é a sua classe.
   O analisador encerra a execução normalmente após a análise
   do último token.
   Caso algum token não seja reconhecido, o analisador indica a
   situação e passa ao próximo token, se possível; caso contrário,
   encerra a execução.


                                                       I NTRODUÇÃO À COMPILAÇÃO
Elementos do analisador léxico




  Estrutura que implementa o autômato deve contemplar
    1. O estado inicial para o autômato;
    2. Dado um estado qualquer, indicar se este é um estado
       final (condição de aceitação); e
    3. Dado um estado qualquer e um símbolo, a indicação de
       qual é o próximo estado.




                                                    I NTRODUÇÃO À COMPILAÇÃO
Algoritmo do analisador léxico


               Obter estado           Obter próximo
                 inicial                símbolo

                              [não há]              [há]

                       Estado atual                   Próximo
                         é final?                      estado

                   [sim]         [não]       [não há]       [há]


                token                  token não
             reconhecido              reconhecido




                                                                I NTRODUÇÃO À COMPILAÇÃO
Aspectos de implementação
Como representar os elementos do analisador em C++




       Símbolos variáveis do tipo char
        Estados variáveis do tipo int
                Estado inicial uma variável do tipo int
                Estados finais um conjunto de variáveis do tipo
                             int
                                  set<int>
     Transições uma seqüência de mapeamentos (um elemento
                por estado) de char (símbolo) para int (estado)
                    vector< map<char,int> >




                                                      I NTRODUÇÃO À COMPILAÇÃO
Geradores automáticos




     É possível implementar analisadores léxicos por esta
     abordagem
         Obter autômato a partir da expressão regular
         Implementar programa para cada autômato
     Este procedimento é sistemático — pode ser
     automatizado
         Papel dos geradores de analisadores léxicos




                                                        I NTRODUÇÃO À COMPILAÇÃO
Gerador de analisadores léxicos

  lex
  Programa do sistema Unix, foi o primeiro gerador de
  analisadores léxicos em C

        Há atualmente diversos programas similares que geram
        analisadores léxicos para diferentes linguagens
        Forma de operação similar para todos
            Arquivo de especificação indica padrões (expressões
            regulares) que devem ser reconhecidos e ações
            correspondentes
            O gerador de analisador léxico traduz essa especificação
            num programa que, ao reconhecer uma string no dado
            padrão, executa a ação
        Não tem por objetivo gerar uma aplicação completa, mas
        sim um programa a ser integrado numa aplicação maior
                                                          I NTRODUÇÃO À COMPILAÇÃO
Arquivo de especificação


  Primeira seção
  Definições e declarações para descrição de
  padrões ou para o programa gerado

  %%
  Segunda seção
  Padrões que devem ser reconhecidos e ações
  correspondentes

  %%
  Terceira seção
  Código complementar do usuário


                                        I NTRODUÇÃO À COMPILAÇÃO
Especificação dos padrões

     Utiliza uma extensão da forma de especificação de
     expressões regulares
     Além das construções primitivas para descrever uma
     expressão regular, pode utilizar
                   . qualquer caráter (exceto nova linha)
                  + uma ou mais ocorrências do padrão anterior
                  ? zero ou uma ocorrência do padrão anterior
             {n} n ocorrências do padrão anterior
            [· · · ] classe de caracteres
          [^ · · · ] classe negada
            ^. . . padrão no início da linha
            . . . $ padrão no fim da linha
       <<EOF>> fim do arquivo de entrada


                                                     I NTRODUÇÃO À COMPILAÇÃO
Definições e declarações
  Para a descrição de regras
     É possível associar um nome a um fragmento de padrão
     que aparece muitas vezes na seção de regras
       nome    fragmento_padrão
     O nome pode ser usado na especificação dos padrões na
     seção de regras, entre chaves
       ...{nome}...

  Para o código gerado
     Fragmentos de declarações e definições em C podem ser
     incluídos no programa gerado
     %{
     ...
     %}
                                                 I NTRODUÇÃO À COMPILAÇÃO
Ações




        Fragmentos de código C que serão executados quando o
        padrão for reconhecido no arquivo de entrada
        Especificados após o padrão
            Se usam mais de um comando C, ação deve estar entre
            chaves




                                                       I NTRODUÇÃO À COMPILAÇÃO
Integração com código

      Especificação é transformada numa função C (yylex())
          Varre os caracteres de um arquivo de entrada, yyin
          Retorna um valor inteiro, tipicamente associado ao
          reconhecimento de um padrão
          String reconhecida por um padrão é apontada pela variável
          yytext
          String não associada a padrão algum é ecoada para um
          arquivo de saída, yyout
          Valores iniciais de yyin e yyout: entrada e saída padrão,
          respectivamente
      Programador precisa fornecer o programa que invoca
      yylex
          Implementação básica é fornecida numa biblioteca do
          gerador de analisador léxico


                                                        I NTRODUÇÃO À COMPILAÇÃO
Exemplo de aplicação




     Objetivo Obter valores inteiros e apresentar o valor
              acumulado ao final
  Papel do analisador léxico Reconhecer as strings que
              representam valores inteiros e converter esses
              valores para inteiros
  O que o analisador não faz Acumular os valores




                                                      I NTRODUÇÃO À COMPILAÇÃO
Exemplo de código para a aplicação
Seções 1 e 2




    %{
    #include <iostream>
    using namespace std;
    #define END -1
    %}
    %%
    [0-9]+ return atoi(yytext);
    <<EOF>> return END;
    %%




                                     I NTRODUÇÃO À COMPILAÇÃO
Exemplo de código para a aplicação
Seção 3




    int main(int argc, char *argv[]) {
       int total=0, valor=0;

          do {
             valor = yylex();
             if (valor != END)
                total += valor;
          } while (valor != END);

          cout << "Total: " << total << endl;
    }



                                                I NTRODUÇÃO À COMPILAÇÃO
Geração e execução da aplicação



     Gerar o analisador léxico a partir do arquivo de
     especificação acumul.l
     > flex acumul.l
     Compilar o arquivo C gerado (lex.yy.c) e fazer a ligação
     com as rotinas auxiliares da biblioteca libfl.so; criar o
     arquivo executável acumul
     > g++ -o acumul lex.yy.c -lfl
     Executar a aplicação
     > ./acumul




                                                        I NTRODUÇÃO À COMPILAÇÃO
Sugestão de leitura (Web)




      Flex - a scanner generator (manual)
      http://www.gnu.org/software/flex/manual/
      flex: The Fast Lexical Analyzer (software)
      http://flex.sourceforge.net/




                                                  I NTRODUÇÃO À COMPILAÇÃO

Contenu connexe

Tendances

Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem PythonLuciano Ramalho
 
Funções Recursivas e Cálculo Lambda
Funções Recursivas e Cálculo LambdaFunções Recursivas e Cálculo Lambda
Funções Recursivas e Cálculo LambdaCarlos Campani
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test frameworkAbner Chih Yi Huang
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Victor Rentea
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven DevelopmentElias Nogueira
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsDenis L Presciliano
 
Robot Framework Introduction
Robot Framework IntroductionRobot Framework Introduction
Robot Framework Introductionlaurent bristiel
 
Java: Heranca e polimorfismo
Java: Heranca e polimorfismoJava: Heranca e polimorfismo
Java: Heranca e polimorfismoArthur Emanuel
 
Apostila Linguagens Formais e Autômatos (LFA)
Apostila Linguagens Formais e Autômatos (LFA)Apostila Linguagens Formais e Autômatos (LFA)
Apostila Linguagens Formais e Autômatos (LFA)Ricardo Terra
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsYura Nosenko
 
Speech and Language Processing
Speech and Language ProcessingSpeech and Language Processing
Speech and Language ProcessingVikalp Mahendra
 
Oscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simpleOscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simpleMartin Odersky
 
Context free langauges
Context free langaugesContext free langauges
Context free langaugessudhir sharma
 
Robot Framework with Python | Edureka
Robot Framework with Python | EdurekaRobot Framework with Python | Edureka
Robot Framework with Python | EdurekaEdureka!
 
Programando para web com python - Introdução a Python
Programando para web com python - Introdução a PythonProgramando para web com python - Introdução a Python
Programando para web com python - Introdução a PythonAlvaro Oliveira
 
Apostila Lógica de Programação
Apostila Lógica de ProgramaçãoApostila Lógica de Programação
Apostila Lógica de ProgramaçãoRicardo Terra
 
Pseudocódigo - Estrutura de Repetição (Lógica de Programação)
Pseudocódigo - Estrutura de Repetição (Lógica de Programação)Pseudocódigo - Estrutura de Repetição (Lógica de Programação)
Pseudocódigo - Estrutura de Repetição (Lógica de Programação)Gercélia Ramos
 

Tendances (20)

Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem Python
 
Funções Recursivas e Cálculo Lambda
Funções Recursivas e Cálculo LambdaFunções Recursivas e Cálculo Lambda
Funções Recursivas e Cálculo Lambda
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
 
WFST
WFSTWFST
WFST
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
Comandos e expressões
Comandos e expressõesComandos e expressões
Comandos e expressões
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e applets
 
Python 03 - Sintaxe
Python 03 - SintaxePython 03 - Sintaxe
Python 03 - Sintaxe
 
Robot Framework Introduction
Robot Framework IntroductionRobot Framework Introduction
Robot Framework Introduction
 
Java: Heranca e polimorfismo
Java: Heranca e polimorfismoJava: Heranca e polimorfismo
Java: Heranca e polimorfismo
 
Apostila Linguagens Formais e Autômatos (LFA)
Apostila Linguagens Formais e Autômatos (LFA)Apostila Linguagens Formais e Autômatos (LFA)
Apostila Linguagens Formais e Autômatos (LFA)
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applications
 
Speech and Language Processing
Speech and Language ProcessingSpeech and Language Processing
Speech and Language Processing
 
Oscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simpleOscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simple
 
Context free langauges
Context free langaugesContext free langauges
Context free langauges
 
Robot Framework with Python | Edureka
Robot Framework with Python | EdurekaRobot Framework with Python | Edureka
Robot Framework with Python | Edureka
 
Programando para web com python - Introdução a Python
Programando para web com python - Introdução a PythonProgramando para web com python - Introdução a Python
Programando para web com python - Introdução a Python
 
Apostila Lógica de Programação
Apostila Lógica de ProgramaçãoApostila Lógica de Programação
Apostila Lógica de Programação
 
Pseudocódigo - Estrutura de Repetição (Lógica de Programação)
Pseudocódigo - Estrutura de Repetição (Lógica de Programação)Pseudocódigo - Estrutura de Repetição (Lógica de Programação)
Pseudocódigo - Estrutura de Repetição (Lógica de Programação)
 

Plus de Ivan Ricarte

Aula catalogo de refatoracoes
Aula   catalogo de refatoracoesAula   catalogo de refatoracoes
Aula catalogo de refatoracoesIvan Ricarte
 
Testes de unidade em Java: JUnit
Testes de unidade em Java: JUnitTestes de unidade em Java: JUnit
Testes de unidade em Java: JUnitIvan Ricarte
 
Refatoração: Code smells
Refatoração: Code smellsRefatoração: Code smells
Refatoração: Code smellsIvan Ricarte
 
Aplicacoes web semantica saude
Aplicacoes web semantica saudeAplicacoes web semantica saude
Aplicacoes web semantica saudeIvan Ricarte
 
R - Software Estatistico
R - Software EstatisticoR - Software Estatistico
R - Software EstatisticoIvan Ricarte
 
Aula revisão de java e junit
Aula   revisão de java e junitAula   revisão de java e junit
Aula revisão de java e junitIvan Ricarte
 
Introducao a refatoracao
Introducao a refatoracaoIntroducao a refatoracao
Introducao a refatoracaoIvan Ricarte
 
C++: biblioteca padrão de templates - Parte 1
C++: biblioteca padrão de templates - Parte 1C++: biblioteca padrão de templates - Parte 1
C++: biblioteca padrão de templates - Parte 1Ivan Ricarte
 
Membros de classes C++
Membros de classes C++Membros de classes C++
Membros de classes C++Ivan Ricarte
 
Princípios da organização de código fonte C++
Princípios da organização de código fonte C++Princípios da organização de código fonte C++
Princípios da organização de código fonte C++Ivan Ricarte
 
Problemas no desenvolvimento do software
Problemas no desenvolvimento do softwareProblemas no desenvolvimento do software
Problemas no desenvolvimento do softwareIvan Ricarte
 
Aula 01 - As linguagens do software (2015)
Aula 01 - As linguagens do software (2015)Aula 01 - As linguagens do software (2015)
Aula 01 - As linguagens do software (2015)Ivan Ricarte
 
SI300 - Apoio a atividades práticas em C++ (01)
SI300 - Apoio a atividades práticas em C++ (01)SI300 - Apoio a atividades práticas em C++ (01)
SI300 - Apoio a atividades práticas em C++ (01)Ivan Ricarte
 
O Projeto Evid@SP - Disseminação de evidências a profissionais da saúde
O Projeto Evid@SP - Disseminação de evidências a profissionais da saúdeO Projeto Evid@SP - Disseminação de evidências a profissionais da saúde
O Projeto Evid@SP - Disseminação de evidências a profissionais da saúdeIvan Ricarte
 

Plus de Ivan Ricarte (20)

Aula catalogo de refatoracoes
Aula   catalogo de refatoracoesAula   catalogo de refatoracoes
Aula catalogo de refatoracoes
 
Testes de unidade em Java: JUnit
Testes de unidade em Java: JUnitTestes de unidade em Java: JUnit
Testes de unidade em Java: JUnit
 
Refatoração: Code smells
Refatoração: Code smellsRefatoração: Code smells
Refatoração: Code smells
 
Aplicacoes web semantica saude
Aplicacoes web semantica saudeAplicacoes web semantica saude
Aplicacoes web semantica saude
 
R - Software Estatistico
R - Software EstatisticoR - Software Estatistico
R - Software Estatistico
 
Aula UML e Java
Aula UML e JavaAula UML e Java
Aula UML e Java
 
Aula revisão de java e junit
Aula   revisão de java e junitAula   revisão de java e junit
Aula revisão de java e junit
 
Introducao a refatoracao
Introducao a refatoracaoIntroducao a refatoracao
Introducao a refatoracao
 
C++: biblioteca padrão de templates - Parte 1
C++: biblioteca padrão de templates - Parte 1C++: biblioteca padrão de templates - Parte 1
C++: biblioteca padrão de templates - Parte 1
 
c++ construtores
c++ construtoresc++ construtores
c++ construtores
 
Padroes
PadroesPadroes
Padroes
 
C++ Sobrecarga
C++ SobrecargaC++ Sobrecarga
C++ Sobrecarga
 
Membros de classes C++
Membros de classes C++Membros de classes C++
Membros de classes C++
 
UML e POO
UML e POOUML e POO
UML e POO
 
Antipadroes
AntipadroesAntipadroes
Antipadroes
 
Princípios da organização de código fonte C++
Princípios da organização de código fonte C++Princípios da organização de código fonte C++
Princípios da organização de código fonte C++
 
Problemas no desenvolvimento do software
Problemas no desenvolvimento do softwareProblemas no desenvolvimento do software
Problemas no desenvolvimento do software
 
Aula 01 - As linguagens do software (2015)
Aula 01 - As linguagens do software (2015)Aula 01 - As linguagens do software (2015)
Aula 01 - As linguagens do software (2015)
 
SI300 - Apoio a atividades práticas em C++ (01)
SI300 - Apoio a atividades práticas em C++ (01)SI300 - Apoio a atividades práticas em C++ (01)
SI300 - Apoio a atividades práticas em C++ (01)
 
O Projeto Evid@SP - Disseminação de evidências a profissionais da saúde
O Projeto Evid@SP - Disseminação de evidências a profissionais da saúdeO Projeto Evid@SP - Disseminação de evidências a profissionais da saúde
O Projeto Evid@SP - Disseminação de evidências a profissionais da saúde
 

Compiladores 3

  • 1. Análise léxica Ivan Ricarte 2008 I NTRODUÇÃO À COMPILAÇÃO
  • 2. Sumário Varredura de tokens Classificação de tokens Autômatos finitos Construção dos autômatos finitos Algoritmo de Thompson Conversão para autômato finito determinístico Minimização de estados Analisadores léxicos Visão conceitual Aspectos de implementação Geradores de analisadores léxicos I NTRODUÇÃO À COMPILAÇÃO
  • 3. Compiladores: análise léxica Reconhecimento, a partir dos caracteres, das palavras básicas do “vocabulário” do programa palavras-chaves da linguagem, operadores, identificadores, constantes elementos que podem ser adequadamente descritos por meio de gramáticas regulares I NTRODUÇÃO À COMPILAÇÃO
  • 4. Análise léxica Arquivo de análise Arquivo de ... síntese destino origem léxica análise Estruturas Gramáticas internas I NTRODUÇÃO À COMPILAÇÃO
  • 5. Gramática regular ou tipo 3 Revisão Apenas um símbolo não-terminal no lado esquerdo de cada produção Produções recursivas não apresentam auto-incorporação Produção recursiva: mesmo símbolo aparece do lado esquerdo e do lado direito Sem auto-incorporação: o símbolo do lado esquerdo aparece apenas no início ou no final da seqüência de símbolos do lado direito A linguagem regular descrita por uma gramática tipo 3 também pode ser descrita por meio de uma expressão regular I NTRODUÇÃO À COMPILAÇÃO
  • 6. Analisadores léxicos Programas que realizam a análise léxica Duas atividades básicas 1. Obter grupos de caracteres, a partir do arquivo com conteúdo a ser analisado, que constituem strings válidas em uma dada linguagem Cada grupo de caracteres é um token 2. Identificar qual é o tipo de token I NTRODUÇÃO À COMPILAÇÃO
  • 7. Varredura de tokens Leitura seqüencial dos caracteres da entrada Agrupamento de caracteres reconhecido como um token da entrada Utiliza as facilidades oferecidas pelas linguagens de programação para leitura de arquivos I NTRODUÇÃO À COMPILAÇÃO
  • 8. Varredura de tokens Recursos da linguagem C++ Definições no arquivo de cabeçalho <fstream> Leitura seqüencial de arquivos com a classe ifstream Métodos open, eof Cada token é um objeto da classe string (arquivo de cabeçalho <string>) Leitura de tokens separados por brancos com o operador » I NTRODUÇÃO À COMPILAÇÃO
  • 9. Varredura de tokens Exemplo básico #include <fstream> #include <string> ... ifstream arq; string token; ... arq.open("nome_arquivo"); ... while (! arq.eof() ) arq >> token; I NTRODUÇÃO À COMPILAÇÃO
  • 10. Classificação de tokens Token obtido precisa ser classificado É um identificador, uma palavra-reservada, uma constante? Extrair Classificar Entrada caracteres tokens string token tipo de token I NTRODUÇÃO À COMPILAÇÃO
  • 11. Autômatos finitos O núcleo do analisador léxico é uma implementação de um autômato finito máquina de estados finitos que aceita símbolos de uma sentença ao final da sentença, indica se ela é válida para a gramática ou não autômato é definido para cada conjunto de símbolos que deve ser reconhecido Cada tipo de token é definido por uma lista ou por uma gramática regular I NTRODUÇÃO À COMPILAÇÃO
  • 12. Autômato finito Definição formal Autômato é descrito por uma quíntupla M = (K , Σ, δ, s, F ) K conjunto (finito) de estados Σ alfabeto (finito) de entrada δ conjunto de transições s estado inicial, s ∈ K F conjunto de estados finais, F ⊆ K I NTRODUÇÃO À COMPILAÇÃO
  • 13. Autômato finito Representação gráfica Estados e transição si a sf I NTRODUÇÃO À COMPILAÇÃO
  • 14. Autômato finito Representação gráfica Estados inicial e finais s0 a s1 b s2 I NTRODUÇÃO À COMPILAÇÃO
  • 15. Autômato finito Representação tabular s0 s1 s2 a s1 — — b s2 — — Estado inicial: s0 Estados finais: s1 , s2 I NTRODUÇÃO À COMPILAÇÃO
  • 16. Tipos de autômatos Não determinísticos A partir de um estado: pode haver transições para dois ou mais estados diferentes pela ocorrência de um mesmo símbolo na entrada uma das transições é escolhida se ocorrer aquele símbolo pode haver transição para outro(s) estado(s) sem a ocorrência de nenhum símbolo transição pela string vazia I NTRODUÇÃO À COMPILAÇÃO
  • 17. Tipos de autômatos Determinísticos Transição sempre ocorre pela ocorrência de um símbolo de entrada Não há transições pela string vazia Não há alternativas distintas para a transição a partir de um dado estado e com um dado símbolo de entrada I NTRODUÇÃO À COMPILAÇÃO
  • 18. Construção dos autômatos finitos Há um procedimento sistemático para construir um autômato que reconhece strings de uma linguagem regular: Algoritmo de Thompson construção de um autômato finito não determinístico a partir de uma expressão regular Método da construção de subconjuntos conversão do autômato finito não determinístico para um autômato finito determinístico equivalente Minimização de estados combinação de estados redundantes do autômato para construir o menor autômato finito determinístico que reconhece as strings da linguagem regular especificada I NTRODUÇÃO À COMPILAÇÃO
  • 19. Algoritmo de Thompson Compõe um autômato finito não determinístico pela combinação de pequenos autômatos que reconhecem os elementos primitivos de uma expressão regular: Um símbolo do alfabeto da linguagem Concatenação de duas expressões regulares Alternativa de duas expressões regulares Repetição (zero ou mais vezes) de uma expressão regular I NTRODUÇÃO À COMPILAÇÃO
  • 20. Algoritmo de Thompson Autômato que reconhece um símbolo do alfabeto σ i f I NTRODUÇÃO À COMPILAÇÃO
  • 21. Algoritmo de Thompson Para as demais construções, dois autômatos serão combinados, um para a expressão regular R e outro para a expressão regular S: iR ..... fR iS ..... fS I NTRODUÇÃO À COMPILAÇÃO
  • 22. Algoritmo de Thompson Concatenação de duas expressões regulares Autômato que reconhece RS ε iR ..... fR iS ..... fS I NTRODUÇÃO À COMPILAÇÃO
  • 23. Algoritmo de Thompson Alternativa de duas expressões regulares Autômato que reconhece R|S iR ..... fR ε ε i f ε iS ..... fS ε I NTRODUÇÃO À COMPILAÇÃO
  • 24. Algoritmo de Thompson Repetição de uma expressão regular Autômato que reconhece R∗ ε ε iR fR ε i ..... f ε I NTRODUÇÃO À COMPILAÇÃO
  • 25. Algoritmo de Thompson Exemplo Autômato finito não-determinístico para reconhecer tokens da linguagem (0|1)*0: 1. Combinação de autômatos para reconhecer a concatenação de (0|1)* e 0 2. Para reconhecer (0|1)*, um autômato para reconhecer a repetição de 0|1 3. Para reconhecer 0|1, um autômato para reconhecer a alternativa entre 0 e 1 I NTRODUÇÃO À COMPILAÇÃO
  • 26. Algoritmo de Thompson Exemplo Autômato para (0|1)*0 ε 0 e3 e5 ε ε ε ε ε 0 e1 e2 e7 e8 e9 e10 ε ε 1 e4 e6 ε I NTRODUÇÃO À COMPILAÇÃO
  • 27. Conversão para autômato finito determinístico O método da construção de subconjuntos Procedimento para conversão de autômato finito não-determinístico (AFND) para autômato finito determinístico (AFD) que reconhece strings da mesma expressão regular Estados que podem ser alcançados a partir de outro por meio de transições pela string vazia são combinados num único estado Conceito de ε∗ de um subconjunto de estados do AFND I NTRODUÇÃO À COMPILAÇÃO
  • 28. O método da construção de subconjuntos 1. Obter estado inicial O estado inicial do AFD é definido como a ε∗ do conjunto contendo apenas o estado inicial do AFND 2. Obter novos estados e transições Cada estado obtido para o AFD é analisado para descobrir, para cada símbolo do alfabeto, suas transições de saída e novos estados que são gerados 3. Marcar estados finais Cada estado do AFD que contenha em seu subconjunto um estado final do AFND será um estado final do AFD I NTRODUÇÃO À COMPILAÇÃO
  • 29. Conversão para autômato finito determinístico Exemplo Conversão do autômato para (0|1)*0 ε 0 e3 e5 ε ε ε ε ε 0 e1 e2 e7 e8 e9 e10 ε ε 1 e4 e6 ε I NTRODUÇÃO À COMPILAÇÃO
  • 30. Conversão para autômato finito determinístico Exemplo Estado inicial ε∗ {e1} {e1, e2, e3, e4, e8, e9} : s0 Transições a partir do estado s0 s0 e1 e2 e3 e4 e8 e9 0 — — e5 — — e10 1 — — — e6 — — s0/0: ε∗ {e5, e10} = {e2, e3, e4, e5, e7, e8, e9, e10} (s1) (final) s0/1: ε∗ {e6} = {e2, e3, e4, e6, e7, e8, e9} (s2) Estados s1, s2 devem ser analisados da mesma forma, assim como novos estados que surjam desta análise I NTRODUÇÃO À COMPILAÇÃO
  • 31. Conversão para autômato finito determinístico Exemplo: resultado 0 s1 0 s0 1 0 1 s2 1 I NTRODUÇÃO À COMPILAÇÃO
  • 32. Minimização de estados Método da construção de subconjuntos gera autômato finito determinístico Possivelmente, com estados redundantes Procedimento de minimização permite obter autômato equivalente com menor número de estados Baseado no particionamento sucessivo do conjunto de estados I NTRODUÇÃO À COMPILAÇÃO
  • 33. Procedimento de minimização de estados 1. Particione o conjunto de estados do autômato Em um grupo, estados que são finais No outro grupo, todos os demais estados 2. Avalie transições para os estados de cada grupo Refinar particionamento: estados que têm transições para grupos diferentes têm que ser colocados em (novos) grupos diferentes 3. Combinar estados redundantes Quando todos os estados do grupo não mudam os grupos de destino quando transições são avaliadas, estados são redundantes — um único estado é suficiente para descrever esse comportamento I NTRODUÇÃO À COMPILAÇÃO
  • 34. Minimização de estados Exemplo Para o autômato obtido para a expressão (0|1)*0 1. Partição inicial P1 = {C1 , C2 }, com C1 = {s1} C2 = {s0, s2} 2. Para a partição C2 : s0 s2 0 C1 C1 1 C2 C2 ⇒ Estados s0, s2 são redundantes I NTRODUÇÃO À COMPILAÇÃO
  • 35. Minimização de estados Exemplo: resultado 1 C2 C1 0 1 0 I NTRODUÇÃO À COMPILAÇÃO
  • 36. Analisadores léxicos Autômato de reconhecimento de strings é o núcleo do programa que faz a análise léxica Analisador léxico O analisador léxico recebe o nome de um arquivo que contém uma seqüência de caracteres. Para cada token que é extraído desse arquivo, retorna a indicação de se o token é válido e qual é a sua classe. O analisador encerra a execução normalmente após a análise do último token. Caso algum token não seja reconhecido, o analisador indica a situação e passa ao próximo token, se possível; caso contrário, encerra a execução. I NTRODUÇÃO À COMPILAÇÃO
  • 37. Elementos do analisador léxico Estrutura que implementa o autômato deve contemplar 1. O estado inicial para o autômato; 2. Dado um estado qualquer, indicar se este é um estado final (condição de aceitação); e 3. Dado um estado qualquer e um símbolo, a indicação de qual é o próximo estado. I NTRODUÇÃO À COMPILAÇÃO
  • 38. Algoritmo do analisador léxico Obter estado Obter próximo inicial símbolo [não há] [há] Estado atual Próximo é final? estado [sim] [não] [não há] [há] token token não reconhecido reconhecido I NTRODUÇÃO À COMPILAÇÃO
  • 39. Aspectos de implementação Como representar os elementos do analisador em C++ Símbolos variáveis do tipo char Estados variáveis do tipo int Estado inicial uma variável do tipo int Estados finais um conjunto de variáveis do tipo int set<int> Transições uma seqüência de mapeamentos (um elemento por estado) de char (símbolo) para int (estado) vector< map<char,int> > I NTRODUÇÃO À COMPILAÇÃO
  • 40. Geradores automáticos É possível implementar analisadores léxicos por esta abordagem Obter autômato a partir da expressão regular Implementar programa para cada autômato Este procedimento é sistemático — pode ser automatizado Papel dos geradores de analisadores léxicos I NTRODUÇÃO À COMPILAÇÃO
  • 41. Gerador de analisadores léxicos lex Programa do sistema Unix, foi o primeiro gerador de analisadores léxicos em C Há atualmente diversos programas similares que geram analisadores léxicos para diferentes linguagens Forma de operação similar para todos Arquivo de especificação indica padrões (expressões regulares) que devem ser reconhecidos e ações correspondentes O gerador de analisador léxico traduz essa especificação num programa que, ao reconhecer uma string no dado padrão, executa a ação Não tem por objetivo gerar uma aplicação completa, mas sim um programa a ser integrado numa aplicação maior I NTRODUÇÃO À COMPILAÇÃO
  • 42. Arquivo de especificação Primeira seção Definições e declarações para descrição de padrões ou para o programa gerado %% Segunda seção Padrões que devem ser reconhecidos e ações correspondentes %% Terceira seção Código complementar do usuário I NTRODUÇÃO À COMPILAÇÃO
  • 43. Especificação dos padrões Utiliza uma extensão da forma de especificação de expressões regulares Além das construções primitivas para descrever uma expressão regular, pode utilizar . qualquer caráter (exceto nova linha) + uma ou mais ocorrências do padrão anterior ? zero ou uma ocorrência do padrão anterior {n} n ocorrências do padrão anterior [· · · ] classe de caracteres [^ · · · ] classe negada ^. . . padrão no início da linha . . . $ padrão no fim da linha <<EOF>> fim do arquivo de entrada I NTRODUÇÃO À COMPILAÇÃO
  • 44. Definições e declarações Para a descrição de regras É possível associar um nome a um fragmento de padrão que aparece muitas vezes na seção de regras nome fragmento_padrão O nome pode ser usado na especificação dos padrões na seção de regras, entre chaves ...{nome}... Para o código gerado Fragmentos de declarações e definições em C podem ser incluídos no programa gerado %{ ... %} I NTRODUÇÃO À COMPILAÇÃO
  • 45. Ações Fragmentos de código C que serão executados quando o padrão for reconhecido no arquivo de entrada Especificados após o padrão Se usam mais de um comando C, ação deve estar entre chaves I NTRODUÇÃO À COMPILAÇÃO
  • 46. Integração com código Especificação é transformada numa função C (yylex()) Varre os caracteres de um arquivo de entrada, yyin Retorna um valor inteiro, tipicamente associado ao reconhecimento de um padrão String reconhecida por um padrão é apontada pela variável yytext String não associada a padrão algum é ecoada para um arquivo de saída, yyout Valores iniciais de yyin e yyout: entrada e saída padrão, respectivamente Programador precisa fornecer o programa que invoca yylex Implementação básica é fornecida numa biblioteca do gerador de analisador léxico I NTRODUÇÃO À COMPILAÇÃO
  • 47. Exemplo de aplicação Objetivo Obter valores inteiros e apresentar o valor acumulado ao final Papel do analisador léxico Reconhecer as strings que representam valores inteiros e converter esses valores para inteiros O que o analisador não faz Acumular os valores I NTRODUÇÃO À COMPILAÇÃO
  • 48. Exemplo de código para a aplicação Seções 1 e 2 %{ #include <iostream> using namespace std; #define END -1 %} %% [0-9]+ return atoi(yytext); <<EOF>> return END; %% I NTRODUÇÃO À COMPILAÇÃO
  • 49. Exemplo de código para a aplicação Seção 3 int main(int argc, char *argv[]) { int total=0, valor=0; do { valor = yylex(); if (valor != END) total += valor; } while (valor != END); cout << "Total: " << total << endl; } I NTRODUÇÃO À COMPILAÇÃO
  • 50. Geração e execução da aplicação Gerar o analisador léxico a partir do arquivo de especificação acumul.l > flex acumul.l Compilar o arquivo C gerado (lex.yy.c) e fazer a ligação com as rotinas auxiliares da biblioteca libfl.so; criar o arquivo executável acumul > g++ -o acumul lex.yy.c -lfl Executar a aplicação > ./acumul I NTRODUÇÃO À COMPILAÇÃO
  • 51. Sugestão de leitura (Web) Flex - a scanner generator (manual) http://www.gnu.org/software/flex/manual/ flex: The Fast Lexical Analyzer (software) http://flex.sourceforge.net/ I NTRODUÇÃO À COMPILAÇÃO