Compiladores Análise Semântica Fabiano Baldo Análise Semântica é por vezes referenciada como análise sensível ao contexto porque lida com algumas semânticas simples tais como o uso de uma variável somente se ela já tiver sido declarada o que está além das capacidades de uma GLC. Geralmente, usa se a tabela de símbolos para realizar / computar a semântica. Mais formalmente, pode ser utilizada a tradução dirigida pela sintaxe com gramáticas de atributos. 2 A análise semântica envolve computação além da alcançada pelas GLC e algoritmos de análise sintática. A informação semântica está fortemente relacionada ao significado eventual ou semântico de um programa sendo compilado. Dado que ele acontece antes da execução do programa, ela é considerada uma análise semântica estática. A análise semântica em uma linguagem estaticamente tipada, como é o caso do C, envolve a construção de uma tabela de símbolos para manter o significado dos identificadores e realizar a inferência de tipo para propagar estes significados e tipos de checagem para expressões e declarações. 3 4 Que tipo de significado está envolvido e que excede a capacidade das GLCs: X foi declarado apenas uma vez? X foi declarado antes do seu primeiro uso? X foi definido antes do seu primeiro uso? X é um escalar, um array, uma função, ou uma classe? X é declarado mais nunca utilizado? A que declaração X se refere? Os tipos de uma expressão são compatíveis? As dimensões casam com o declarado? A análise semântica pode ser dividida em duas categorias: Para estabelecer a corretude de um programa a fim de garantir sua execução apropriada. Isto varia de acordo com a rigidez iid semântica da linguagem em questão. Linguagens com orientação dinâmica, como LISP, pode não exigir uma análise um análise semântica estática. Para melhorar a eficiência da execução do programa. Isto é freqüentemente relacionado a otimização de código. 5 6 1
Análise Semântica Estática Atributos e Gramática de Atributos Envolve tanto a descrição quando a implementação das análises utilizando algoritmos apropriados. Atributos e gramáticas de atributos pode ser utilizados para escrever regras semânticas. Gramáticas de atributos pode ser úteis para linguagens que obedecem o princípio da semântica dirigida pela sintaxe (o conteúdo semântico de um programa está intimamente relacionado com sua sintaxe). Linguagens de programação modernas costumam seguir esta princípio. A semântica costuma não ser formalmente especificada pelos projetistas da linguagem, deixando para o construtor do compilador a tarefa de identificar os atributos da gramática 7 Um atributo é uma propriedade da linguagem de programação que precisa ser verificada. Alguns exemplos de atributos são: Tipo de dados de uma variável; Valor de uma expressão; Localização de uma variável em memória; Código objeto de um procedimento; Quantidade de dígitos significativos em um número. 8 Gramática de Atributos Gramática de Atributos Regras semânticas expressam como a computação dos atributos se relaciona com as regras gramaticais da linguagem. Este conjunto de atributos e regras semânticas é denominado gramática de atributos. A construção de uma gramática de atributos é consideravelmente complicada. Portanto, uma base muito melhor para a expressão das computações semânticas é a sintaxe abstrata, representada por árvore de sintaxe abstrata. Os atributos pode ser fixados antes do processo de compilação (ou da construção do compilador). Os atributos pode ser também determinados somente durante a execução do programa. O processo de computar um atributo e associar seu valor com a construção da ling. recebe o nome de amarração do atributo. O momento em que ocorre a amarração de um atributo é denominado tempo de amarração. Atributos amarrados antes da execução são ditos estáticos; Atributos amarrados durante a execução são ditos dinâmicos; 9 10 Gramática de Atributos Se X for um símbolo gramatical e a for um atributo de X, escrevemos X.a para o valor de a associado a X. Dada uma coleção de atributos a 1,...,a k, o princípio da semântica dirigida pela sintaxe implica que para cada regra gramatical X 0 X 1 X 2...X n, os valores dos atributos X i.a j de cada símbolo X i são relacionados aos valores dos atributos dos outros símbolos da regra. Cada relação é especificada por uma regra semântica ou equação de atributos: Exemplo 1: Gramática de Atributos O atributo mais significativo de um número é seu valor, e recebe o nome val. Sua gramática de atributos é especificada como segue: 11 12 2
Exemplo 1: Árvore de Derivação Árvore de derivação para o inteiro 345 Exemplo 2: Gramática de Atributos para expressões O atributo de exp, term e factor é seu valor numérico val. Sua gramática ái de atributos é especificada como segue: 13 14 Exemplo 2: Gramática de Atributos para expressões Note que o + na regra gramatical exp 1 exp 2 + term representa o token no programa fonte, e o + na regra semântica representa a operação aritmética a ser executada em tempo de execução. Não há equações com number.val à esquerda, pois seu valor é calculado anteriormente, na fase sintática. Exemplo 2: Árvore de Derivação Árvore de derivação para a expressão (34 3)*42 15 16 Exemplo 3: Gramática de Atributos para declarações de variáveis Exemplo 3: Árvore de Derivação Árvore de derivação para a declaração float x, y Para representar o tipo dos dados é adicionado um atributo a chamado dtype. 17 18 3
Exemplo 4: Gramática de Atributos para números com base Exemplo 4: Gramática de Atributos para números com base Neste caso number e digit necessitam de um novo atributo, chamado base. 19 20 Exemplo 4: Árvore de Derivação Árvore de derivação para o número 345o Algoritmos para Computação de Atributos De que forma um compilador pode computar gramáticas de atributos? Isto leva a transformar a equação de atributos em regras de computação. Considere a seguinte equação de atributos: 21 22 Algoritmos para Computação de Atributos Ela é vista como uma atribuição do valor da expressão funcional à direita ao atributo X i.a j, onde todos os atributos do lado direito devem ser conhecidos. Alguns do atributos do lado direito podem depender dos valores de outros atributos antes de serem computados. A solução desse problema de dependência está em encontrar uma ordem para a avaliação que garanta a disponibilidade dos valores a cada computação de atributo Essa dependência pode ser resolvida através da construção de um grafo de dependência. Grafo de Dependência e Ordem de Avaliação Dada uma gramática de atributos, cada regra gramatical tem um grafo de dependência associado. Esse grafo tem um nó rotulado para cada atributo X i.a j de cada símbolo da regra gramatical, e para cada equação de atributos. Associada à regra gramatical existe um arco de cada nó X m.a k à direita do nó X i.a j 23 24 4
para Números Para a regra gramatical e sua equação de atributos: para Números O grafo de dependência para a cadeia 345 é: O grafo de dependência é: Para a regra gramatical e sua equação de atributos: O grafo de dependência é: 25 26 Na gramática para declaração, a regra Tem a seguinte equação de atributos e grafo de dependência De maneira similar, a regra tem como grafo de dependência A regra tem a seguinte grafo de dependência: Dado que decl não está envolvida no grafo de dependência, nãofica claro qualregra gramatical está associada com ela. Por este motivo o grafo de dependência é desenhado sobre a árvore de análise sintática correspondente. As regras e tem grafos de dependências triviais. 27 Isso deixa mais claro a qual regra gramatical a dependência está associada. 28 O grafo de dependência sobre a árvore de análise sintática para pode ser escrita: O grafo de dependência sobre a árvore de análise sintática para float x,y 29 30 5
para Números com Base O grafo de dependência para a regra gramatical para Números com Base O grafo de dependência para a regra gramatical é: é: A dependência é criada por O grafo mostra a dependência de e 31 onde depende de 32 para Números com Base O grafo de dependência para a regra é: para 345o A dependência é criada por 33 34 Atributos Sintetizados e Herdados A avaliação de atributos baseada em regras depende de um percurso explícito ou implícito da árvore sintática. Diversos tipos de percursos têm poder diferente em termos dos tipos de dependências de atributos que podem ser manipulados. Para estudar estas diferenças, é necessário classificar os atributos por tipos de dependências. Atributos Sintetizados Um atributo é sintetizado se todas as suas dependências apontarem de filho para pai na árvore de análise sintática. Portanto, um atributo a é sintetizado se, dada uma regra gramatical A X 1 X 2...X n, a única equação de atributos associada com um a à esquerda tiver a forma: A.a=f(X 1.a 1,...,X 1.a k,...,x n.a 1,...,X n.a k ) Uma gramática de atributos em que todos os atributos são sintetizados é denominada S atribuída. 35 36 6
Gramática S atribuída Os valores de atributos de uma gramática S atribuída podem ser computados por um único percurso ascendente, ou em pós ordem, da árvore. Pseudocódigo para um avaliador recursivo em pósordem: Atributos Herdados Um atributo que não é sintetizado é denominado atributo herdado. Existem três tipos de herança de atributos: a) Herança de pai para filho; b) Herança entre irmãos; c) Herança entre irmãos através de ponteiros entre irmãos. 37 a) b) c) 38 Atributos Herdados Gramática L atribuída Os valores dos atributos herdados podem ser computados por um percurso em pré ordem e inordem para percorrer a árvore de análise sintática. Uma gramática de atributos para os atributos a 1,...,a k é L atribuída se, para cada atributo herdado a j e cada regra gramatical X 0 X 1 X 2...X n, as equações associadas a a j forem todas da forma: X i.a j =f ij (X 0.a 1,...,X 0.a k, X 1.a 1,...,X 1.a k,..., X i 1.a 1,...,X i 1.a k )) Ou seja, se o valor de a j em X i puder apenas depender dos atributos dos símbolos X 0,...,X i 1 que ocorram à esquerda de X i na regra gramatical. 39 40 Considerações S atribuída é um caso especial de L atribuída. Dada uma gramática L atribuída em que os atributos herdados não dependem dos atributos sintetizados, um analisador sintático descendente recursivo pode avaliar todos os atributos como segue: Transformação dos atributos herdados em parâmetros; Transformação dos atributos sintetizados em valores de retorno. 41 7