Intermediate Code Generation - Recursion in Verification

Asked

Viewed 83 times

1

Good afternoon, guys. I’m at a stage in the matter of compilers which is the intermediate code generation of my grammar. After the steps of lexical, syntactic, semantic analysis.

Basically I have the following code:

from infixToPostfix import infixToPostfix # Importação da função que faz a conversão de infixa pra posfixa

def verAtribuicao(variavel, i, cod, tok):
    ex = ''
    while tok[i][1] != 'fim_linha':  # Enquanto não encontrar um token de fim linha
        ex += ' ' + tok[i][0]  # o buffer acumula os tokens encontrados
        i += 1
    return tac(variavel, infixToPostfix(ex), cod, i)  # Chama a função tac (three address code) passando a variavel, expressao pos fixada, a lista e a iteração

def tac(var, expression, cod, it):
    exp = expression.split()
    stack = []
    oper = ['+', '-', '*', '/']
    for i in range(len(exp)):
        if exp[i] in oper:
            v1 = stack.pop()
            v2 = stack.pop()
            t = f'{v2} {exp[i]} {v1}'
            if len(exp) == i+1:
                cod.append(f'{var} := {t}')
            else:
                cod.append(f'_t{it} := {t}')
                stack.append(f'_t{it}')
                it += 1
        else:
            stack.append(exp[i])
    if len(stack) == 1:
        cod.append(f'{var} := {stack[0]}')

# Abertura da lista de tokens retornada na análise léxica

with open("lista_tokens.txt", "r") as arquivo:
    tk = arquivo.readlines()

# variáveis de controle

i = 0
ctrl = 0

# declaração das listas de apoio

cod_intermediario = []
registro_log = []
tokens = []

# Loop apenas pra inserir as informações das linhas já delimitado

for j in tk:
    tokens.append(j.split('|'))

# Faz a verificação da declaração das variáveis

for tk in tokens:
    if tk[1] == 'id' and tokens[ctrl-1][1] == 'tiponum':
        cod_intermediario.append(f'INTEIRO {tk[0]}')
        registro_log.append(f'Declaração da variável {tk[0]}')
    ctrl += 1

def verifica(tokens, i, L, C): # Função para fazer a verificação de leitura, escrita e atribuição
    expressao = ''
    if tokens[i][1] == 'ler':  # Verifica se o token é de leitura, mostra o token e pula 4 iterações
        cod_intermediario.append(f'LEIA {tokens[i+2][0]}')
        registro_log.append(f'Reconhecido comando leitura da variável {tokens[i+2][0]}')
        i += 4
    elif tokens[i][1] == 'escrever':  # Verifica se o token é de escrita, mostra o token e pula 4 iterações
        cod_intermediario.append(f'ESCREVA {tokens[i+2][0]}')
        registro_log.append(f'Reconhecido comando de escrita')
        i += 4
    elif tokens[i][1] == 'atribuicao':  # Verifica se o token é de atribuição e avança 1 iteração
        variavel = tokens[i - 1][0]
        i += 1
        registro_log.append(f'Reconhecido expressão atribuída para {tokens[i-2][0]}')
        verAtribuicao(variavel, i, cod_intermediario, tokens)
    elif tokens[i][1] == 'enquanto': # Verifica se o token encontrado é um enquanto
        i += 2
        while tokens[i][1] != 'parenteses_fecha': # enquanto não encontrar um fechamento de parenteses, acumula os tokens no buffer
            expressao += ' ' + tokens[i][0]
            i += 1
        if expressao.split()[1] == '<=':
            operador = '>'
        elif expressao.split()[1] == '>=':
            operador = '<'
        elif expressao.split()[1] == '==':
            operador = '='
        cod_intermediario.append(f'_L{L}: if {expressao.split()[0]} {operador} {expressao.split()[2]} goto _L{L+1}')
        i += 2
        i = verifica(tokens, i, L+1, C)
        cod_intermediario.append(f'_L{L+1}:')
        registro_log.append(f'Reconhecido expressão enquanto para {expressao}')
    elif tokens[i][1] == 'se': # Verifica se o token encontrado é um enquanto
        i += 2
        while tokens[i][1] != 'parenteses_fecha': # enquanto não encontrar um fechamento de parenteses, acumula os tokens no buffer
            expressao += ' ' + tokens[i][0]
            i += 1
        if expressao.split()[1] == '<=':
            operador = '>'
        elif expressao.split()[1] == '>=':
            operador = '<'
        elif expressao.split()[1] == '==':
            operador = '='
        cod_intermediario.append(f'_C{C}: if {expressao.split()[0]} {operador} {expressao.split()[2]} goto _C{C+1}')
        i += 2
        cod_intermediario.append(f'_C{C+1}:')
        registro_log.append(f'Reconhecido expressão se para {expressao}')
    return i

L = C = 0

while i < len(tokens):
    i = verifica(tokens, i, L, C)
    i += 1

for t in registro_log:
    print(t)

print('\n')
print('*' * 50)
print('\n')

for j in cod_intermediario:
    print(j)

Within the function checks I have two conditions: When is found a "while", and when is found a "if".

Let’s say in my grammar below:

run

integer f = 1;
integer i = 1;
integer n;

display("Digite qual numero deseja calcular a fatorial");
input(n);
while(i <= n){
    f = f * i;
    i = i+1;
}
exit

As I have a while and inside that while I have two lines of assignments, so far so good... but for example, it can happen from inside it to have an if, or other while, etc. Can anyone help me to have an idea of what to do in this case? Thank you!

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.