1. Considere a gramática a seguir:
Construa o DFA de itens LR(0) para essa gramática. Ela é LR(0)? Se não for, indentifique o conflito. Construa a tabela de análise sintática shift-reduce LR(0) (se possível) ou SLR(1).
2. Considere a gramática a seguir:
Construa o DFA de itens LR(0) para essa gramática. Ela é LR(0)? Se não for, indentifique o conflito. Construa a tabela de análise sintática shift-reduce LR(0) (se possível) ou SLR(1).
3. Considere a gramática a seguir, para um fragmento de TINY:
a) Dê a sequência de ações (shift, reduce, accept) do analisador LR para o termo id := num ; id := id ()
.
b) Construa o DFA de itens LR(0) dessa gramática.
4. Um analisador LR(0) pode efetuar mais ou menos reduções que um analisador SLR(1) antes de declarar um erro? Justifique sua resposta.
5. Suponha que sejam removidas as especificações de associatividade e precedência dos operadores na especificação Jacc da gramática a seguir (tornando, portanto, a gramática ambígua). Quais seriam a associatividade e precedência dos operadores usando as regras de eliminação de ambiguidade de Jacc (shift em caso de conflito shift-reduce, reduce pela regra que vem primeiro em caso de conflito reduce-reduce)?
6. Acrescente os operadores ^
(exponenciação) e -
(menos unário) à especificação
de TINY. A precedência da exponenciação é maior do que a dos outros operadores
binários, e ela é associativa à direita. A precedência do menos unário é maior que a dos operadores
binários.
7. Considere a gramática a seguir para declarações simples em Pascal:
Escreva a especificação de uma AST Java para termos dessa gramática, e
implemente a verificação de tipos nessa AST. Assuma que já existe a
implementação de uma tabela de símbolos nos moldes da que foi vista em
sala (como uma classe TabSimb<T>
).
8. Considere o seguinte programa TINYPy:
Desenhe a pilha (e seu conteúdo) para esse programa no momento em que a linha comentada é executada, a partir do registro de ativação de main, e marque na pilha a localização de cada registro de ativação. Marque também para qual posição na pilha o registrador EBP está apontando.
9. Considere o seguinte programa TINYPy:
Desenhe a pilha (e seu conteúdo) para esse programa no momento em que a linha comentada é executada, a partir do registro de ativação de main, e marque na pilha a localização de cada registro de ativação. Marque também para qual posição na pilha o registrador EBP está apontando.
10. Acrescente um comando repeat-until
ao compilador TINYPy. A sintaxe é
O comportamento de um comando repeat é executar o bloco até que a expressão EXP
seja verdade. Faça todo o trabalho: modificação do analisador léxico para incluir as palavras chave repeat
e until
(lembre
que TINYPy não faz distinção entre maiúsculas e minúsculas), modificação do analisador sintático para gerar o nó apropriado, e implementação da classe Java que representa esse nó. A expressão do until
está no mesmo escopo do bloco de comandos.
11. O curto-circuito de expressões booleanas é um recurso
bastante comum em linguagens de programação. No curto circuito, uma
expressão e1 and e2
(e lógico) não precisa avaliar
e2
se e1
já for falsa, e uma expressão e1 or e2
(ou lógico) não precisa avaliar e2
se e1
já for
verdadeira.
Em um gerador de código para expressões booleanas, geralmente geramos
código que salta para determinado rótulo se a expressão for
falsa. Essa é a função do método void codigoSaltoF(Contexto c,
TabSimb<Endereco> escopo, String rotulo)
em Expressao
, abaixo.
Faça a geração de código para as expressões LogE
, correspondente a
and
, e LogOu
, correspondente a or
, implementando seus
métodos codigoSaltoF
. Assuma que a classe Contexto
é a mesma
que usamos para TINY.
12. As classes abaixo modelam o sistema de tipos de uma linguagem orientada a objetos simples, que não tem tipos primitivos, membros estáticos, interfaces ou herança múltipla:
O método subClasseDe
diz se uma classe é subclasse da outra,
direta ou indiretamente. Uma classe sempre é subclasse dela mesma.
Para verificar se um método está corretamente tipado, o sistema de
tipos deve criar uma tabela de símbolos para tipar o método,
associar o nome this
à classe do método, cada parâmetro a seu tipo, e
tipar cada expressão do corpo nesse ambiente. A última expressão do corpo deve
ter um tipo que é subclasse do tipo de retorno do método.
Já a classe Java abaixo modela o fragmento da AST da linguagem responsável pelas chamadas de métodos:
Para tipar uma chamada de método, o sistema de tipos primeiro tipa o objeto da chamada, para buscar os dados do método sendo chamado. Depois verifica se o número de argumentos bate com o número de parâmetros do método, e se cada argumento é subclasse do tipo de cada parâmetro. O tipo da chamada então é o tipo de retorno do método.
Um erro de tipagem pode ser sinalizado com uma RuntimeException
simples, contendo a mensagem “erro de tipagem”.
a) Implemente o método subClasseDe
.
b) Implemente o método tipoExp
de ChamadaMetodo
.
c) Implemente o método checaTipo
de Metodo
.
Última Atualização: 2016-05-18 10:58