1. Anotações na árvore sintática abstrata: o contexto
A análise léxica e sintática executam processamento livre de contexto.
Outras informações e verificações são efetuadas na fase de análise
semântica ou de contexto.
Os dados necessários para a análise semântica são armazenados sob a
forma de atributos na AST (poderiam estar na tabela de símbolos ou
em variáveis locais do analisador).
A análise semântica calcula os atributos e verifica as condições de
contexto. Pode ser escrit a à mão ou ser gerada através de uma
especificação (gramática de atributos)
Gramática de atributos baseia -se no paradigma de programação de
dataflow (os valores podem ser calculados em ordem arbitrária).
GLC usada na construção do analisador é estendida com dois
recursos:
1. Para cada simbolo gramatical S, terminal ou não terminal, são
especificados zero ou mais atributos, com nome e tipo (são chamados
atributos formais). Os atributos reais são alocados em cada nó criado
para S na AST. Os atributos guardam informações sobre a semântica
associada a esse nó. Assim, todos os nós na AST do simbolo S
possuem os mesmos atributos formais mas atributos reais diferentes.
2. Para cada regra de produção N -> M1, ..., Mn, está associado um
conjunto de regras computacionais (regras de avaliação de atributos),
que verificam condições de contexto e emitem mensagens de
advertência e erro. As regras estão associadas às produções e não aos
seus não-terminais. Os atributos devem atender ao seguinte requisito:
Cada símbolo gramatical possui um conjunto de atr ibutos associados
divididos em dois grupos:
w Atributos sintetizados: cujo valor calculado em função dos filhos
w Atributos herdados: cujo valor é herdado do nó pai e/ou irmãos
2. O avaliador de atributos avalia as regras semânticas em determinada
ordem para calcular todos os valores de uma AST, sem utilizar um
valor não tenha sido previamente calculado. Execução similar a uma
máquina de dataflow: um cálculo só é executado quando todos os
valores que ele depende são determinados. Os valores inicialmente
disponíveis advém dos atributos sintetizados, vindos do próprio texto
do programa. O avaliador continua a propagar os valores até
completar o preenchimento dos atributos da AST (caso não haja
ciclos).
Exemplo figura – atributos herdados a direita, sintetizados a
esquerda. Tabela de simbolos pode ser um atributo herdado
Segundo a teoria inicial de Knuth (1968), o simbolo inicial não tem
nenhum atributo herdado, e os terminais não possuem nenhum
atributo. Simbolos terminais auxiliam em geral a sintaxe apenas, ent ão
não teriam nenhuma semäntica associada. Exceções interessantes: o
simbolo inicial pode ter atributos para geraçäo de codigo espec ífica
para uma maquina. Ex: processador = pentium VI, 386, Sparc.
Problema: Como avaliar os atributos ?
Possibilidade de loop infinito nos cálculos. Existem algoritmos para
detecção de loops em gramáticas de atributos.
Grafo de dependência
Cada nó em uma árvore sintática corresponde a uma regra de
produção N -> M1, ..., Mn; identificado com o simbolo N e contém os
atributos de N e n ponteiros para nós. Fluxo de dados para nós.
Representados por retangulos à esquerda (herdados) e à direita
(sintetizados) do simbolo na arvore.
Nome correto seria grafo de fluxo de dados e não grafo de
dependencia, pois representa o fluxo e não a dependencia da
informacao (sentido inverso). Se os dados fluem da variavel a para b
entao b depende de a.
3. Exemplo : const definition: const pi = 3,14 (const id = expr;)
Utiliza-se o algoritmo de classificação topológica para percorrer o
grafo de dependencia e ordenar a execução das ações semanticas.
Dessa forma, garante-se que dada uma regra semantica b = f (c1, ...,
cn), todos os atributos de ci estão disponiveis (calculados) antes da
aplicação da função f.
Cálculo de atributos
O avaliador de atributos deve :
1. Criar a AST
2. Alocar espaço para os atributos da árvore
3. Anotar a arvore preenchendo os atributos dos terminais na arvore
com valores derivados das representacoes dos terminais
4. Executar regras de avaliacao nos nós para atribuir valores a
atributos ate que nenhum novo valor de atributo seja usado antes de
estar disponivel
5. Detectar quando não for possivel faze-lo
Implementacao do avaliador de atributos – utilizar uma maquina
dataflow.
Metodo Simples: visitar todos os nós do grafo de flu xo de dados,
executando todas as atribuiçoes possiveis em cada nó quando o
visitarmos e repetir esse processo ate que todos os atributos
sintetizados da raiz tenham recebido um valor.
Ordem calculada dinamicamente, ordem em que os atributos são
avaliados é determinada dinamicamente.
Tenta executar todas as regras para um nó, percorre os filhos, e ao
retornar deles, tenta mais uma vez executar todas as atribuicoes. As
atribuicoes antes da visita propagam os atributos herdados de cima
para baixo e as atribuicoes após a visita colhem os atributos
sintetizados dos filhos e os propagam para cima.
Outro método que mostra um limite superior sobre o tempo necessario
para realizar a avaliacao de atributos. Vincula-se todos os atributos da
4. arvore de analise em uma lista encadeada, classificamos essa lista
topologicamente (ordem parcial) de acordo com as dependencias de
dados e executamos as atribuicoes na ordem classificada. Com n
atribuicoes e d dependencias de dados, classifica las topologicamente
com um algoritmo recursivo custa O (n+d), as atribuicoes
subsequentes custarao O(n). A classificacao topologica poderá revelar
quaisquer ciclos.
Deteccao dinamica de ciclos – verifica se o algoritmo já passou do
numero máximo (conhecido) de rodadas.
Alocacao de atributos: listas podem aumentar o tempo de busca e
atualizacao, e atributos são em geral copiados. Pode-se usar uma
pilha.
Modificacao no algoritmo de construcao da AST. AST vira um GDA
(grafo dirigido acíclico) para subexpressoes comuns – Aho 125.
Restricoes as gramaticas de atributos:
1. Gramaticas L-atribuidas. Um atributo herdado de um filho de
um não terminal N pode depender apenas de atributos sintetizados de
filhos a esquerda dele na regra de producao para N e dos atributos
herdados do proprio N e as gramat icas S-atribuidas que não podem ter
absolutamente atributos herdados.
Top down constroi os nos da AST da esq para a direita primeiro o no
pai e em seguida os filhos. Na bottom up, primeiro os filhos depois o
pai.
Regras semânticas estabelecem dependências entre os atributos
representados em um grafo
O grafo determina a ordem de avaliação das regras
A avaliação das regras semânticas gera os valores dos atributos
5. A árvore gramatical que mostra os valores dos atributos é chamada de
árvore gramatical anotada
Cada produção A → α está associado a um conjunto de regras
semânticas na forma:
B := f(c1, c2, ..., ck)
Onde f é uma função que vigora em uma das seguintes situações:
w B é um atributo sintetizado de A e c 1, c2, ..., ck são atributos
pertencentes aos símbolos gramaticais da produção
w B é um atributo herdado, pertencente a um dos símbolos
gramaticais do lado direito da produção e c1, c2, ..., ck são atributos
pertencentes aos símbolos gramaticais da produção
Exemplo:
Produção Regra Semântica
L→En Imprimir(E.val)
E → E1+T E.val:= E1.val + T.val
E→T E.val:= T.val
T → T1 * F T.val:= T1.val * F.val
T →F T.val:= F.val
F → (E) F.val:= E.val
F → dígito F.val:= dígito.lexval
Na tradução dirigida pela sintaxe assume-se que os terminais tenham
somente atributos sintetizados na medida em que as definições não
providenciem quaisquer regras semânt icas
Os valores para os atributos dos terminais costumam ser fornecidos
pelo léxico:
F → dígito F.val= dígito.lexval
Atributos sintetizados são bastante usados na prática
Uma definição dirigida pela sintaxe somente com atributos
sintetizados é chamada de definição S-atribuída
Os atributos costumam ser avaliados de baixo para cima, das folhas
para a raiz
6. Atributos herdados são convenientes para expressar construções de
LPs em relação ao contexto em que aparecem
Bastante útil na verificação de tipos
Controlar se um identificador aparece do lado esquerdo (endereço) ou
direito (valor) de uma atribuição
Produção Regra Semântica
D→TL L.in:= T.tipo
T → int T.tipo:= inteiro
T → float T.tipo:= real
L → L1, id L1.in:= L.in
incluir_tipo(id.entrada, L.in)
L → id incluir_tipo(id.entrada, L.in)
Um Grafo de Dependências é construído para uma árvore gramatical
Ele mostra as interdependências entre os atributos dos nós da árvore
gramatical
Define uma ordem de avaliação das regras semânticas em uma
tradução dirigida pela sintaxe
Algoritmo
para cada nó n na árvore gramatical faça
para cada atributo a do símbolo gramatical em n faça
gere um nó para a no grafo de dependências
fim para
fim para
para cada nó n na árvore gramatical faça
para cada regra semântica b:= f(c 1, c2, ...,ck) faça
para i= 1 até k faça
gere uma aresta a partir do nó ci até o nó b
fim para
fim para
fim para
7. Uma classificação topológica é uma ordenação dos nós de um grafo
do primeiro ao último nó ordenado
Se mi → mj é uma aresta, então mi aparece antes de m j na classificação
topológica
Os atributos c1, ..., c k dos quais uma regra semântica dependa b:= f(c1,
..., ck ) devem estar disponíveis antes de f ser avaliada
Métodos propostos para avaliar regras semânticas
w Método das árvores gramaticais : gera a ordem de avaliação
automaticamente em tempo de compilação. Falha se existem ciclos no
grafo
w Método baseado em regras : gera a ordem de avaliação
automaticamente em tempo de construção do compilador.
w Método alienado: uma ordem de avaliação é escolhida sem
considerar as regras semânticas. Restringe a classe de definições
dirigidas a sintaxe que podem ser aplicadas.
Crie uma ordenação topológica baseada em regras para a cadeia
float x, y