Ações semânticas para gramática ZooG1 – Compiladores 2006-1 (De Lucca)
AÇÃO [0]
Antes de tudo, a parte semântica deve ser inicializada. Abaixo, a lista de elementos
necessários para a execução das ações semânticas.
Inicializar variáveis auxiliares e contadores
tipo: valores possívels: int/bool/caracter/flut/nada
categoria: variavel/vetor/procedimento/função/constante/parâmetro/nomeprograma
deslocamento: controla a posição da declaração de cada identificador. Cada variável
simples incrementará o deslocamento de 1 (valor inicial = 3)
deslocString: controla a posição da declaração de strings. Cada string incrementará o
deslocString de 1. O deslocString fará papel de apontador na tabela de Strings
contaParâmetros: contador de parâmetros declarados
escopo: controla o escopo de declaração dos identificadores
geradoRET: controla se foi ou não gerada a instrução RET em uma função
TI: tabela de identificadores (ou tabela de símbolos)
Tabela de Strings: vetor que conterá todos os strings do programa, sequencialmente,
indexados pelo deslocString.
EG – endereço de geração. EG deve conter o endereço onde será gerada a próxima
instrução. Valor inicial de EG-> 0 (se considerar que a área de geração é um vetor
cujo primeiro elemento tem índice 0). Sempre que se gera uma instrução, o EG é
incrementado
Área de geração de código: pode-se imaginar um vetor de triplas (Operador,
operando1, operando2), indexado sequencialmente e controlado por EG
diversas pilhas para solução de referências futuras
pilhas de desvios para Principal
pilha de solução de enquanto (pilhaEnquanto)
pilha de solução de para (pilhaPara)
pilha de solução de faça-enquanto (pilhaFaça)
pilhas de solução de se-senão (pilhaSE)
outras que se fizerem necessárias
pilhaOP: pilha de apoio à geração de código de operações aritméticas e lógicas
[1] <ZooG> ::= #0 <import> programa ID #1 "{" <corpo> "}" #2 ;
Incluir ID na TI com atributos adequados (categoria=nome programa, escopo=0)
[2] <ZooG> ::= #0 <import> programa ID #1 "{" <corpo> "}" #2 ;
Verificar se há pendências nas pilhas (-> ERRO1)
[3] <import> ::= importar ID #3 ";" <import>
OBS: Não será feita importação de arquivos neste semestre
<tipo> ::= int #7 | bool #8 | caracter #9 | flutuante
<tiponada> ::= <tipo> | nada #11 ;
[7] tipo = int
[8] tipo = bool
[9] tipo = caracter
[10] tipo = flutuante
1
#10
;
Sempre que ocorrer um ERRO, deve ser cancelada a geração de código. A análise pode continuar, mas
qualquer que seja o código gerado não deverá ser considerado correto.
7
[11] tipo = nada
[12] <declara> ::= <tiponada> ID #12 <declrotvar>
se existe ID na TI no mesmo escopo
então ERRO(“Já declarado”)
senão
reúne mais informações para incluir na TI (ainda não sabe se categoria é variável ou
função ou vetor) – dados disponíveis: ID, escopo e tipo
[13] <declrotvar> ::= ';' #13 (é declaração de variável)
se tipo =int
gera instrução AMEM 1
incluir na TI os dados reunidos em #11, completando categoria=”variável simples” e
end.relativo=deslocamento
deslocamento++
senão
se tipo =flutuante ou caracter ou bool
NÃO FAZ NADA – excluídos da linguagem neste semestre
senão o tipo será “nada”: ERRO("'Nada' não permitido em declaração de variável")
[14] <declrotvar> ::= '=' #14 <inicial> #15 ';'
idem ação #13
[15] <declrotvar> ::= #14 '=' <inicial> #15 ';'
Gerar PUSHK (valor da inicialização) (o valor da inicialização virá da ação #16)
Gerar POP 0, deslocamento, utilizando o end.relativo da última variável incluída na TI
(que é igual ao valor atual da variável deslocamento, menos 1)
<inicial> ::= cteint #16 | cteflut #17 | litcar #18
[16] se tipo <> int : ERRO(Tipos incompatíveis)
senão salva valor da cteint em variável temporária para usar em #15, em #28 ou em #41
[17] FLUTUANTE retirado da linguagem neste semestre. Gerar ERRO ("Flutuante não
suportado").
[18] idem #17 para caracter
[19] <inicial>::= ID #19 ;
RETIRADA A POSSIBILIDADE DE INICIALIZAÇÂO COM CONSTANTE NESTE
SEMESTRE.
Gerar ERRO(“Constante não suportada neste ponto”)
[21] <declrotvar> ::= '[' #21 cteint #22 ']' ';'
[22] <declrotvar> ::= '[' #21 cteint #22 ']' ';'
OBS: SINTAXE E SEMÂNTICA DE VETOR DEFINIDAS POR VOCÊS. ISTO AQUI É SÓ
UM EXEMPLO...
[23]<declrotvar> ::= '(' #23 <listaargs> #24 ')' #51 <bloco> #52
se tipo==nada
categoria = procedimento
se tipo== int ou caracter ou bool
categoria = função
Gerar DSVS ? , empilhando o endereço onde foi gerada esta instrução para resolver ao
final da sub-rotina (empilhe na pilha de desvios para Principal)
incluir na TI os dados reunidos em #12, completando categoria (definida acima) e
7
endereço (posição do início de geração de código da sub-rotina = endereço seguinte
ao DSVS recém-gerado)
escopo++
contaParametros = 0
guardar posição onde a tupla foi incluída na TI para, no futuro, retornar e colocar o nº
de parâmetros (será feito em #24)
geradoRET = falso (será verificado, no final do bloco, se foi gerado o return)
[24]<declrotvar> ::= #23 '(' <listaargs> #24 ')' #51 <bloco> #52
atualizar entrada na TI correspondente à subrotina (cuja posição foi salva), com o nº de
parâmetros
atualizar entradas dos parâmetros com deslocamentos negativos
exemplo: nada xyz ( int a, bool b, int c)
deslocamento de a = -3
deslocamento de b = -2
deslocamento de c = -1
[25] <listaargs> ::= <tipo> ID #25 <repargs>
se tipo == nada, bool, caracter ou flutuante: ERRO(Estes tipos não são admitidos como
parâmetros – NESTE SEMESTRE)
senão
se a ID já existe na TI no mesmo escopo: ERRO(Já declarado)
senão
inserir na TI: ID, categoria=parâmetro, tipo, escopo
contaParâmetros++
[26] <declara> ::= final #26 <tipo> ID #27 '=' <inicial> #28 ';'
[27] <declara> ::= final #26 <tipo> ID #27 '=' <inicial> #28 ';'
[28] <declara> ::= final #26 <tipo> ID #27 '=' <inicial> #28 ';'
NÃO UTILIZADO NESTE SEMESTRE (não haverá geração de código para constantes)
[29] <declara> ::= string ID #29 '=' litstring #30 ';'
se a ID já existe na TI no mesmo escopo: ERRO(Já declarado)
senão incluir na TI: ID, categoria=variável, tipo=string, escopo, deslocString
[30] <declara> ::= string ID #29 '=' litstring #30 ';'
incluir litstring na Tab de strings, na posição definida por deslocString
deslocString++
[31] <corpo> ::= principal #31 <bloco> #53 <corpo>
resolver desvios pendentes gerados em #23 (pilha de desvios para Principal), usando
para isso o endereço que corresponderá à primeira instrução de 'Principal'.
Comando SE
[32] <cmdse> ::= se '(' <cond> ')' #32 <bloco> <cmdse2> #34
Empilhar EG na pilhaSE (EG é onde o DSVF abaixo será gerado)
Gerar DSVF ? (o endereço de destino pendente será resolvido em #33 ou #34)
[33] <cmdse2> ::= senão #33 <bloco>
Gerar DSVS ? (o endereço de destino pendente será resolvido em #34)
Resolver referência pendente (pendência está situada na posição indicada pelo
endereço que estiver no topo da pilhaIF) usando EG atual. Desempilhar o endereço da
pilhaIF
Empilhar EG-1 (referente ao DSVS gerado acima) na pilhaIF
7
[34] <cmdse> ::= se '(' <cond> ')' #32 <bloco> <cmdse2> #34
Resolver referência pendente (cujo endereço está no topo da pilhaIF) usando EG e
desempilhar (pode ter sido empilhado em #32 ou em #33)
Comando FAÇA:
[35] <cmdfaca> ::= faça #35 <bloco> enquanto '(' <cond> ')' #36
Empilhar EG na pilhaFaça
[36] <cmdfaca> ::= faça #35 <bloco> enquanto '(' <cond> ')' #36
Gerar (DSVT endereço) usando o valor que estiver no topo da pilhaEnquanto como
endereço e desempilhar
Comando ENQUANTO:
[37] <cmdeqto> ::= enquanto #37 '(' <cond> #38 ')' <bloco> #39
Empilhar EG na pilhaEnquanto
[38] <cmdeqto> ::= enquanto #37 '(' <cond> #38 ')' <bloco> #39
Empilhar EG na pilhaEnquanto (endereço onde o DSVF abaixo será gerado)
Gerar DSVF ? (endereço ficará pendente para resolução futura – na ação #39)
[39] <cmdeqto> ::= enquanto #37 '(' <cond> #38 ')' <bloco> #39
Resolver referência pendente do topo da pilhaEnquanto usando EG+1 e desempilhar
Gerar (DSVS endereço), usando o novo topo da pilhaEnquanto como endereço
Comando FOR:
[40] <cmdpara> ::= para "(" ID #40 "=" <inicial> #41 ";" <cond>
#42 ";" #43 <expr> #44 ")" <bloco> #45 ;
As ações para o COMANDO PARA não serão utilizadas neste semestre. As posições de
ações definidas acima são apenas sugestões.
[46] <cmdatrib> ::= ID #46 <contatrib>
Se ID não está na TI:
ERRO(Não declarado: Não se pode chamar PROCEDIMENTO que não tenha sido
declarado anteriormente)
senão
Se ID está na TI como função/nome de prog/const: ERRO(deve ser variável, parâmetro
ou procedimento)
senão Recuperar os dados da TI correspondentes ao ID e salvar em tupla temporária
[47] <contatrib> ::= '=' <cond> #47
Gerar (POP dif.nível, desloc) usando informações da tupla temporária salva em #46
[48] <contatrib> ::= '(' #48 <listaparam> #49 ')'
Se ID não é procedimento (ver dados da tupla temporária): ERRO(Esperava-se
procedimento)
senão Zerar contaParam
[49] <contatrib> ::= '(' #48 <listaparam> #49 ')'
Se contaParam <> nº parâmetros da tupla temporária salva em [46]: ERRO(Nº de
parâmetros incorreto)
senão Gerar (CALL base, end) usando informações da tupla temporária salva em #46
base = escopo atual – escopo de declaração da sub-rotina (ver tupla)
end = endereço do procedimento (ver tupla)
[50] <listaparam> ::= <expr> #50 <rlista>
7
<rlista> ::= <expr> #50 <rlista>
Incrementar contaParam
[51] <declrotvar> ::= '(' #23 <listaargs> #24 ')' #51 <bloco> #52
Gerar AMEM 0,3 <<reservando espaço para o registro de ativação
[52] <declrotvar> ::= '(' #23 <listaargs> #24 ')' #51 <bloco> #52
Decrementar escopo
Se categoria é função e se variável geradoRET=false: ERRO(falta return)
Gerar (RET K) (K é o nº de parâmetros do procedimento)
[53] <corpo> ::= principal '(' ')' #31 <bloco> #53 <corpo>
Verificar se há pendências em aberto nas diversas pilhas. Se houver, gerar o erro
equivalente.
Senão Gerar PARA -,[54] <clauresult> ::= resultado <cond> #54
Se categoria não é função:
ERRO(Cláusula 'resultado' só pode ser utilizada dentro de funções)
senão
Gerar POP 0,0 -> isto fará com que o valor de retorno seja copiado para a posição
mais baixa da pilha de execução (qdo o código for executado)
Fazer geradoRET = true
[57] <clausula> ::= '!' <valor> #57
Gerar NEGA -,[58] <cond2> ::= '&&' <clausula> #58 <cond2>
Gerar CONJ -,[59] <cond2> ::= '||' <clausula> #59 <cond2>
Gerar DISJ -,[60] <oprel> ::= '>' #60 | '<' #61 | '>=' #62 | '<=' #63 |
'==' #64 | '!=' #65
Empilhar "maior" na pilhaOP
[61]
Empilhar "menor" na pilhaOP
[62]
Empilhar "maior-igual" na pilhaOP
[63]
Empilhar "menor-igual" na pilhaOP
[64]
Empilhar "igual" na pilhaOP
[65]
Empilhar "dif" na pilhaOP
[66] <valor> ::= <expr> <oprel> <expr> #66
Gerar instrução de comparação correspondente à operação do topo da pilhaOP e
desempilhar
se topo de pilhaOP="maior" – Gerar CMMA -, se topo de pilhaOP=”menor” - Gerar CMME -, se topo de pilhaOP="igual" – Gerar CMIG -,etc, etc.
[67] <optermo> ::= '+' #67 | '-' #68
7
Empilhar "soma" na pilhaOP
[68]
Empilhar "subt" na pilhaOP
[69] <expr2> ::= <optermo> <termo> #69 <expr2>
Gerar instrução aritmética conforme topo da pilhaOP e desempilhar
se topo="soma" – Gerar SOMA -, se topo="subt" – Gerar SUB -,[70] <opfator> ::= '*' #70 | '/' #71 | '%' #72
Empilhar "mult" na pilhaOP
[71]
Empilhar "div" na pilhaOP
[72]
Empilhar "rest" na pilhaOP
[73] <termo2> ::= <opfator> <fator> #73 <termo2>
Gerar instrução arimética conforme topo da pilhaOP e desempilhar
se topo="mult" – Gerar MULT -, se topo="div" – Gerar DIV -, se topo="rest" – Gerar MOD -,[74] <fator> ::= '-' <fator> #74
Gerar MUNARIO -,[75] <litnum> ::= cteint #75
Gerar PUSHK cteint
Fazer tipo="int"
[76] <litnum> ::= cteflutuante #76
Flutuante retirado da linguagem neste semestre. Só faz: tipo="flutuante"
[77] <fator> ::= litcar #77
DESNECESSÁRIO IMPLEMENTAR NESTE SEMESTRE
Gerar PUSHK código(litcar) (usar o código ASCII ou Unicode do caracter)
Fazer tipo="caracter"
[78] <fator> ::= litstring #78
Armazenar "litstring" na Tabela de Strings (deslocString++)
Gerar PUSHK deslocString (posição da TabString onde o litstring foi armazenado)
Fazer tipo="string"
[79] <fator> ::= ID #79 <contid>
OBS: Não se pode chamar FUNÇÃO NÃO pré-declarada
Se ID está na TI e não for variável, parametro, função ou cte: ERRO(uso indevido)
senão Recuperar da TI os dados do ID e salvar em uma tupla temporária para usar em
#80/81
[80] <contid> ::= @ #80
Se ID é constante (esta opção não terá utilidade neste semestre)
Gerar PUSHK x (x é o valor pré-declarado – está na tupla temporária)
Fazer tipo="int"
senão
se ID é var.string
Gerar PUSHK deslocString (está na tupla temporária)
7
Fazer tipo="string"
se ID é outro tipo de variável ou parâmetro
Gerar PUSH base, desloc (ver tupla temporária)
Fazer tipo=(ver tipo definido na tupla temporária)
senão ERRO(Esperava-se variável, parâmetro ou constante)
[81] <contid> ::= #81 '(' <listaparam> #82 ')'
Se ID (ver tupla temporária salva em #79) não é função: ERRO(Esperava-se função)
Senão
Zerar contaParam
Fazer tipo=(ver tipo definido na tupla temporária salva em #79)
[82] <contid> ::= #81 '(' <listaparam> #82 ')'
Se contaParam <> nºparametros declarados (ver tupla temporária):
ERRO(nº parâmetros incorreto)
Gerar CALL base, end
Gerar PUSH 0, 0 <- servirá para carregar o resultado da função que está no fundo da
pilha de execução
[83] <fator> ::= ler '(' ')' #83
Gerar instrução LEIT -,- (deixa o valor lido no topo da pilha – se for lido um caracter,
deve-se utilizar o valor do código correspondente (Unicode ou Ascii))
[84] <cmdsaida> ::= escrever "(" <expr> #84 ")";
Se tipo da <expr> for "string" (consultar variável "tipo")
Gerar instrução IMPRLIT _,_ (utilizará o valor do topo da pilha de execução
para acessar a TabStrings e colocar o string na tela)
Se tipo é "caracter"
Gerar instrução IMPRCH _,_ (o valor do topo da pilha é um código ASCII
ou Unicode. Deverá ser convertido p/o caracter adequado e depois exibido)
Se tipo é "booleano"
Gerar instrução IMPRBL _,_ (o valor do topo da pilha é 0 (false) ou 1 (true).
IMPRBL imprimirá a Falso ou Verdade, respectivamente)
Se tipo é "int"
Gerar instrução IMPR _,_
Outros: ERRO(Não implementado nesta versão)
7