17.01.2013 Views

COMPORT – Compilador Portugol - Nilo Menezes

COMPORT – Compilador Portugol - Nilo Menezes

COMPORT – Compilador Portugol - Nilo Menezes

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

UNIVERSIDADE DO AMAZONAS<br />

Instituto de Ciências Exatas<br />

Departamento de Ciência da Computação<br />

<strong>COMPORT</strong> <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

MANAUS <strong>–</strong> AM<br />

SETEMBRO 2003<br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

I


<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

<strong>COMPORT</strong> <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Monografia apresentada à banca<br />

examinadora da Universidade do<br />

Amazonas, como exigência parcial para<br />

obtenção do grau de Bacharel em<br />

Processamento de Dados sob a orientação<br />

do Professor Doutor Alberto Nogueira de<br />

Castro Júnior.<br />

MANAUS <strong>–</strong> AM<br />

SETEMBRO 2003<br />

II


<strong>Menezes</strong>, <strong>Nilo</strong><br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Acadêmico [Manaus] 2003.<br />

125p, 29,7cm<br />

Monografia de conclusão de curso <strong>–</strong> Universidade do Amazonas<br />

Área de concentração: <strong>Compilador</strong>es<br />

Orientador(a): Prof(a). Alberto Nogueira de Castro Júnior, PhD<br />

1. <strong>Compilador</strong>es<br />

2. <strong>Portugol</strong><br />

3. Linguagens de programação<br />

III


À memória de José Ney Farias de <strong>Menezes</strong>, meu avô,<br />

responsável pela minha introdução à computação.<br />

IV


Aos meus pais pelo incentivo e suporte.<br />

A minha esposa e filhos pela paciência e finais de semana perdidos.<br />

V


“Quem quer fazer alguma coisa encontra um meio.<br />

Quem não quer fazer nada encontra uma desculpa”<br />

(provérbio árabe)<br />

“Quando se busca o cume da montanha,<br />

não se dá importância às pedras no caminho”<br />

(provérbio oriental)<br />

“As maiores distâncias que devemos percorrer estão dentro de nós mesmos”<br />

(Charles de Gaulle)<br />

VI


Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

ESTA MONOGRAFIA FOI SUBMETIDA À COORDENAÇÃO DO CURSO DE<br />

PROCESSAMENTO DE DADOS, COMO PARTE DOS REQUISITOS NECESSÁRIOS À OBTENÇÃO DO<br />

TÍTULO DE BACHAREL EM PROCESSAMENTO DE DADOS, OUTORGADO PELA UNIVERSIDADE DO<br />

AMAZONAS - UA E ENCONTRA-SE À DISPOSIÇÃO DOS INTERESSADOS NA BIBLIOTECA DA REFERIDA<br />

UNIVERSIDADE.<br />

A CITAÇÃO DE QUALQUER TRECHO DESTA MONOGRAFIA É PERMITIDA, DESDE<br />

QUE FEITA DE ACORDO COM AS NORMAS DE ÉTICA CIENTÍFICA.<br />

Banca Examinadora:<br />

_______________________________<br />

Prof. Alberto Nogueira de Castro Júnior, PhD<br />

Universidade do Amazonas<br />

_______________________________<br />

Prof. Edjar de Souza Mota, PhD<br />

Universidade do Amazonas<br />

_______________________________<br />

Prof. Ruiter Braga, MsC<br />

Universidade do Amazonas<br />

Julgado em: ____ / ____ / _______<br />

MANAUS <strong>–</strong> AM<br />

SETEMBRO 2003<br />

VII


DECLARAÇÃO<br />

Declaro que esta monografia foi desenvolvida por mim e, através deste instrumento,<br />

concedo ao Departamento de Ciência da Computação da Universidade do Amazonas<br />

(DCC/UA) o direito de utilizá-la, bem como aos produtos resultantes do trabalho nela<br />

descrito (software, hardware, modelos, algoritmos, etc) nas suas atividades de ensino,<br />

pesquisa e extensão.<br />

_________________________________<br />

<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

VIII


RESUMO<br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

Setembro 2003<br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Orientador: Prof. Alberto Nogueira de Castro Júnior, PhD<br />

Este trabalho visa reunir informações sobre a construção de um compilador<br />

da linguagem <strong>Portugol</strong>, com objetivo de servir como um estudo de caso para a disciplina de<br />

Construção de <strong>Compilador</strong>es do curso de Ciência da Computação da Universidade do<br />

Amazonas. A disponibilização de uma ferramenta para estudo e ensino de programação em<br />

português pretende quebrar a barreira da língua inglesa, presente em praticamente todas<br />

as linguagens de programação conhecidas. O trabalho inclui um estudo e especificação de<br />

uma máquina RISC virtual que pode ser analisada e estendida durante cursos de<br />

Organização de Computadores. Foi incluída uma pequena referência bibliográfica que pode<br />

servir como base para o estudo das técnicas de compilação e geração de código.<br />

9


ABSTRACT<br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

Setembro 2001<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Supervisor: Prof. Alberto Nogueira de Castro Júnior, PhD<br />

The purpose of this paper is to collect information about the <strong>Portugol</strong> language<br />

compiler construction and specification. The learning of the English language is a<br />

very difficult problem to Brazilian students who want to learn their first programming<br />

language as they are always written in English. This paper can be used in Compiler<br />

Construction courses. The virtual RISC machine specification included can be used<br />

in the Computers Organization course. It includes a little reference about compiling<br />

and code generation.<br />

10


SUMÁRIO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

DECLARAÇÃO......................................................................................................... VIII<br />

RESUMO.......................................................................................................................9<br />

ABSTRACT.................................................................................................................10<br />

SUMÁRIO....................................................................................................................11<br />

LISTA DE TABELAS ..................................................................................................15<br />

LISTA DE FIGURAS...................................................................................................16<br />

INTRODUÇÃO ............................................................................................................17<br />

1. A COMPILAÇÃO.................................................................................................18<br />

1.1. Linguagem e Sintaxe ..................................................................................................18<br />

1.1.1. Símbolos ...............................................................................................................19<br />

1.1.2. Alfabeto, palavra e comprimento .........................................................................19<br />

1.1.3. Gramática .............................................................................................................20<br />

1.1.4. Autômatos Finitos ................................................................................................21<br />

1.2. <strong>Compilador</strong> .................................................................................................................24<br />

1.3. Análise Léxica e Analisador Léxico ..........................................................................25<br />

1.3.1. Tokens, Padrões e Lexemas .................................................................................26<br />

1.3.2. Expressões regulares.............................................................................................26<br />

1.3.3. Tabela de Símbolos ..............................................................................................28<br />

1.4. Análise Sintática .........................................................................................................28<br />

11


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

1.4.1. Gramáticas livres de contexto...............................................................................28<br />

1.5. Análise Semântica.......................................................................................................29<br />

1.6. Geração de Código .....................................................................................................29<br />

1.7. Otimização de Código ................................................................................................30<br />

2. PORTUGOL.........................................................................................................31<br />

2.1. Comentários ................................................................................................................31<br />

2.2. Tipos básicos ...............................................................................................................31<br />

2.2.1. Numérico ..............................................................................................................31<br />

2.2.2. Literal ...................................................................................................................32<br />

2.2.3. Lógico...................................................................................................................32<br />

2.2.4. Vetores e matrizes ................................................................................................32<br />

2.2.5. Registros ...............................................................................................................32<br />

2.3. Variáveis e identificadores.........................................................................................33<br />

2.4. Declaração de variáveis..............................................................................................33<br />

2.5. Atribuição....................................................................................................................34<br />

2.6. Operadores..................................................................................................................34<br />

2.6.1. Operadores Aritméticos........................................................................................34<br />

2.6.2. Operadores Lógicos..............................................................................................35<br />

2.6.3. Operadores Relacionais ........................................................................................35<br />

2.6.4. Operadores Literais ..............................................................................................35<br />

2.7. Estrutura seqüencial ..................................................................................................36<br />

2.8. Estruturas condicionais..............................................................................................36<br />

2.9. Estruturas de repetição..............................................................................................37<br />

2.10. Procedimentos e Funções .......................................................................................38<br />

12


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

2.11. Módulos ...................................................................................................................39<br />

2.12. Funções pré-definidas ............................................................................................39<br />

2.13. Especificação BNF ..................................................................................................40<br />

3. O COMPILADOR PORTUGOL ...........................................................................43<br />

3.1. Analisador Léxico.......................................................................................................43<br />

3.2. Analisador Sintático ...................................................................................................43<br />

3.3. Gerador de Código .....................................................................................................43<br />

3.4. Funções Adicionais .....................................................................................................43<br />

4. A MÁQUINA VIRTUAL........................................................................................44<br />

4.1. Registradores ..............................................................................................................44<br />

4.2. Formato de Instruções ...............................................................................................45<br />

4.3. Instruções ....................................................................................................................46<br />

4.4. Limitações ...................................................................................................................48<br />

4.5. Implementação............................................................................................................48<br />

CONCLUSÃO .............................................................................................................49<br />

REFERÊNCIA BIBLIOGRÁFICA ...............................................................................50<br />

APÊNDICE A <strong>–</strong> CÓDIGO FONTE ..............................................................................51<br />

SCANNER.H...........................................................................................................................51<br />

SCANNER.CPP ......................................................................................................................55<br />

PARSER.H ..............................................................................................................................65<br />

13


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

PARSER.CPP .........................................................................................................................67<br />

CODEGENERATOR.H.........................................................................................................84<br />

CODEGENERATOR.CPP ....................................................................................................87<br />

FUNCOES.H.........................................................................................................................100<br />

FUNCOES.CPP ....................................................................................................................101<br />

RISC.H ..................................................................................................................................103<br />

RISC.CPP..............................................................................................................................104<br />

INSTRUCOES.H ..................................................................................................................108<br />

PRINCIPAL.CPP .................................................................................................................109<br />

MAKEFILE ..........................................................................................................................110<br />

APENDICE B <strong>–</strong> TABELA ASCII...............................................................................114<br />

APENDICE C <strong>–</strong> OPCODES DA MÁQUINA VIRTUAL.............................................115<br />

APENDICE D <strong>–</strong> EMENTAS DE CURSOS DE COMPILAÇÃO DE OUTRAS<br />

UNIVERSIDADES.....................................................................................................118<br />

ÍNDICE REMISSIVO .................................................................................................124<br />

14


LISTA DE TABELAS<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Tabela 1 - Função programa _________________________________________________ 22<br />

Tabela 2 - Token x Lexema x Padrão___________________________________________ 26<br />

Tabela 3 - Notação para as expressões regulares _________________________________ 27<br />

Tabela 4 - Operadores aritméticos_____________________________________________ 34<br />

Tabela 5 - Operadores lógicos ________________________________________________ 35<br />

Tabela 6 - Operadores Relacionais ____________________________________________ 35<br />

Tabela 7 - Operadores literais ________________________________________________ 35<br />

Tabela 8 - Funções pré-definidas______________________________________________ 39<br />

Tabela 9 <strong>–</strong> Instruções da Máquina Virtual_______________________________________ 47<br />

15


LISTA DE FIGURAS<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Figura 1 - Fita e unidade de controle ......................................................................................21<br />

Figura 2 - Representação gráfica de um autômato..................................................................22<br />

Figura 3 - Exemplo de autômato finito ....................................................................................23<br />

Figura 4 - Diagrama de tradução ............................................................................................24<br />

Figura 5 - Fases de um compilador .........................................................................................25<br />

Figura 6 - O papel do analisador léxico ..................................................................................25<br />

16


INTRODUÇÃO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

A aprendizagem de uma linguagem de programação, normalmente<br />

com símbolos e palavras-chave em inglês, por estudantes brasileiros que não<br />

dominam o idioma é um obstáculo a mais no estudo da computação. Para resolver<br />

este tipo de problema e garantir independência de conteúdo em relação à<br />

linguagens comerciais ou não padronizadas, muitos autores criaram uma linguagem<br />

aportuguesada, normalmente utilizada para descrever algoritmos, geralmente<br />

chamada de <strong>Portugol</strong>.<br />

No entanto, vários autores definiram o <strong>Portugol</strong> como uma forma<br />

traduzida de Pascal ou de “Pascal sem ponto-e-vírgula em português”. Além disso,<br />

a escassez ou inexistência de compiladores de <strong>Portugol</strong> faz com que a tradução<br />

para uma outra linguagem de programação seja etapa necessária e obrigatória para<br />

o teste da lógica num computador.<br />

O objetivo deste trabalho é construir um compilador <strong>Portugol</strong>,<br />

detalhando as fases de construção, mostrando opções e justificando escolhas. Não<br />

só criando uma ferramenta de testes, mas também, material para estudo nas<br />

disciplinas de Construção de <strong>Compilador</strong>es e Linguagens de Programação; e talvez<br />

Sistemas Operacionais e Organização de Computadores.<br />

O texto foi dividido em quatro capítulos. O primeiro capítulo trata da<br />

definição dos termos básicos para o entendimento de todo o texto, desde a<br />

definição de linguagem até as partes e fases de um compilador. O segundo capítulo<br />

cobre a modelagem do <strong>Portugol</strong>, desta vez uma linguagem em português com<br />

características próprias. O terceiro capítulo é a aplicação dos conceitos dos dois<br />

primeiros, nele constrói-se o compilador <strong>Portugol</strong> propriamente dito. No quarto e<br />

último capítulo define-se a máquina virtual, uma vez que o compilador gera<br />

pseudocódigo, com objetivo de garantir portabilidade e transparência entre<br />

plataformas e sistemas operacionais. O código fonte de todos os programas<br />

desenvolvidos se encontram nos apêndices e tabelas importantes nos anexos.<br />

<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

17


1. A COMPILAÇÃO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

O entendimento do processo de compilação exige o conhecimento de<br />

uma série de termos como linguagem, sintaxe, tokens e lexemas entre outros. O<br />

objetivo deste capítulo é explicar estes termos, dando uma noção geral do que está<br />

por vir, formando uma base comum de conhecimento.<br />

1.1. LINGUAGEM E SINTAXE<br />

Em WIRTH (1996), cada linguagem mostra uma estrutura chamada<br />

gramática ou sintaxe. Por exemplo, uma sentença correta consiste de um sujeito<br />

seguido por um predicado, onde correto significa bem formada. Este fato pode ser<br />

descrito pela seguinte fórmula:<br />

sentença = sujeito predicado.<br />

Se adicionarmos a esta fórmula outras duas:<br />

sujeito = “João” | “Maria”<br />

predicado = “come” | “fala”<br />

Então definiríamos conseqüentemente quatro possíveis sentenças:<br />

João come<br />

João fala<br />

Maria come<br />

Maria fala<br />

Onde o símbolo “|” é pronunciado como “ou”. Estas fórmulas são<br />

chamadas regras sintáticas, produções ou simplesmente equações sintáticas.<br />

Sujeito e predicado são classes sintáticas. Uma notação simplificada omite<br />

identificadores significativos:<br />

S = AB.<br />

A=”a”|”b”.<br />

B=”c”|”d”.<br />

L={ac,ad,bc,bd}<br />

18


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Ao conjunto L de sentenças que são geradas desta forma, ou seja, pela<br />

substituição repetida de sentenças do lado esquerdo pelas do lado direito da<br />

equação; é chamado linguagem.<br />

Formulando os conceitos apresentados mais rigorosamente, uma<br />

linguagem é definida pelo seguinte:<br />

1. Um conjunto de símbolos terminais. São símbolos que ocorrem<br />

em suas sentenças. São chamados terminais por não poderem<br />

ser substituídos por nenhum outro símbolo. O processo de<br />

substituição termina com símbolos terminais. No exemplo, este<br />

conjunto consiste dos elementos a,b,c e d. Este conjunto<br />

também é chamado de vocabulário.<br />

2. Um conjunto de símbolos não-terminais. Estes denotam classes<br />

sintáticas e podem ser substituídos. No exemplo, são os<br />

elementos S, A e B.<br />

3. Um conjunto de equações sintáticas. Estas definem as possíveis<br />

substituições de símbolos não terminais. Uma equação é<br />

especificada para cada símbolo não terminal.<br />

4. Um símbolo inicial. É um símbolo não-terminal. No exemplo S.<br />

Uma linguagem é um conjunto de seqüências de símbolos<br />

terminais que, começando pelo símbolo inicial, podem ser gerados pela<br />

aplicação repetitiva de equações sintáticas, ou seja, substituições.<br />

1.1.1. Símbolos<br />

Símbolos não possuem uma definição formal, são entidades abstratas<br />

básicas, um conceito primitivo, como o ponto na Geometria.<br />

Exemplos de símbolos são as letras do nosso alfabeto ou dígitos de um<br />

número.<br />

1.1.2. Alfabeto, palavra e comprimento<br />

Um alfabeto é um conjunto finito de símbolos. Por exemplo, o alfabeto<br />

da língua portuguesa é composto de letras de “A” até “Z”. No estudo de<br />

19


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

compiladores podemos definir outros alfabetos para fins específicos. Por exemplo:<br />

Σ={a,b} indica um alfabeto chamado Σ, com dois elementos (a e b). Utilizaremos o<br />

símbolo Σ* para denotar todas as palavras que podem ser formadas por um alfabeto<br />

Σ.<br />

Entende-se por palavra uma seqüência ou cadeia de símbolos de um<br />

alfabeto. A palavra vazia será representada por ε e utilizaremos Σ+ para denotar<br />

todas as palavras de um alfabeto Σ, com exceção da palavra vazia. Logo, podemos<br />

concluir que Σ+ = Σ* - { ε }. É bom lembrar que Σ = { } é um alfabeto válido, mesmo<br />

sem possuir símbolos.<br />

Exemplo:<br />

Utilizando a nossa definição anterior de Σ={a,b}, teríamos Σ*={ε, a, b,<br />

aa, bb, aaa, bbb, ...} e Σ+={a, b, aa, bb, aaa, bbb, ...}.<br />

O comprimento de uma palavra é igual ao número de símbolos que ela<br />

possui. Exemplo:<br />

| a | = 1 lê-se o comprimento de “a” é 1.<br />

| aaa | = 3 lê-se o comprimento de “aaa” é 3.<br />

1.1.3. Gramática<br />

Em MENEZES (2001), obtemos a definição formal de gramática:<br />

“Uma gramática é uma quádrupla ordenada G = (V, T, P, S) onde:<br />

V conjunto de símbolos variáveis ou não terminais;<br />

T conjunto de símbolos terminais, disjunto de V;<br />

P conjunto finitos de pares, denominados regras de produção;<br />

S elemento de V denominado variável inicial.”<br />

Na notação acima, a linguagem anterior poderia ser representada por:<br />

G = ( { A, B, S}, { a, b, c, d }, P, S )<br />

Onde P = { S � AB, A � a | b, B � c | d }<br />

Desta forma podemos dizer que L é a linguagem gerada por G, ou seja,<br />

L(G) ou simplesmente GERA(G).<br />

Dizemos que duas gramáticas são equivalentes se e somente se as<br />

linguagens por ela geradas forem iguais, ou seja, supondo G1 e G2 gramáticas, G1<br />

e G2 são equivalentes se e somente se GERA(G1)=GERA(G2).<br />

20


1.1.4. Autômatos Finitos<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Segundo AHO (1995), um reconhecedor para uma linguagem é um<br />

programa que toma como entrada uma cadeia x e responde “sim” se x for uma<br />

sentença da linguagem e “não” caso contrário. Compilamos expressões regulares<br />

(veja 1.3.2) num reconhecedor através da construção de um diagrama de transições<br />

generalizado, chamado autômato finito.<br />

Os autômatos finitos se classificam em determinísticos e nãodeterminísticos.<br />

Um autômato finito determinístico pode ser visto como uma máquina<br />

simples, composta de fita, unidade de controle e programa ou função.<br />

A fita é finita (nos dois sentidos), sendo dividida em células de um símbolo<br />

ou caractere. Esta fita não permite gravação e contém toda a informação de entrada.<br />

Os símbolos pertencem ao alfabeto de entrada.<br />

Figura 1 - Fita e unidade de controle<br />

A unidade de controle possui um número finito e predefinido de estados.<br />

Inicialmente a cabeça de leitura está posicionada no símbolo mais à esquerda da<br />

fita. A cada símbolo lido, desloca-se a cabeça de leitura uma célula para a direita.<br />

O programa é uma função parcial que dependendo do símbolo lido<br />

determina o estado corrente do autômato. É importante notar que um autômato não<br />

possui memória, devendo-se utilizar estados intermediários para armazenar<br />

resultados.<br />

Formalmente, podemos definir um autômato finito determinístico como<br />

uma quíntupla:<br />

M=(Σ,Q,δ,q0,F)<br />

Onde:<br />

Σ Alfabeto de símbolos de entrada<br />

Q Conjunto de estados possíveis do autômato<br />

21


δ Função programa ou de transição<br />

q0 Estado inicial<br />

F Conjunto de estados finais, tal que F ⊂ Q<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

O processamento de um autômato finito M, para uma palavra de entrada<br />

w, consiste na sucessiva aplicação de δ para cada símbolo de w (da esquerda para<br />

a direita), até ocorrer uma condição de parada.<br />

Um autômato finito determinístico pode parar em três casos:<br />

1. Quando o processamento da entrada leva a um estado finito e a<br />

entrada é aceita.<br />

2. Quando um símbolo de entrada possui uma saída indeterminada pela<br />

função programa, neste caso a entrada é rejeitada.<br />

3. Quando a fita acaba e o autômato está num estado não-final, a entrada<br />

é rejeitada.<br />

Um autômato finito sempre pára, uma vez que um novo símbolo de<br />

entrada é lido a cada aplicação da função programa, não existindo a possibilidade<br />

de loop infinito, dada a natureza finita da fita.<br />

Figura 2 - Representação gráfica de um autômato<br />

Um exemplo de autômato finito determinístico seria aquele responsável<br />

por validar uma entrada que possua a seqüência ab, considerando-se Σ={a,b} como<br />

alfabeto, Q={q0, q1,qf} como os possíveis estados e F={qf}.<br />

Sendo δ a função programa abaixo:<br />

Tabela 1 - Função programa<br />

δ a b<br />

q0 q1 q0<br />

q1 q1 qf<br />

Qf qf qf<br />

Graficamente este autômato seria representado por:<br />

22


Figura 3 - Exemplo de autômato finito<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Supondo aabab como entrada, iniciaríamos no estado q0, lendo o “a”<br />

mais à esquerda. Pela função programa da Tabela 1, teríamos trocado de estado<br />

para q1 e leríamos o segundo “a”, permanecendo em q1. Ao lermos o “b”,<br />

trocaríamos de estado para qf, onde permaneceremos, enquanto “a” ou “b” forem<br />

lidos até o fim da fita. Como chegamos a um estado final no fim da fita, este<br />

autômato diz que a seqüência é válida.<br />

Em autômatos finitos não-determinísticos temos a mesma definição<br />

formal, exceto em relação a função programa que pode gerar um conjunto de<br />

estados para um símbolo de entrada.<br />

Ao executar um autômato finito não-determinístico e obtermos um<br />

conjunto de estados como resultado da função programa, “cria-se” uma linha de<br />

execução independente para cada elemento do conjunto. Como se tivéssemos uma<br />

nova máquina para cada elemento, com recursos e destinos próprios.<br />

Todo autômato finito não determinístico pode ser transformado em<br />

autômato finito determinístico, como é provado em MENEZES (2001).<br />

Segundo AHO (1995), tanto os autômatos finitos determinísticos<br />

quanto os não-determinísticos são capazes de reconhecer precisamente expressões<br />

regulares. Conseqüentemente, ambos podem validar exatamente o que estas<br />

expressões podem denotar. Entretanto, existe uma barganha tempo-espaço:<br />

enquanto os autômatos finitos determinísticos podem levar a reconhecedores mais<br />

rápidos que os não determinísticos, um autômato finito determinístico pode ser muito<br />

maior que um não determinístico equivalente.<br />

23


1.2. COMPILADOR<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Segundo WIRTH (1996), programas de computador são formulados em<br />

uma linguagem de programação e especificam classes de processos<br />

computacionais. Computadores, entretanto, interpretam seqüências de instruções<br />

particulares, mas não textos de programas. Assim sendo, o texto do programa deve<br />

ser traduzido em uma seqüência de instruções específicas, antes de poder ser<br />

processado por um computador. Esta tradução pode ser automatizada, o que implica<br />

que pode ser formulada como um programa. O programa de tradução é chamado<br />

compilador e o texto a ser traduzido é chamado de texto fonte ou código fonte.<br />

Definido em AHO (1995) como: “um compilador é um programa que lê<br />

um programa escrito em uma linguagem <strong>–</strong> a linguagem de origem <strong>–</strong> e o traduz em<br />

um programa equivalente em outra linguagem <strong>–</strong> a linguagem destino. Como uma<br />

importante parte no processo de tradução, o compilador reporta ao seu usuário a<br />

presença de erros no programa origem”.<br />

Figura 4 - Diagrama de tradução<br />

A linguagem de origem pode ser qualquer linguagem de alto nível<br />

como C, Pascal ou Modula e a de destino qualquer outra linguagem de alto nível ou<br />

código de máquina de qualquer processador.<br />

Na Figura 4, vemos o programa fonte, escrito na linguagem de origem,<br />

o compilador e o programa objeto, escrito na linguagem destino.<br />

Um compilador pode ter várias partes como: analisador léxico,<br />

analisador sintático, analisador semântico, otimizador e gerador de código. Um<br />

esquema de todas as suas partes e interelações pode ser visto na Figura 5 abaixo.<br />

24


Figura 5 - Fases de um compilador<br />

1.3. ANÁLISE LÉXICA E ANALISADOR LÉXICO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Em AHO (1995), análise léxica é a primeira fase de um compilador.<br />

Sua principal tarefa é ler os caracteres de entrada e produzir como saída uma<br />

seqüência de tokens que serão utilizados na análise sintática. Esta interação é<br />

normalmente implementada fazendo com que o analisador léxico seja uma subrotina<br />

do analisador sintático (parser). Ao receber o comando “obter próximo token”<br />

do parser, o analisador léxico lê caracteres da entrada até que identifique o próximo<br />

token. Este processo pode ser visualizado na figura abaixo:<br />

Figura 6 - O papel do analisador léxico<br />

25


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Como o analisador léxico é a parte do compilador que lê o texto fonte<br />

(origem), ele também pode realizar outras funções secundárias como remover<br />

espaços em branco, comentários e geração de mensagens de erro com referências<br />

a linhas do programa.<br />

1.3.1. Tokens, Padrões e Lexemas<br />

É impossível falar sobre análise léxica e analisadores léxicos sem<br />

definir o significado de tokens, padrões e lexemas.<br />

Tokens são símbolos terminais na gramática de uma linguagem. Na<br />

maioria das linguagens de programação, as seguintes construções são tratadas<br />

como tokens: palavras-chave, operadores, identificadores, constantes, cadeias<br />

literais (strings) e símbolos de pontuação como parênteses, vírgulas e pontos.<br />

Um padrão (pattern) é uma regra descrevendo o conjunto de lexemas<br />

que podem representar um token na linguagem. Estas regras normalmente são<br />

descritas na forma de expressões regulares (Ver 1.3.2).<br />

Lexemas são seqüências de caracteres descritas por um padrão de um<br />

token. Ou seja, o lexema é o valor do token, muitas vezes aparecendo como um<br />

atributo para as fases seguintes de compilação. Enquanto o analisador léxico<br />

procura por tokens, na geração de código precisaremos dos lexemas para produzir<br />

significado.<br />

Exemplo: 3.1415<br />

Tabela 2 - Token x Lexema x Padrão<br />

Token Lexema Padrão<br />

Numero 3.1415 ([+,-])([0-9])*(.([0-9])+)<br />

1.3.2. Expressões regulares<br />

Expressões regulares são uma forma muito interessante de descrever<br />

padrões, especialmente aqueles que consistem em cadeias de caracteres. Através<br />

destas expressões podemos especificar que seqüências de caracteres são aceitas<br />

em um token, especificando caracteres opcionais e o número de repetições aceitos.<br />

26


3, abaixo:<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

A notação utilizada nos exemplos deste texto é especificada na Tabela<br />

Tabela 3 - Notação para as expressões regulares<br />

Símbolo Significado<br />

+ Indica repetição de 1..n.<br />

Exemplo: [a-z]+<br />

* Indica repetição de 0..n.<br />

Exemplo: [0-9]*<br />

? Denota que um item é opcional.<br />

Exemplo: [0-9]?<br />

[ ] Utilizados para definir conjuntos de caracteres.<br />

Exemplo: [afgh] [159]<br />

( ) Utilizados para agrupar itens.<br />

Exemplo: ([0-9]+)?<br />

- Indica faixa em conjuntos.<br />

Exemplo: [0-9] [a-z] [A-Z]<br />

{ } Indicam um número conhecido de repetições.<br />

Caso haja um número mínimo e um máximo,<br />

pode-se representar a faixa utilizando uma “,“.<br />

| Significa “ou”. Aparece entre parênteses e<br />

separa os elementos de uma lista. Somente um<br />

item da lista pode ser usado por vez.<br />

^ Denota início de linha<br />

$ Fim de linha<br />

Exemplos de uso:<br />

Exemplo 1: [0-9] Indica que um caractere, na faixa de 0 à 9 é aceito, ou seja, o<br />

conjunto {0,1,2,3,4,5,6,7,8,9}.<br />

Exemplo 2: [a-z] O mesmo do exemplo anterior, mas para letras minúsculas. É<br />

importante notar que para aceitar maiúsculas e minúsculas é necessário a<br />

expressão: [A-Za-z]<br />

Exemplo 3: (+|-)?[0-9]{1,10} Indica que podemos ter o símbolo “-“ ou “+” uma ou<br />

zero vezes, seguido de dígitos de 0 à 9 em número mínimo de uma ocorrência e<br />

máximo de 10.<br />

27


1.3.3. Tabela de Símbolos<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

É uma estrutura de dados utilizada para armazenar atributos dos<br />

tokens. Ela começa a ser preenchida pelo analisador léxico, mas continua<br />

recebendo dados das outras fases de compilação. Um exemplo é o reconhecimento<br />

de um número, considerando-se como referência a Tabela 2, teríamos dois campos<br />

na tabela de símbolos: o token e o lexema. Em identificadores mais complexos,<br />

como variáveis, poderíamos ter outros campos como o tipo da variável e até mesmo<br />

informações sobre diversos identificadores, como se são nomes de procedimentos,<br />

funções ou rótulos.<br />

O uso de uma tabela de símbolos para a representação das palavras<br />

reservadas de uma linguagem dá flexibilidade à sua extensão, além de proporcionar<br />

um método único para identificação de identificadores, como visto em AHO (1995) e<br />

WIRTH (1996).<br />

As tabelas de símbolos também são responsáveis pelo registro do<br />

endereço de identificadores, possibilitando a tradução de instruções de salto,<br />

chamadas de procedimentos e acesso a variáveis de memória.<br />

1.4. ANÁLISE SINTÁTICA<br />

Segundo AHO (1995), o analisador sintático (parser) obtém uma<br />

seqüência de tokens do analisador léxico e verifica se esta seqüência pode ser<br />

gerada pela gramática da linguagem.<br />

Todas as linguagens de programação possuem regras que descrevem<br />

a estrutura sintática de programas corretamente formados. A sintaxe de uma<br />

linguagem de programação pode ser descrita através de uma gramática livre de<br />

contexto ou notação BNF (Backus-Naur-Form).<br />

1.4.1. Gramáticas livres de contexto<br />

Segundo WIRTH (1996), o termo livre de contexto deve-se a Chomsky<br />

e indica que a substituição do símbolo à esquerda da � pela seqüência derivada da<br />

direita é sempre permitida, independente do contexto em que o símbolo foi inserido.<br />

28


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Esta restrição de liberdade de contexto é aceitável e desejável para linguagens de<br />

programação.<br />

Muitas linguagens de programação possuem estruturas que são<br />

naturalmente recursivas que podem ser definidas por gramáticas livres de contexto.<br />

Por exemplo, poderíamos ter uma declaração condicional definida por uma regra<br />

como:<br />

se E então S1 senão S2<br />

Esta forma de declaração condicional não pode ser expressa através<br />

de uma expressão regular. Por outro lado, utilizando a variável sintática stmt para<br />

denotar a classe da declaração e expr a classe das expressões, poderíamos<br />

expressar a declaração condicional como:<br />

1.5. ANÁLISE SEMÂNTICA<br />

stmt � se expr então stmt senão stmt<br />

Segundo AHO (1995), a fase de análise semântica verifica o código<br />

fonte para detectar erros de semântica e ao mesmo tempo coleta informações de<br />

tipo para a geração de código. Usando a estrutura hierárquica gerada pela fase de<br />

análise sintática, operadores e operandos de expressões e declarações são<br />

identificados. Um importante componente da análise semântica é a verificação de<br />

tipos. Nesta fase o compilador verifica se cada operador tem os operandos<br />

permitidos pela especificação da linguagem. Um exemplo é a utilização de números<br />

para índices de vetores. A maioria das linguagens permite o uso apenas de números<br />

inteiros, sendo números reais tratados como erro neste caso.<br />

1.6. GERAÇÃO DE CÓDIGO<br />

Nesta fase a representação intermediária do código é traduzida para a<br />

linguagem de máquina da máquina alvo, ou para a linguagem destino. Entre as<br />

tarefas do gerador de código estão: gerenciamento de memória, seleção de<br />

instruções e alocação de registradores entre outras.<br />

29


1.7. OTIMIZAÇÃO DE CÓDIGO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Segundo AHO (1995), compiladores devem produzir código tão bons<br />

quanto se fossem escritos à mão. A realidade é que este objetivo só é alcançado em<br />

poucos casos e com dificuldade. Entretanto, o código produzido por compiladores<br />

pode quase sempre rodar mais rápido ou ocupar menos espaço, ou ainda ambos.<br />

Esta melhoria é alcançada através de transformações que tradicionalmente são<br />

chamadas de “otimizações”, sendo o termo otimização não muito preciso, já que não<br />

há garantias de que o código resultante é o melhor possível.<br />

O nível e o tipo de otimizações podem variar entre otimizações<br />

independentes de máquina e otimizações dependentes de máquina. As<br />

independentes são normalmente simplificações de expressões através de regras<br />

matemáticas como no exemplo: x = x * 1. As dependentes podem ocorrer em função<br />

da plataforma destino, como o uso de registradores e operações especiais de<br />

máquina.<br />

30


2. PORTUGOL<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

O portugol como linguagem não é bem definido, variando de autor para<br />

autor. Na maioria das vezes é apenas uma tradução de Pascal para o português,<br />

inclusive trazendo símbolos que o tornam perigoso para uso no estudo de<br />

algoritmos, justamente por o tornar tão dependente de uma certa linguagem. O<br />

<strong>Portugol</strong>, aqui definido, será baseado em [FARRER], mas com algumas<br />

modificações, principalmente, nas estruturas de repetição e de bloco.<br />

2.1. COMENTÁRIOS<br />

Várias formas de comentários são aceitas, com o objetivo de se estimular<br />

seu uso no código. Tanto o // usado no C e C++ quanto o # (cerquilha) usado no<br />

Shell do Unix são aceitos como comentários de uma linha. Os { } (colchetes) são a<br />

única forma aceita de comentários para várias linhas ou comentários de bloco.<br />

2.2. TIPOS BÁSICOS<br />

Como o objetivo do <strong>Portugol</strong> aqui definido é o ensino de lógica de<br />

programação e algoritmos, os tipos básicos serão o mais restritos possíveis, a fim de<br />

promover a independência de linguagem e de máquina.<br />

2.2.1. Numérico<br />

O tipo numérico resume todos os tipos para cálculo aritmético. Não se faz<br />

distinção entre números inteiros ou números reais (ponto flutuante). Caso um<br />

algoritmo necessite de alguma propriedade específica de algum desses tipos deverá<br />

especificá-la através de funções. A vírgula é o símbolo usado para separar a parte<br />

decimal dos números. Não se escrevem os separadores de milhar.<br />

31


2.2.2. Literal<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Tipo responsável por armazenar seqüências de letras e símbolos, o<br />

popular tipo string de muitas linguagens. Para simplificar o entendimento do<br />

<strong>Portugol</strong>, o tipo caractere, será suprimido e tratado como um literal de comprimento<br />

um. O tratamento do tamanho do caractere será tratado via funções. A alocação de<br />

espaço para armazenamento é automática.<br />

2.2.3. Lógico<br />

Responsável pelo armazenamento das constantes verdadeiro e falso. O<br />

tipo lógico é muito importante na definição de algoritmos, sendo o tipo básico<br />

retornado pela execução de várias operações.<br />

2.2.4. Vetores e matrizes<br />

É permitida a criação de vetores e matrizes de qualquer tipo básico,<br />

incluindo registros definidos pelo usuário. As operações sobre matrizes e vetores<br />

deverão ser especificadas na forma de algoritmos escritos em <strong>Portugol</strong>, logo não são<br />

definidas na linguagem. As operações básicas deste tipo são as mesmas permitidas<br />

em seus tipos básicos. A palavra-chave matriz é reservada para este tipo. A base ou<br />

número inicial dos índices sempre é 1.<br />

Exemplo:<br />

a matriz numérico[30] // Cria uma matriz 30x1<br />

b matriz lógico[3][3] // Cria uma matriz 3x3<br />

2.2.5. Registros<br />

São definidos pela palavra-chave registro e são compostos pelos campos<br />

declarados, da mesma forma que variáveis, até a palavra fimregistro.<br />

Exemplo:<br />

registro dia, mês, ano numérico<br />

nome literal<br />

matriculado lógico<br />

fimregistro<br />

32


2.3. VARIÁVEIS E IDENTIFICADORES<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

As variáveis são uma importante parte da linguagem. Qualquer<br />

identificador válido tem como primeiro símbolo uma letra. Números e _ (sublinha)<br />

são aceitos após o segundo caractere. Fica estabelecido o tamanho máximo de 32<br />

caracteres para o tamanho do maior nome válido.<br />

É importante observar que símbolos ignorados ou proibidos por outros<br />

compiladores são aceitos em <strong>Portugol</strong>. Como exemplo os caracteres acentuados da<br />

língua portuguesa: â, á, ã, à, ê, é, è, ..., ç.<br />

Uma vez declarado um nome de identificador com acentos, estes não<br />

serão considerados opcionais. Assim sendo, a variável avião é diferente da variável<br />

aviao. Não há distinção entre maiúsculas e minúsculas.<br />

2.4. DECLARAÇÃO DE VARIÁVEIS<br />

Não há uma seção específica para declaração de variáveis, mas esta<br />

deve ser feita no início de uma seção, seja o programa principal ou um<br />

procedimento/função. O comando declare será usado para declarar as variáveis em<br />

<strong>Portugol</strong>, sendo permitida a enumeração de identificadores do mesmo tipo, mas não<br />

a declaração de tipos diferentes na mesma linha.<br />

Exemplo:<br />

declare a, b, c numérico<br />

declare d, e, f literal<br />

declare g, h, i lógico<br />

declare j registro dia, mês, ano inteiro<br />

nome literal<br />

matriculado lógico<br />

fimregistro<br />

Exemplo de declaração inválida:<br />

declare a numérico, b literal<br />

33


declarou.<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

A visibilidade de uma variável é definida pelo escopo da estrutura que a<br />

2.5. ATRIBUIÇÃO<br />

A atribuição de valores será denotada pelo símbolo :=.<br />

Só é permitido a atribuição de um valor por vez. Construções do tipo<br />

a:=b:=c:=0 não são aceitas. Uma atribuição válida possui um identificador válido à<br />

esquerda e uma expressão do mesmo tipo do identificador a direita.<br />

Exemplos:<br />

declare a,b numérico<br />

declare c,d literal<br />

declare e,f lógico<br />

a := 5<br />

b := 4,5<br />

2.6. OPERADORES<br />

2.6.1. Operadores Aritméticos<br />

Tabela 4 - Operadores aritméticos<br />

Operação Símbolo<br />

Adição +<br />

Subtração -<br />

Divisão /<br />

Multiplicação *<br />

34


2.6.2. Operadores Lógicos<br />

Tabela 5 - Operadores lógicos<br />

Operação Símbolo<br />

inversão <strong>–</strong> não não<br />

junção e<br />

disjunção ou<br />

2.6.3. Operadores Relacionais<br />

2.6.4. Operadores Literais<br />

Tabela 6 - Operadores Relacionais<br />

Operação Símbolo<br />

Igualdade =<br />

Maior ><br />

Menor <<br />

Maior ou igual >=<br />

Menor ou igual <br />

Menor <<br />

Maior ou igual >=<br />

Menor ou igual


2.7. ESTRUTURA SEQÜENCIAL<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

O programa começa com a palavra programa e termina em<br />

fimprograma. A importação de outros módulos deve ser especificada como um<br />

comando, logo após a declaração de programa.<br />

Em portugol não se utilizam símbolos especiais ou visuais para marcar o<br />

fim de linha e sim o retorno de carro, mais conhecido pela tecla ENTER, definido na<br />

posição 13 da tabela ASCII. Para manter uma independência de sistemas<br />

operacionais, mas para não dificultar a criação dos programas, seqüências de<br />

símbolos 10 e 13, utilizadas no MS-DOS, como o 10 do UNIX serão tratadas como<br />

fim de linha.<br />

Qualquer símbolo ou comando, exceto comentários, feitos fora da<br />

declaração de programa serão considerados erro. Funções e procedimentos devem<br />

ser declarados em módulos externos e importados pelo programa que as utilize.<br />

Esta decisão visa estimular a modularização do código, bem como a criação de<br />

arquivos menores e mais fáceis de entender.<br />

2.8. ESTRUTURAS CONDICIONAIS<br />

Apenas duas são definidas em <strong>Portugol</strong>, o se e o caso.<br />

O se avalia uma condição ou expressão condicional, que<br />

obrigatoriamente retorna um valor lógico. Dependendo deste valor a execução passa<br />

para o bloco então, ou senão, para valores verdadeiros e falsos, respectivamente. A<br />

fim de eliminar a criação de blocos, tipo início e fim, define-se em <strong>Portugol</strong> o<br />

fimentão e o fimsenão, de uso obrigatório.<br />

Exemplo:<br />

se a > b<br />

então a = 1<br />

fimentão<br />

senão b = 1<br />

fimsenão<br />

fimse<br />

36


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

A estrutura caso permite a avaliação de múltiplos valores e admite<br />

variável dos tipos lógico, numérico e literal.<br />

caso idade<br />

10: i := 10<br />

20: j := 10<br />

30: k := 30<br />

fimcaso<br />

2.9. ESTRUTURAS DE REPETIÇÃO<br />

Utiliza-se o faça, enquanto e repita.<br />

O faça substitui o for da maioria das outras linguagens. Sua construção é<br />

demonstrada abaixo:<br />

faça a de 1 até 10<br />

<br />

fimfaça<br />

A estrutura acima executará os comandos dez vezes, variando o valor de<br />

a de 1 até 10. A variável de controle, no exemplo acima “a”, não deve ter seu valor<br />

alterado pelos comandos internos. Sempre ao chegar no fimfaça o valor da variável<br />

de controle é incrementado de 1. O valor de “a” após o fimfaça será igual ao limite<br />

estipulado, no caso 10.<br />

O enquanto substitui o while.<br />

enquando a > b<br />

<br />

fimenquanto<br />

A estrutura enquanto executa o bloco de comandos até que a condição<br />

seja falsa. É importante notar que os comandos podem nem ser executados,<br />

dependendo da condição inicial.<br />

O repita é definido como uma estrutura de repetição básica. O ponto de<br />

verificação e interrupção é livre, sendo especificado pelo comando interrompa.<br />

repita<br />

<br />

37


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

interrompa<br />

fimrepita<br />

Após a execução do interrompa, a execução vai para depois de<br />

fimrepita.<br />

2.10. PROCEDIMENTOS E FUNÇÕES<br />

Procedimentos e funções seguem as mesmas regras de um programa,<br />

exceto por não poderem importar módulos.<br />

A declaração de procedimento é exemplificada abaixo:<br />

procedimento calculaA ( i numérico<br />

j literal<br />

k lógico<br />

)<br />

<br />

fimprocedimento<br />

As variáveis declaradas em uma função ou procedimento são internas a<br />

eles, ou seja, possuem escopo local.<br />

Para denotar a passagem por parâmetro, colocamos o prefixo param<br />

antes do nome do parâmetro. Exemplo:<br />

procedimento calculaA ( param i numérico<br />

j literal<br />

k lógico<br />

)<br />

<br />

fimprocedimento<br />

Neste caso somente o parâmetro i é passado por referência. Caso haja<br />

mais de um parâmetro na mesma linha, todos serão marcados como passados por<br />

referência:<br />

procedimento calculaA (param i, j, k numérico)<br />

38


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

As funções obedecem todas as regras e possuem todas as propriedades<br />

dos procedimentos. O que diferencia uma função é sua capacidade de retornar um<br />

valor. O valor a ser retornado deve ser atribuído a um identificador, com o mesmo<br />

nome e tipo da função de seu tipo de retorno, antes do fimfunção. Observar que<br />

esta atribuição não força o retorno, o que só ocorre ao executarmos o fimfunção.<br />

Exemplo:<br />

função calculaB( i numérico<br />

j literal<br />

k lógico<br />

) numérico<br />

<br />

calculaB:=r<br />

fimfunção<br />

2.11. MÓDULOS<br />

Os módulos iniciam com a palavra módulo seguida do nome e terminam<br />

com fimmodulo. Este nome deve ser utilizado na hora de importar o módulo no<br />

programa principal ou em outro módulo, através da cláusula importe.<br />

As variáveis declaradas dentro do módulo, mas fora de funções e<br />

procedimentos são globais ao módulo, podendo ser acessadas de fora se utilizando<br />

o nome do módulo seguido de ponto e nome da variável. Não é permitida a<br />

repetição de nomes de módulos ou a re-declaração destes na forma de variável.<br />

2.12. FUNÇÕES PRÉ-DEFINIDAS<br />

Tabela 8 - Funções pré-definidas<br />

Formato Função<br />

inteiro(x numérico) numérico Retorna a parte inteira de um número.<br />

tamanho(y literal) numérico Retorna o tamanho em caracteres de uma<br />

variável literal. 0 caso esteja vazia.<br />

ordem(x literal) numérico Retorna o valor correspondente ao primeiro<br />

caractere da seqüência passada na tabela<br />

39


Formato Função<br />

ASCII.<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

caractere(x numérico) literal Retorna o caractere correspondente a posição<br />

denotada por x na tabela ASCII.<br />

número(x literal) numérico Converte uma seqüência literal em número.<br />

Caso não consiga, retorna 0.<br />

lit(n numérico) literal Converte um número em seqüência literal.<br />

2.13. ESPECIFICAÇÃO BNF 1<br />

S = “programa” identificador novalinha comandos “fimprograma” novalinha<br />

digito = [“0”| ”1”| ”2”| “3”| ”4”| ”5”| ”6”| ”7”| “8”| ”9”]<br />

letras-minusculas = [“a”|”b”|”c”|”d”| “e”| “f”| “g”| “h”| “i”| “j”| “k”| “l”| “m”| “n”| “o”| “p”|<br />

“q”| “r”|”s”|”t”| “u”| “v”| “w”| “x”| “y”| “z”| “á”| “é”| “í”| “ó”| “ú”| “ý”|<br />

“ã”| “õ”| “ñ”| “à”| “è”| “ì”| “ò”| “ù”| “ä”| “ë”| “ï”| “ö”| “ü”| “ÿ”| “â”| “ê”|<br />

“î”| “ô”| “û”| “ç”]<br />

letras-maiusculas = [“A”|”B”|”C”|”D”| “E”| “F”| “G”| “H”| “I”| “J”| “K”| “L”| “M”| “N”| “O”|<br />

“P”| “Q”| “R”|”S”|”T”| “U”| “V”| “W”| “X”| “Y”| “Z”| “Á”| “É”| “Í”| “Ó”|<br />

“Ú”| “Ý”| “Ô| “Õ”| “Ñ”| “À”| “È”| “Ì”| “Ò”| “Ù”| “Ä”| “Ë”| “Ï”| “Ö”|<br />

“Ü”| “Ÿ”| “”| “Ê”| “Δ| “Ô”| “Û”| “Ç”]<br />

letra = (letras-minusculas|letras-maiusculas)<br />

numeral = digito{digito}<br />

numero = [+|-] numeral<br />

valor = numero | identificador<br />

literal = \"{*}\"<br />

logico = “verdadeiro” | ”falso”<br />

identificador = letra{letra|digito|”_”}<br />

novalinha = \n | \r | \n\r<br />

op-logico = “não” | “e” | “ou”<br />

op-numerico = “+” | “-“ | “*” | “/”<br />

op-literal = “+” | “=” | “>” | “=” | “


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

op-relacional = “” | “>=” | “


expressao-logica = valor-logico |<br />

expressão-numerica op-relacional expressao-numerica |<br />

valor-logico op-logico expressao-logica<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

42


3. O COMPILADOR PORTUGOL<br />

3.1. ANALISADOR LÉXICO<br />

3.2. ANALISADOR SINTÁTICO<br />

3.3. GERADOR DE CÓDIGO<br />

3.4. FUNÇÕES ADICIONAIS<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

43


4. A MÁQUINA VIRTUAL<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

A máquina virtual escolhida é baseada na de WIRTH (1996), que por<br />

sua vez se baseia na máquina DLX de Hannessy e Patterson (1995) 2 , aproximandose<br />

da arquitetura da máquina MIPS.<br />

O conjunto completo de instruções da máquina DLX encontra se no<br />

apêndice C. O subconjunto particular implementado é descrito a seguir.<br />

4.1. REGISTRADORES<br />

Registradores são memórias especiais à disposição do processador<br />

para diversos fins. Em linguagem de máquina, valores são guardados na memória e<br />

as operações com estes são realizadas nos registradores. Diversas instruções,<br />

especialmente em máquinas RISC, utilizam registradores como seus operandos.<br />

Diferente de máquinas CISC (conjunto de instruções complexo) que possuem<br />

dúzias de formas diferentes de endereçamento (gerando uma instruções para cada<br />

um deles), as máquinas RISC trocam o número de instruções pelo número de<br />

registradores. Uma máquina CISC tem normalmente de 4 a 6 registradores e<br />

enquanto máquinas RISC operam com 32. Este número também é justificado pelo<br />

pequeno número de formas de endereçamento disponível para máquinas RISC, o<br />

que obriga que valores sejam movidos da memória para um registrador antes de<br />

serem utilizados em uma instrução.<br />

A máquina virtual possui 32 registradores de 32 bits cada. Estes<br />

registradores são nomeados de R0 a R31, sendo alguns de uso específico:<br />

R0 sempre contém o valor 0.<br />

R31 é utilizado para armazenar o endereço de retorno em instruções<br />

de salto.<br />

2 HANNESEY J.L., PATTERSON D.A. Computer Architecture <strong>–</strong> A Quantitative<br />

Approach. Morgan Kaufmann:1995<br />

44


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

IR, ou Instruction Register, contém a instrução atualmente sendo<br />

executada.<br />

PC, ou Program Counter, contém o endereço da próxima instrução a<br />

ser lida da memória.<br />

4.2. FORMATO DE INSTRUÇÕES<br />

A máquina virtual utiliza três formatos de instruções:<br />

Formato 1 <strong>–</strong> Operações com constantes<br />

6 5 5 16<br />

Op a b c<br />

op é o código de 6 bits do opcode<br />

a é o número de um registrador (5 bits)<br />

b é o número de um registrador (5 bits)<br />

c é a constante de 16 bits<br />

Formato 2 <strong>–</strong> Operações com registros<br />

6 5 5 11 5<br />

Op a b c<br />

op é o código de 6 bits do opcode<br />

a é o número de um registrador (5 bits)<br />

b é o número de um registrador (5 bits)<br />

c é o número de um registrador (5 bits)<br />

Formato 3 <strong>–</strong> Operações de Salto<br />

6 26<br />

Op c<br />

op é o código de 6 bits do opcode<br />

c é o deslocamento com 26 bits<br />

45


4.3. INSTRUÇÕES<br />

Instrução Significado Formato Descrição<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

ADD a,b,c R.a := R.b + R.c 2 Adição entre registradores<br />

ADDI a,b,c R.a := R.b + c 1 Adição com constante<br />

SUB a,b,c R.a := R.b - R.c 2 Subtração entre<br />

registradores<br />

SUBI a,b,c R.a := R.b - c 1 Subtração com constante<br />

MUL a,b,c R.a := R.b * R.c 2 Multiplicação entre<br />

registradores<br />

MULI a,b,c R.a := R.b * c 1 Multiplicação com constante<br />

DIV a,b,c R.a := R.b / R.c 2 Divisão entre registradores<br />

DIVI a,b,c R.a := R.b / c 1 Divisão com constante<br />

MOD a,b,c R.a := Rb % R.c 2 Módulo entre registradores<br />

MODI a,b,c R.a := Rb % c 1 Módulo com constante<br />

CMP a,b,c R.a := Ra <strong>–</strong> Rc 2 Comparação entre<br />

registradores<br />

CMPI a,b,c R.a := Ra <strong>–</strong> c 1 Comparação com constante<br />

CHK a,c 0


Instrução Significado Formato Descrição<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

XOR a,b,c R.a := R.b ^ R.c 2 Ou exclusivo entre<br />

registradores<br />

XORI a,b,c R.a := R.b ^ c 1 Ou exclusivo com constante<br />

LSH a,b,c R.a := LSH(R.b,R.c) 2 Deslocamento à esquerda<br />

LSHI a,b,c R.a := LSH(R.b, c) 1 Deslocamento à esquerda<br />

com constante<br />

ASH a,b,c R.a := ASH(R.b,R.c) 2 Ajuste aritmético entre<br />

registradores<br />

ASHI a,b,c R.a := ASH(R.b,c) 1 Ajuste aritmético com<br />

constante<br />

LDW a,b,c R.a := Mem[R.b+c] 1 Carrega palavra<br />

LDB a,b,c R.a := Mem[R.b+c] 1 Carrega byte<br />

POP a,b,c R.a := Mem[R.b];<br />

R.b := R.b+c<br />

1 Retira da pilha (pop)<br />

STW a,b,c Mem[R.b+c]:=R.a 1 Armazena palavra<br />

STB a,b,c Mem[R.b+c]:=R.a 1 Armazena byte<br />

PSH a,b,c R.b:=R.b-c;<br />

Mem[R.b]:=R.a<br />

1 Coloca na pilha (push)<br />

BEQ a,c 2 Salta para c seR.a = 0<br />

BNE a,c 2 Salta para c seR.a 0<br />

BLT a,c 2 Salta para c seR.a < 0<br />

BGE a,c 2 Salta para c seR.a >= 0<br />

BGT a,c 2 Salta para c seR.a > 0<br />

BLE a,c 2 Salta para c seR.a


4.4. LIMITAÇÕES<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

A máquina implementada não possui sistema operacional ou suporte a<br />

operações de ponto flutuante. Tais limitações são candidatas para futuras extensões<br />

deste projeto.<br />

A implementação de ponto flutuante exige o suporte de instruções para<br />

operação de simples e dupla precisão, bem como suporte aos registradores de<br />

ponto flutuante. Instruções para conversão de tipo também são necessárias. A<br />

adoção de um padrão numérico deve observar as normas do IEEE<br />

4.5. IMPLEMENTAÇÃO<br />

A máquina virtual encontra-se nos arquivos RISC.H e RISC.CPP,<br />

ambos no anexo A.<br />

48


CONCLUSÃO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

O estudo de compiladores se mostra fundamental, não só para a área de<br />

compilação, mas para diversos assuntos afins. Compreender o processo de<br />

construção e implementação de uma linguagem é um processo rico e proveitoso. A<br />

criação do ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong> é de grande valor para futuras extensões<br />

e pode ser o embrião para projetos mais ambiciosos, como orientação a objetos e<br />

interface gráfica, entre outros.<br />

49


REFERÊNCIA BIBLIOGRÁFICA<br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

AHO, Alfred. SETHI, Ravi. ULLMAN Jeffrey. <strong>Compilador</strong>es <strong>–</strong> Princípios, Técnicas e<br />

Ferramentas. 1. ed. <strong>–</strong> Rio de Janeiro: LTC <strong>–</strong> Livros Técnicos e Científicos:1995.<br />

FARRER, Henry. BECKER, Cristiano Gonçalves. FARIA, Eduardo Chaves. MATOS,<br />

Helton Fábio de. SANTOS, Marcos Augusto. MAIA, Miriam Lourenço. Programação<br />

Estruturada de Computadores - Algoritmos Estruturados. 2. ed. <strong>–</strong> Rio de Janeiro:<br />

Editora Guanabara: 1989<br />

FRIEDL, Jeffrey E. F. Mastering Regular Expressions <strong>–</strong> Powerful Techniques for Perl<br />

and Other Tools. 7. ed. <strong>–</strong> Sebastopol, Califórnia, EEUU:O’Reilly Associates:1998.<br />

MENEZES, Paulo Blauth. Linguagens Formais e Autômatos. 4. ed. - Porto Alegre:<br />

Instituto de Informática da UFRGS:Editora Sagra Luzzatto:2001<br />

PRICE, Ana Maria de Alencar. TOSCANI, Simão Sirineo. Implementação de<br />

Linguagens de Programação: <strong>Compilador</strong>es. 1. ed. - Porto Alegre: Instituto de<br />

Informática da UFRGS:Editora Sagra Luzzatto:2000<br />

SEBESTA, Robert W. Conceitos de Linguagens de Programação. 4. ed. <strong>–</strong> Porto<br />

Alegre:Bookman:2000.<br />

WIRTH, Niklaus. Compiler Construction. 1. ed. <strong>–</strong> Essex, Inglaterra:Addison-<br />

Wesley:1996.<br />

50


SCANNER.H<br />

#ifndef ISCANNER<br />

#define ISCANNER<br />

#include "funcoes.h"<br />

// Tamanho do maior identificador<br />

#define IdLen 32<br />

// Número máximo de palavras chaves<br />

#define KW 50<br />

APÊNDICE A <strong>–</strong> CÓDIGO FONTE<br />

#define LISTA_DE_ACENTOS "áéíóúâêîôûäëïöüÿãõàèìòùñç"<br />

/*<br />

#define null 0<br />

#define times 1<br />

#define div 3<br />

#define mod 4<br />

#define and 5<br />

#define plus 6<br />

#define minus 7<br />

#define or 8<br />

#define eql 9<br />

#define neq 10<br />

#define lss 11<br />

#define geq 12<br />

#define leq 13<br />

#define gtr 14<br />

#define period 18<br />

#define comma 19<br />

#define colon 20<br />

#define rparen 22<br />

#define rbrak 23<br />

#define of 25<br />

#define then 26<br />

#define DO 27<br />

#define lparen 29<br />

#define lbrak 30<br />

#define not 32<br />

#define becomes 33<br />

#define number 34<br />

#define ident 37<br />

#define semicolon 38<br />

#define END 40<br />

#define ELSE 41<br />

#define ELSIF 42<br />

#define IF 44<br />

#define WHILE 46<br />

Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

51


#define ARRAY 54<br />

#define RECORD 55<br />

#define CONST 57<br />

#define TYPE 58<br />

#define VAR 59<br />

#define PROCEDURE 60<br />

#define BEGIN 61<br />

#define MODULE 63<br />

#define eof 64<br />

#define TRUE 1<br />

#define FALSE 0<br />

*/<br />

#define MAXLONGINT 1000000<br />

#define NULO 0<br />

#define NUMERICO 1<br />

#define LITERAL 2<br />

#define LOGICO 3<br />

#define MATRIZ 4<br />

#define REGISTRO 5<br />

#define FIMREGISTRO 6<br />

#define DECLARE 7<br />

#define PROGRAMA 8<br />

#define FIMPROGRAMA 9<br />

#define SE 10<br />

#define FIMSE 11<br />

#define ENTAO 12<br />

#define SENAO 13<br />

#define FIMENTAO 14<br />

#define FIMSENAO 15<br />

#define CASO 16<br />

#define FIMCASO 17<br />

#define DEFINA 18<br />

#define FACA 20<br />

#define FIMFACA 21<br />

#define ENQUANTO 22<br />

#define FIMENQUANTO 23<br />

#define REPITA 24<br />

#define FIMREPITA 25<br />

#define INTERROMPA 26<br />

#define DE 27<br />

#define ATE 28<br />

#define PROCEDIMENTO 30<br />

#define FIMPROCEDIMENTO 31<br />

#define FUNCAO 32<br />

#define FIMFUNCAO 33<br />

#define MODULO 40<br />

#define FIMMODULO 41<br />

#define INTEIRO 50<br />

#define TAMANHO 51<br />

#define ORDEM 52<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

52


#define CARACTERE 53<br />

#define NUMERO 54<br />

#define LIT 55<br />

#define ATRIBUICAO 60<br />

#define MAIS 61<br />

#define MENOS 62<br />

#define DIVISAO 63<br />

#define MULTIPLICACAO 64<br />

#define RESTO 65<br />

#define NAO 70<br />

#define E 71<br />

#define OU 72<br />

#define IGUAL 80<br />

#define MAIOR 81<br />

#define MENOR 82<br />

#define MAIOR_IGUAL 83<br />

#define MENOR_IGUAL 84<br />

#define DIFERENTE 85<br />

#define VIRGULA 86<br />

#define PONTO 87<br />

#define DOIS_PONTOS 88<br />

#define VERDADEIRO 90<br />

#define FALSO 91<br />

#define PARENTESE_E 92<br />

#define PARENTESE_D 93<br />

#define CHAVE_E 94<br />

#define CHAVE_D 95<br />

#define IDENTIFICADOR 96<br />

#define ENUMERO 97<br />

#define NOVALINHA 100<br />

#define FDA 101<br />

#define TIPO 102<br />

#define VARIAVEL 103<br />

#define CONSTANTE 104<br />

#define LITERALVALOR 105<br />

#define NUMEROVALOR 106<br />

#define BOOLEANOVALOR 107<br />

#define COLCHETE_E 108<br />

#define COLCHETE_D 109<br />

typedef char Ident[IdLen];<br />

// Valores temporários<br />

extern long val;<br />

extern char sval[255];<br />

extern bool bval;<br />

extern Ident id;<br />

extern unsigned int error;<br />

extern char ch;<br />

extern int numerodeid;<br />

extern long errpos;<br />

extern long linha;<br />

extern long coluna;<br />

extern FILE *R;<br />

extern FILE *W;<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

53


Listas de tokens<br />

extern char comandos[MAX_ELEM_CJ];<br />

extern char fimdecomandos[MAX_ELEM_CJ];<br />

extern char cjfator[MAX_ELEM_CJ];<br />

void Mark (char *msg);<br />

void fIdent (int &sym);<br />

void Number (int &sym);<br />

//void comment (int &sym);<br />

void Get (int &sym);<br />

void EnterKW (int sym, char *name);<br />

void Init (long pos, FILE *C);<br />

void mainScanner (void);<br />

char leiaMinC(FILE *R);<br />

#endif<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

54


SCANNER.CPP<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

/*<br />

* Módulo OSS - Scanner Universidade do Amazonas Comport - <strong>Compilador</strong><br />

* <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

*<br />

* Baseado no compilador Oberon-0 de Niklaus Wirth<br />

*<br />

*/<br />

#define SCANNER<br />

#include <br />

#include <br />

#include <br />

#include <br />

#include "scanner.h"<br />

#include "funcoes.h"<br />

long val;<br />

char sval[255]={0};<br />

bool bval=false;<br />

// Identificador<br />

// id é usado para retornar o resultado da pesquisa de um identificador<br />

Ident id;<br />

// Código do erro<br />

unsigned int error;<br />

char ch;<br />

// Número de palavras chaves cadastradas<br />

// numerodeid e KW é o máximo<br />

int numerodeid;<br />

// Posição do erro<br />

long errpos;<br />

long linha=1;<br />

long coluna=1;<br />

// R é o arquivo fonte em <strong>Portugol</strong><br />

FILE *R;<br />

// W é o stdout, mas pode ser usada para redirecionar a saída se necessário<br />

FILE *W;<br />

// Estrutura que armazena as palavras-chaves já cadastradas,<br />

// Associando um código (sym) com o nome da palavra-chave (id)<br />

struct<br />

{<br />

int sym;<br />

char id[IdLen];<br />

}<br />

keyTab[KW]; // Vetor de palavras-chave<br />

55


char comandos[MAX_ELEM_CJ];<br />

char fimdecomandos[MAX_ELEM_CJ];<br />

char cjfator[MAX_ELEM_CJ];<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

// Função usada para ler um caracter e converte-lo para minuscula<br />

char leiaMinC(FILE *R)<br />

{<br />

return minusculaC(fgetc(R));<br />

}<br />

// Função usada para imprimir mensagens de erro<br />

void<br />

Mark (char *msg)<br />

{<br />

long p;<br />

p = ftell (R);<br />

if (p > errpos)<br />

{<br />

fprintf (W, " Linha: %d Coluna: %d Posição %d %s\n", linha, pcoluna+1,<br />

p, msg);<br />

}<br />

errpos = p;<br />

error = VERDADEIRO;<br />

}<br />

// Função usada para ler e localizar um identificador<br />

void<br />

fIdent (int &sym)<br />

{<br />

int i = 0, k;<br />

do<br />

{<br />

if (i < IdLen)<br />

{<br />

id[i] = ch;<br />

i++;<br />

}<br />

ch = minusculaC(fgetc (R));<br />

}<br />

while ((ch >= '0' && ch = 'a' && ch


}<br />

sym = ENUMERO;<br />

do<br />

{<br />

if (val = '0' && ch


}<br />

do<br />

{<br />

while (ch == '{')<br />

{<br />

ch = fgetc (R);<br />

if (ch == '*')<br />

Comentario (sym);<br />

}<br />

if (ch == '*')<br />

{<br />

ch = fgetc (R);<br />

break;<br />

}<br />

if (feof (R))<br />

break;<br />

ch = fgetc (R);<br />

}<br />

while (1);<br />

if (ch == ')')<br />

{<br />

ch = fgetc (R);<br />

break;<br />

}<br />

if (feof (R))<br />

{<br />

Mark ("Comentário não terminado");<br />

break;<br />

}<br />

}<br />

while (1);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

// Função mais importante do parser. Usada para caminhar na árvore léxica<br />

// Sempre é chamada para identificar o tipo do próximo sym.<br />

void<br />

Get (int &sym)<br />

{<br />

// Ignora espaços e caracteres de controle<br />

while (!feof (R) && ch


case '-':<br />

ch = fgetc (R);<br />

sym = MENOS;<br />

break;<br />

case '=':<br />

ch = fgetc (R);<br />

sym = IGUAL;<br />

break;<br />

// case '#':<br />

// ch = fgetc (R);<br />

// sym = ;<br />

// break;<br />

case '')<br />

{<br />

ch=leiaMinC(R);<br />

sym = DIFERENTE;<br />

}<br />

else<br />

{<br />

sym = MENOR;<br />

}<br />

break;<br />

case '>':<br />

ch = fgetc (R);<br />

if (ch == '=')<br />

{<br />

ch = fgetc (R);<br />

sym = MAIOR_IGUAL;<br />

}<br />

else<br />

{<br />

sym = MAIOR;<br />

}<br />

break;<br />

case 10: // LF<br />

case 13: // NL<br />

do<br />

{<br />

ch=leiaMinC(R);<br />

} while (ch==13 || ch==10);<br />

sym = NOVALINHA;<br />

linha++;<br />

coluna=ftell(R);<br />

break;<br />

case ',':<br />

ch = fgetc (R);<br />

sym = VIRGULA;<br />

break;<br />

case '"':<br />

Literal(sym);<br />

break;<br />

case ':':<br />

ch = fgetc (R);<br />

if (ch == '=')<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

59


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

{<br />

ch = fgetc (R);<br />

sym = ATRIBUICAO;<br />

}<br />

else<br />

{<br />

sym = DOIS_PONTOS;<br />

}<br />

break;<br />

case '.':<br />

ch = fgetc (R);<br />

sym = PONTO;<br />

break;<br />

//NILO: Ver o caso do comentário // e #<br />

case '(':<br />

ch = fgetc (R);<br />

if (ch == '*')<br />

{<br />

Comentario (sym);<br />

Get (sym);<br />

}<br />

else<br />

sym = PARENTESE_E;<br />

break;<br />

case ')':<br />

ch = fgetc (R);<br />

sym = PARENTESE_D;<br />

break;<br />

//NILO: Mudar de chave para colchete<br />

case '[':<br />

ch = fgetc (R);<br />

sym = COLCHETE_E;<br />

break;<br />

case ']':<br />

ch = fgetc (R);<br />

sym = COLCHETE_D;<br />

break;<br />

// case '~':<br />

// ch = fgetc (R);<br />

// sym = not;<br />

// break;<br />

default:<br />

if ((ch >= 'A' && ch = 'a' && ch = '0' && ch


{<br />

}<br />

error = FALSO;<br />

errpos = pos;<br />

R = C;<br />

ch = fgetc (R);<br />

void<br />

EnterKW (int sym, char *name)<br />

{<br />

keyTab[numerodeid].sym = sym;<br />

strcpy (keyTab[numerodeid].id, name);<br />

numerodeid++;<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

// Para testar o cadastro de identificadores, defina SPRINCIPAL.<br />

// Isso fará com que a mainScanner se torne a main<br />

#ifndef SPRINCIPAL<br />

void mainScanner(void)<br />

#else<br />

int main (int argc, char **argv)<br />

#endif<br />

{<br />

W = stdout;<br />

error = VERDADEIRO;<br />

numerodeid = 0; // Inicializa o índice de palavras-chave<br />

EnterKW( NUMERICO, "numérico"); // 1<br />

EnterKW( LITERAL, "literal"); // 2<br />

EnterKW( LOGICO, "lógico"); // 3<br />

EnterKW( MATRIZ, "matriz"); // 4<br />

EnterKW( REGISTRO, "registro"); // 5<br />

EnterKW( FIMREGISTRO, "fimregistro"); // 6<br />

EnterKW( DECLARE, "declare"); // 7<br />

EnterKW( PROGRAMA, "programa"); // 8<br />

EnterKW( FIMPROGRAMA, "fimprograma"); // 9<br />

EnterKW( SE, "se"); // 10<br />

EnterKW( FIMSE, "fimse"); // 11<br />

EnterKW( ENTAO, "então"); // 12<br />

EnterKW( SENAO, "senão"); // 13<br />

EnterKW( FIMENTAO, "fimentão"); // 14<br />

EnterKW( FIMSENAO, "fimsenão"); // 15<br />

EnterKW( CASO, "caso"); // 16<br />

EnterKW( FIMCASO, "fimcaso"); // 17<br />

EnterKW( FACA, "faça"); // 20<br />

EnterKW( FIMFACA, "fimfaça"); // 21<br />

EnterKW( ENQUANTO, "enquanto"); // 22<br />

EnterKW( FIMENQUANTO, "fimenquanto"); // 23<br />

EnterKW( REPITA, "repita"); // 24<br />

EnterKW( FIMREPITA, "fimrepita"); // 25<br />

EnterKW( INTERROMPA, "interrompa"); // 26<br />

EnterKW( DE, "de"); // 27<br />

EnterKW( ATE, "ate"); // 28<br />

EnterKW( PROCEDIMENTO,"procedimento");// 30<br />

EnterKW( FIMPROCEDIMENTO, "fimprocedimento"); // 31<br />

61


EnterKW( FUNCAO, "função"); // 32<br />

EnterKW( FIMFUNCAO, "fimfunção"); // 33<br />

EnterKW( MODULO, "módulo"); // 40<br />

EnterKW( FIMMODULO, "fimmódulo"); // 41<br />

EnterKW( INTEIRO, "inteiro"); // 50<br />

EnterKW( TAMANHO, "tamanho"); // 51<br />

EnterKW( ORDEM, "ordem"); // 52<br />

EnterKW( CARACTERE, "caractere"); // 53<br />

EnterKW( NUMERO, "número"); // 54<br />

EnterKW( LIT, "lit"); // 55<br />

// EnterKW( ATRIBUICAO 60<br />

// EnterKW( MAIS 61<br />

// EnterKW( MENOS 62<br />

// EnterKW( DIVISAO 63<br />

// EnterKW( MULTIPLICACAO 64<br />

EnterKW( NAO, "não"); // 70<br />

EnterKW( E, "e"); // 71<br />

EnterKW( OU, "ou"); // 72<br />

// EnterKW( IGUAL, ""); 80<br />

// EnterKW( MAIOR, ""); 81<br />

// EnterKW( MENOR, ""); 82<br />

// EnterKW( MAIOR_IGUAL, ""); 83<br />

// EnterKW( MENOR_IGUAL, ""); 84<br />

// EnterKW( DIFERENTE, ""); 85<br />

EnterKW( VERDADEIRO, "verdadeiro"); // 90<br />

EnterKW( FALSO, "falso"); // 91<br />

// EnterKW( NOVALINHA, "\n"); // 100<br />

// Conjuntos<br />

// Conjunto de Comandos (Statements)<br />

CriaConjunto(comandos);<br />

AdicionaConjunto(comandos, SE);<br />

AdicionaConjunto(comandos, FIMSE);<br />

AdicionaConjunto(comandos, ENTAO);<br />

AdicionaConjunto(comandos, FIMENTAO);<br />

AdicionaConjunto(comandos, SENAO);<br />

AdicionaConjunto(comandos, FIMSENAO);<br />

AdicionaConjunto(comandos, ENQUANTO);<br />

AdicionaConjunto(comandos, REPITA);<br />

AdicionaConjunto(comandos, FIMREPITA);<br />

AdicionaConjunto(comandos, FACA);<br />

AdicionaConjunto(comandos, FIMFACA);<br />

AdicionaConjunto(comandos, CASO);<br />

AdicionaConjunto(comandos, FIMCASO);<br />

AdicionaConjunto(comandos, MATRIZ);<br />

AdicionaConjunto(comandos, REGISTRO);<br />

AdicionaConjunto(comandos, FIMREGISTRO);<br />

AdicionaConjunto(comandos, DECLARE);<br />

AdicionaConjunto(comandos, FIMPROGRAMA);<br />

AdicionaConjunto(comandos, PROGRAMA);<br />

AdicionaConjunto(comandos, MODULO);<br />

AdicionaConjunto(comandos, FIMMODULO);<br />

AdicionaConjunto(comandos, PROCEDIMENTO);<br />

AdicionaConjunto(comandos, FIMPROCEDIMENTO);<br />

AdicionaConjunto(comandos, FUNCAO);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

62


AdicionaConjunto(comandos, FIMFUNCAO);<br />

AdicionaConjunto(comandos, FDA);<br />

CriaConjunto(fimdecomandos);<br />

AdicionaConjunto(fimdecomandos, FIMSE);<br />

AdicionaConjunto(fimdecomandos, FIMENTAO);<br />

AdicionaConjunto(fimdecomandos, FIMSENAO);<br />

AdicionaConjunto(fimdecomandos, FIMREPITA);<br />

AdicionaConjunto(fimdecomandos, FIMFACA);<br />

AdicionaConjunto(fimdecomandos, FIMCASO);<br />

AdicionaConjunto(fimdecomandos, MATRIZ);<br />

AdicionaConjunto(fimdecomandos, REGISTRO);<br />

AdicionaConjunto(fimdecomandos, FIMREGISTRO);<br />

AdicionaConjunto(fimdecomandos, DECLARE);<br />

AdicionaConjunto(fimdecomandos, FIMPROGRAMA);<br />

AdicionaConjunto(fimdecomandos, PROGRAMA);<br />

AdicionaConjunto(fimdecomandos, MODULO);<br />

AdicionaConjunto(fimdecomandos, FIMMODULO);<br />

AdicionaConjunto(fimdecomandos, PROCEDIMENTO);<br />

AdicionaConjunto(fimdecomandos, FIMPROCEDIMENTO);<br />

AdicionaConjunto(fimdecomandos, FUNCAO);<br />

AdicionaConjunto(fimdecomandos, FIMFUNCAO);<br />

AdicionaConjunto(fimdecomandos, FDA);<br />

CriaConjunto(cjfator);<br />

AdicionaConjunto(cjfator,NULO);<br />

AdicionaConjunto(cjfator,MULTIPLICACAO);<br />

AdicionaConjunto(cjfator,DIVISAO);<br />

AdicionaConjunto(cjfator,E);<br />

AdicionaConjunto(cjfator,MAIS);<br />

AdicionaConjunto(cjfator,MENOS);<br />

AdicionaConjunto(cjfator,OU);<br />

AdicionaConjunto(cjfator,IGUAL);<br />

AdicionaConjunto(cjfator,DIFERENTE);<br />

AdicionaConjunto(cjfator,MENOR);<br />

AdicionaConjunto(cjfator,MAIOR_IGUAL);<br />

AdicionaConjunto(cjfator,MENOR_IGUAL);<br />

AdicionaConjunto(cjfator,MAIOR);<br />

AdicionaConjunto(cjfator,VIRGULA);<br />

AdicionaConjunto(cjfator,DOIS_PONTOS);<br />

AdicionaConjunto(cjfator,PARENTESE_D);<br />

AdicionaConjunto(cjfator,CHAVE_D);<br />

AdicionaConjunto(cjfator,COLCHETE_D);<br />

AdicionaConjunto(cjfator,ENTAO);<br />

#ifdef SPRINCIPAL<br />

Init(0);<br />

if(argc==2)<br />

R=fopen(argv[1],"r");<br />

ch=leiaMinC(R);<br />

int i;<br />

for(i=0;i


eturn(0);<br />

#endif<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

64


PARSER.H<br />

#ifndef IPARSER<br />

#define IPARSER<br />

#include <br />

#include <br />

#include <br />

#include "scanner.h"<br />

#include "codegenerator.h"<br />

#include "risc.h"<br />

#include "funcoes.h"<br />

#define WordSize 4<br />

#ifndef PARSER<br />

extern int sym;<br />

extern int loaded;<br />

extern Object topScope;<br />

extern Object universe;<br />

extern Object guard;<br />

#endif<br />

#define VERSAO "0.92"<br />

void NewObj (Object & obj, int Class);<br />

void find (Object & obj);<br />

void FindField (Object & obj, Object list);<br />

int IsParam (Object obj);<br />

void OpenScope (void);<br />

void CloseScope (void);<br />

void selector (Item & x);<br />

void factor (Item & x);<br />

void term (Item & x);<br />

void SimpleExpression (Item & x);<br />

void expression (Item & x);<br />

void parameter (Object & fp);<br />

void param (Item & x);<br />

void StatSequence (void);<br />

void IdentList (int Class, Object & first);<br />

void fType (Type & type);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

65


void declarations (long varsize);<br />

void FPSection (long &parblksize);<br />

void ProcedureDecl (void);<br />

void Module (FILE * S);<br />

void Compile (FILE *C);<br />

void enter (int cl, long n, Ident name, Type type);<br />

void mainParser (void);<br />

#endif<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

66


PARSER.CPP<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

/*<br />

* Módulo OSP - Parser Universidade do Amazonas Comport - <strong>Compilador</strong><br />

* <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

*<br />

* Baseado no compilador Oberon-0 de Niklaus Wirth<br />

*<br />

*/<br />

#include <br />

#include <br />

#include <br />

#define PARSER<br />

#include "parser.h"<br />

#include "codegenerator.h"<br />

int sym, loaded;<br />

Object topScope, universe, guard;<br />

void<br />

NewObj (Object & obj, int Class)<br />

{<br />

Object nova, x;<br />

x = topScope;<br />

strcpy(guard->name, id);<br />

while (strcmp(x->next->name, id)!=0)<br />

x = x->next;<br />

if (x->next==guard)<br />

{<br />

nova = new ObjDesc;<br />

strcpy(nova->name, id);<br />

nova->Class = Class;<br />

nova->next = guard;<br />

x->next = nova;<br />

obj = nova;<br />

}<br />

else<br />

{<br />

obj = x->next;<br />

Mark ("Definição múltipla !");<br />

}<br />

}<br />

void<br />

find (Object & obj)<br />

{<br />

Object s, x;<br />

s = topScope;<br />

strcpy(guard->name, id);<br />

do<br />

{<br />

x = s->next;<br />

while (!strcmp (x->name, id))<br />

67


}<br />

x = x->next;<br />

if (x != guard)<br />

{<br />

obj = x;<br />

break;<br />

}<br />

if (s == universe)<br />

{<br />

obj = x;<br />

Mark ("Não definido");<br />

break;<br />

}<br />

s = s->dsc;<br />

}<br />

while (1);<br />

//NILO: Verificar se não há problema caso não encontre<br />

void<br />

FindField (Object & obj, Object list)<br />

{<br />

strcpy(guard->name,id);<br />

while (!strcmp (list->name, id))<br />

list = list->next;<br />

obj = list;<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

int<br />

IsParam (Object obj)<br />

{<br />

return (obj->Class == Par || obj->Class == Var && obj->val > 0);<br />

}<br />

void<br />

OpenScope (void)<br />

{<br />

Object s;<br />

s = new ObjDesc;<br />

s->Class = Head;<br />

s->dsc = topScope;<br />

s->next = guard;<br />

topScope = s;<br />

}<br />

void<br />

CloseScope (void)<br />

{<br />

topScope = topScope->dsc;<br />

}<br />

void<br />

selector (Item & x)<br />

{<br />

Item y;<br />

Object obj;<br />

while (sym == COLCHETE_E || sym == PONTO)<br />

{<br />

switch(sym)<br />

{<br />

case COLCHETE_E:<br />

68


}<br />

}<br />

}<br />

Get (sym);<br />

expression (y);<br />

if (x.type->form == MATRIZ)<br />

{<br />

Index (x, y);<br />

}<br />

else<br />

{<br />

Mark ("Não é uma matriz");<br />

}<br />

if (sym == COLCHETE_D)<br />

{<br />

Get (sym);<br />

}<br />

else<br />

Mark ("Falta ]?");<br />

break;<br />

case PONTO:<br />

Get (sym);<br />

if (sym == IDENTIFICADOR)<br />

{<br />

if (x.type->form == REGISTRO)<br />

{<br />

FindField (obj, x.type->fields);<br />

Get (sym);<br />

if (obj != guard)<br />

Field (x, obj);<br />

else<br />

Mark ("Não definido");<br />

}<br />

else<br />

Mark ("Não é um registro");<br />

}<br />

break;<br />

default:<br />

Mark ("IDENTIFICADOR?");<br />

//NILO: Verificar a equivalencia de Simbolos<br />

void<br />

factor (Item & x)<br />

{<br />

Object obj;<br />

if (PertenceConjunto(cjfator, sym))<br />

{<br />

Mark ("IDENTIFICADOR?");<br />

do<br />

{<br />

Get (sym);<br />

} while (PertenceConjunto(cjfator, sym));<br />

}<br />

switch(sym)<br />

{<br />

case IDENTIFICADOR:<br />

find (obj);<br />

Get (sym);<br />

MakeItem (x, obj);<br />

selector (x);<br />

break;<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

69


}<br />

}<br />

case ENUMERO:<br />

MakeConstItem (x, intType, val);<br />

Get (sym);<br />

break;<br />

case PARENTESE_E:<br />

Get (sym);<br />

expression (x);<br />

if (sym == PARENTESE_D)<br />

Get (sym);<br />

else<br />

Mark (")?");<br />

break;<br />

case COLCHETE_E:<br />

Get (sym);<br />

expression (x);<br />

if (sym == COLCHETE_D)<br />

Get (sym);<br />

else<br />

Mark ("]?");<br />

break;<br />

case NAO:<br />

Get (sym);<br />

factor (x);<br />

Op1 (NAO, x);<br />

break;<br />

default:<br />

Mark ("factor?");<br />

MakeItem (x, guard);<br />

void<br />

term (Item & x)<br />

{<br />

Item y;<br />

int op;<br />

factor (x);<br />

// Modulo retirado, pois não é definido em portugol<br />

while (sym == MULTIPLICACAO || sym==DIVISAO || sym == E)<br />

{<br />

op = sym;<br />

Get (sym);<br />

if (op == E)<br />

Op1 (op, x);<br />

factor (y);<br />

Op2 (op, x, y);<br />

}<br />

}<br />

void<br />

SimpleExpression (Item & x)<br />

{<br />

Item y;<br />

int op;<br />

switch(sym)<br />

{<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

70


}<br />

case MAIS:<br />

Get (sym);<br />

term (x);<br />

break;<br />

case MENOS:<br />

Get (sym);<br />

term (x);<br />

Op1 (MENOS, x);<br />

break;<br />

default:<br />

term (x);<br />

}<br />

while (sym == MAIS || sym==MENOS || sym == OU)<br />

{<br />

op = sym;<br />

Get (sym);<br />

if (op == OU)<br />

{<br />

Op1 (op, x);<br />

}<br />

term (y);<br />

Op2 (op, x, y);<br />

}<br />

//NILO: Verificar a equivalencia de Simbolos<br />

void<br />

expression (Item & x)<br />

{<br />

Item y;<br />

int op;<br />

SimpleExpression (x);<br />

}<br />

if (sym == IGUAL || sym == MAIOR || sym == MENOR<br />

|| sym == MAIOR_IGUAL || sym == MENOR_IGUAL<br />

|| sym == DIFERENTE)<br />

{<br />

op = sym;<br />

Get (sym);<br />

SimpleExpression (y);<br />

Relation (op, x, y);<br />

}<br />

void<br />

parameter (Object & fp)<br />

{<br />

Item x;<br />

expression (x);<br />

if (IsParam (fp))<br />

{<br />

Parameter (x, fp->type, fp->Class);<br />

fp = fp->next;<br />

}<br />

else<br />

Mark ("Parâmetros demais");<br />

}<br />

void<br />

param (Item & x)<br />

{<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

71


if (sym == PARENTESE_E)<br />

Get (sym);<br />

else<br />

Mark ("(?");<br />

expression (x);<br />

if (sym == PARENTESE_D)<br />

Get (sym);<br />

else<br />

Mark (")?");<br />

}<br />

//NILO: Verificar a equivalencia de Simbolos<br />

void<br />

StatSequence (void)<br />

{<br />

Object par, obj;<br />

Item x, y;<br />

long L;<br />

do<br />

{<br />

obj = guard;<br />

if (!PertenceConjunto(comandos, sym))<br />

{<br />

Mark ("Comando?");<br />

do<br />

{<br />

Get (sym);<br />

}<br />

while (!PertenceConjunto(comandos,sym));<br />

}<br />

switch(sym)<br />

{<br />

case IDENTIFICADOR:<br />

find (obj);<br />

Get (sym);<br />

MakeItem (x, obj);<br />

selector (x);<br />

switch(sym)<br />

{<br />

case ATRIBUICAO:<br />

Get (sym);<br />

expression (y);<br />

Store (x, y);<br />

break;<br />

case IGUAL:<br />

Mark (":= ?");<br />

Get (sym);<br />

expression (y);<br />

break;<br />

default:<br />

if (x.mode == Proc)<br />

{<br />

par = obj->dsc;<br />

if (sym == PARENTESE_E)<br />

{<br />

Get (sym);<br />

if (sym == PARENTESE_D)<br />

Get (sym);<br />

else<br />

{<br />

do<br />

{<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

72


}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

parameter (par);<br />

if (sym == VIRGULA)<br />

Get (sym);<br />

else<br />

{<br />

if (sym == PARENTESE_D)<br />

{<br />

Get (sym);<br />

break;<br />

}<br />

else<br />

{<br />

if (sym == NOVALINHA)<br />

break;<br />

else<br />

Mark (") or , ?");<br />

}<br />

}<br />

} while (1);<br />

}<br />

if (obj->val < 0)<br />

Mark ("forward call");<br />

else if (!IsParam (par))<br />

Call (x);<br />

else<br />

Mark ("Poucos parâmetros");<br />

}<br />

else if (x.mode == SProc)<br />

{<br />

if (obj->val Class == Typ)<br />

Mark ("Atribuição ilegal?");<br />

else<br />

Mark ("Comando?");<br />

}<br />

break;<br />

case SE:<br />

Get (sym);<br />

expression (x);<br />

CJump (x);<br />

if (sym == ENTAO)<br />

Get (sym);<br />

else<br />

Mark ("então?");<br />

StatSequence ();<br />

L = 0L;<br />

while (sym == SENAO)<br />

{<br />

Get (sym);<br />

FJump (L);<br />

FixLink (x.a);<br />

expression (x);<br />

CJump (x);<br />

if (sym == ENTAO)<br />

Get (sym);<br />

else<br />

Mark ("Então?");<br />

73


}<br />

StatSequence ();<br />

}<br />

if (sym == SENAO)<br />

{<br />

Get (sym);<br />

FJump (L);<br />

FixLink (x.a);<br />

StatSequence ();<br />

}<br />

else<br />

FixLink (x.a);<br />

FixLink (L);<br />

if (sym == FIMSE)<br />

Get (sym);<br />

else<br />

Mark ("Fimse?");<br />

break;<br />

case ENQUANTO:<br />

Get (sym);<br />

L = pc;<br />

expression (x);<br />

CJump (x);<br />

// if (sym == DO)<br />

// Get (sym);<br />

// else<br />

// Mark ("DO?");<br />

StatSequence ();<br />

BJump (L);<br />

FixLink (x.a);<br />

if (sym == FIMENQUANTO)<br />

Get (sym);<br />

else<br />

Mark ("fimenquanto?");<br />

break;<br />

}<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else if (PertenceConjunto(fimdecomandos, sym))<br />

break;<br />

else<br />

Mark ("Fim de linha ?");<br />

} while (1);<br />

void<br />

IdentList (int Class, Object & first)<br />

{<br />

Object obj;<br />

if (sym == IDENTIFICADOR)<br />

{<br />

NewObj (first, Class);<br />

Get (sym);<br />

while (sym == VIRGULA)<br />

{<br />

Get (sym);<br />

if (sym == IDENTIFICADOR)<br />

{<br />

NewObj (obj, Class);<br />

Get (sym);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

74


}<br />

}<br />

else<br />

Mark ("IDENTIFICADOR?");<br />

//NILO: Aqui vem o tipo da variável<br />

// if (sym == DOIS_PONTOS)<br />

// Get (sym);<br />

// else<br />

// Mark (":?");<br />

}<br />

}<br />

void<br />

fType (Type & type)<br />

{<br />

Object obj, first;<br />

Item x;<br />

Type tp;<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

if (sym != IDENTIFICADOR && sym != MATRIZ && sym != REGISTRO &&<br />

sym != NUMERICO && sym !=LITERAL && sym !=LOGICO)<br />

{<br />

Mark ("Tipo ?");<br />

do<br />

{<br />

Get (sym);<br />

}<br />

while (sym != IDENTIFICADOR && sym !=NOVALINHA);<br />

}<br />

switch (sym) {<br />

case LITERAL:<br />

type = litType;<br />

Get(sym);<br />

break;<br />

case NUMERICO:<br />

type = intType;<br />

Get(sym);<br />

break;<br />

case LOGICO:<br />

type = boolType;<br />

Get(sym);<br />

break;<br />

case IDENTIFICADOR: // Tipo definido pelo usuário<br />

find (obj);<br />

Get (sym);<br />

if (obj->Class == Typ)<br />

type = obj->type;<br />

else<br />

Mark ("Tipo ?");<br />

break;<br />

case MATRIZ:<br />

Get (sym);<br />

expression (x);<br />

if (x.mode != Const || x.a < 0)<br />

Mark ("Índice inválido");<br />

// if (sym == of)<br />

// Get (sym);<br />

// else<br />

// Mark ("OF?");<br />

tp = new TypeDesc;<br />

type->form = MATRIZ;<br />

75


}<br />

type->base = tp;<br />

type->len = SHORT (x.a);<br />

type->size = type->len * tp->size;<br />

break;<br />

case REGISTRO:<br />

Get (sym);<br />

type = new TypeDesc;<br />

type->form = REGISTRO;<br />

type->size = 0;<br />

OpenScope ();<br />

do<br />

{<br />

if (sym == IDENTIFICADOR)<br />

{<br />

IdentList (Fld, first);<br />

fType (tp);<br />

obj = first;<br />

while (obj != guard)<br />

{<br />

obj->type = tp;<br />

obj->val = type->size;<br />

type->size += (obj->type->size);<br />

obj = obj->next;<br />

}<br />

}<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else if (sym == IDENTIFICADOR)<br />

Mark (" ?");<br />

else break;<br />

} while (1);<br />

type->fields = topScope->next;<br />

CloseScope ();<br />

if (sym == FIMREGISTRO)<br />

Get (sym);<br />

else<br />

Mark ("fimregistro ?");<br />

break;<br />

default:<br />

Mark ("Identificador ?");<br />

}<br />

int EInicioDeDeclaracaoDefinicaoOuFim(int s)<br />

{<br />

switch(s)<br />

{<br />

case PROCEDIMENTO:<br />

case FUNCAO:<br />

case FIMPROGRAMA:<br />

case FIMMODULO:<br />

case FDA:<br />

case DECLARE:<br />

case DEFINA:<br />

return(VERDADEIRO);<br />

}<br />

return(FALSO);<br />

}<br />

//NILO: Verificar a equivalencia de Simbolos<br />

void<br />

declarations (long varsize)<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

76


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

{<br />

Object obj, first;<br />

Item x;<br />

Type tp;<br />

long L;<br />

if (sym != DECLARE && sym != DEFINA)<br />

{<br />

Mark ("declaração?");<br />

do // Pula o código até a próxima declaração de bloco<br />

{<br />

Get (sym);<br />

}<br />

while (EInicioDeDeclaracaoDefinicaoOuFim(sym));<br />

}<br />

do<br />

{<br />

switch (sym) {<br />

case DEFINA:<br />

{<br />

Get (sym);<br />

while (sym == IDENTIFICADOR)<br />

{<br />

NewObj (obj, Const);<br />

Get (sym);<br />

if (sym == IGUAL)<br />

Get (sym);<br />

else<br />

Mark ("= ?");<br />

expression (x);<br />

fprintf(stderr, "Constante %s definida como %d", id, x.a);<br />

if (x.mode == Const)<br />

{<br />

obj->val = x.a;<br />

obj->type = x.type;<br />

}<br />

else<br />

Mark ("A expressão não é uma constante!");<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark ("?");<br />

}<br />

break;<br />

}<br />

/* TODO: não há no portugol sintaxe para declaração de tipo */<br />

case TIPO:<br />

{<br />

Get (sym);<br />

while (sym == IDENTIFICADOR)<br />

{<br />

NewObj (obj, Typ);<br />

Get (sym);<br />

if (sym == IGUAL)<br />

Get (sym);<br />

else<br />

Mark ("=?");<br />

fType (obj->type);<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark ("?");<br />

77


lista<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

}<br />

break;<br />

}<br />

case DECLARE:<br />

{<br />

Get (sym);<br />

while (sym == IDENTIFICADOR)<br />

{<br />

IdentList (Var, first);<br />

fType (tp);<br />

//atualiza a informação de tipo do primeiro ao ultimo da<br />

obj = first;<br />

while (obj != guard)<br />

{<br />

obj->type = tp;<br />

obj->lev = curlev;<br />

varsize = varsize + obj->type->size;<br />

obj->val = -varsize;<br />

fprintf(stderr, "Variável %s criada sendo do tipo %s\n",<br />

obj->name , id);<br />

obj = obj->next;<br />

}<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark (" ?");<br />

}<br />

break;<br />

}<br />

}<br />

}<br />

while (sym == DECLARE || sym == DEFINA);<br />

}<br />

void<br />

FPSection (long &parblksize)<br />

{<br />

Object obj, first;<br />

Type tp;<br />

long parsize;<br />

if (sym == VARIAVEL)<br />

{<br />

Get (sym);<br />

IdentList (Par, first);<br />

}<br />

else<br />

IdentList (VARIAVEL, first);<br />

if (sym == IDENTIFICADOR)<br />

{<br />

find (obj);<br />

Get (sym);<br />

if (obj->Class == Typ)<br />

tp = obj->type;<br />

else<br />

{<br />

Mark ("type?");<br />

tp = intType;<br />

}<br />

}<br />

else<br />

78


}<br />

{<br />

Mark ("IDENTIFICADOR?");<br />

tp = intType;<br />

}<br />

if (first->Class == VARIAVEL)<br />

{<br />

parsize = tp->size;<br />

if (tp->form >= MATRIZ)<br />

Mark ("no struct params");<br />

}<br />

else<br />

parsize = WordSize;<br />

obj = first;<br />

while (obj != guard)<br />

{<br />

obj->type = tp;<br />

parblksize += parsize;<br />

obj = obj->next;<br />

}<br />

void<br />

ProcedureDecl (void)<br />

{<br />

const int marksize = 8;<br />

Object proc, obj;<br />

Ident procid;<br />

long locblksize, parblksize;<br />

Get (sym);<br />

if (sym == IDENTIFICADOR)<br />

{<br />

strcpy(procid,id);<br />

NewObj (proc, Proc);<br />

Get (sym);<br />

parblksize = marksize;<br />

IncLevel (1);<br />

OpenScope ();<br />

proc->val = -1;<br />

if (sym == PARENTESE_E)<br />

{<br />

Get (sym);<br />

if (sym == PARENTESE_D)<br />

Get (sym);<br />

else<br />

{<br />

FPSection (parblksize);<br />

while (sym == NOVALINHA)<br />

{<br />

Get (sym);<br />

FPSection (parblksize);<br />

}<br />

if (sym == PARENTESE_D)<br />

Get (sym);<br />

else<br />

Mark (")?");<br />

}<br />

}<br />

else if (curlev == 1)<br />

EnterCmd (procid);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

79


obj = topScope->next;<br />

locblksize = parblksize;<br />

while (obj != guard)<br />

{<br />

obj->lev = curlev;<br />

if (obj->Class == Par)<br />

locblksize -= WordSize;<br />

else<br />

locblksize -= obj->type->size;<br />

obj->val = locblksize;<br />

obj = obj->next;<br />

}<br />

proc->dsc = topScope->next;<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark ("?");<br />

locblksize = 0;<br />

declarations (locblksize);<br />

while (sym == PROCEDIMENTO)<br />

{<br />

ProcedureDecl ();<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark ("?");<br />

}<br />

proc->val = pc;<br />

Enter (locblksize);<br />

// if (sym == BEGIN)<br />

// {<br />

Get (sym);<br />

StatSequence ();<br />

// }<br />

if (sym == FIMPROCEDIMENTO)<br />

Get (sym);<br />

else<br />

Mark ("fimprocedimento?");<br />

if (sym == IDENTIFICADOR)<br />

{<br />

if (procid != id)<br />

Mark ("no match");<br />

Get (sym);<br />

}<br />

Return (parblksize - marksize);<br />

CloseScope ();<br />

IncLevel (-1);<br />

}<br />

}<br />

void<br />

Module (FILE * S)<br />

{<br />

Ident modid;<br />

long varsize;<br />

fprintf (W, " compilando: ");<br />

if (sym == MODULO)<br />

{<br />

Get (sym);<br />

Open ();<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

80


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

OpenScope ();<br />

varsize = 0;<br />

if (sym == IDENTIFICADOR)<br />

{<br />

strcpy(modid, id);<br />

Get (sym);<br />

fprintf (W, "%s\n", modid);<br />

}<br />

else<br />

Mark ("IDENTIFICADOR?");<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark ("?");<br />

if(sym==DECLARE || sym ==DEFINA)<br />

declarations (varsize);<br />

while (sym == PROCEDIMENTO)<br />

{<br />

ProcedureDecl ();<br />

if (sym == NOVALINHA)<br />

Get (sym);<br />

else<br />

Mark ("?");<br />

}<br />

Header (varsize);<br />

// if (sym == BEGIN)<br />

// {<br />

// Get (sym);<br />

StatSequence ();<br />

// }<br />

if (sym == FIMMODULO)<br />

Get (sym);<br />

else<br />

Mark ("fimmódulo?");<br />

if (sym == IDENTIFICADOR)<br />

{<br />

if (modid != id)<br />

Mark ("Nome do módulo diferente do declarado");<br />

Get (sym);<br />

}<br />

else<br />

Mark ("Nome do módulo ?");<br />

if (sym != PONTO)<br />

Mark (". ?");<br />

CloseScope ();<br />

if (!error)<br />

{<br />

/* TODO: Vericar este item no código original do Wirth */<br />

/*<br />

IF ~OSS.error THEN<br />

COPY(modid, S.s); OSG.Close(S, varsize); Texts.WriteString(W, "code<br />

generated");<br />

Texts.WriteInt(W, OSG.pc, 6); Texts.WriteLn(W);<br />

Texts.Append(Oberon.Log, W.buf)<br />

END<br />

*/<br />

}<br />

fscanf (S, "%s", modid);<br />

Close (S, varsize);<br />

fprintf (W, "code generated%6d\n", pc);<br />

81


}<br />

}<br />

else<br />

Mark ("módulo?");<br />

void<br />

Compile (FILE *C)<br />

{<br />

long beg, end, time;<br />

FILE *S;<br />

loaded = FALSO;<br />

S = C;<br />

Init (0,C);<br />

Get (sym);<br />

Module (S);<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

/* TODO: Ver o que fazem estas funções: Decode, Load e Exec */<br />

/*<br />

*<br />

*<br />

* PROCEDURE Decode*; VAR V: MenuViewers.Viewer; T: Texts.Text; X, Y:<br />

* INTEGER; BEGIN T := TextFrames.Text("");<br />

* Oberon.AllocateSystemViewer(Oberon.Par.frame.X, X, Y); V :=<br />

* MenuViewers.New( TextFrames.NewMenu("Log.Text", "System.Close<br />

* System.Copy System.Grow Edit.Search Edit.Store"), TextFrames.NewText(T,<br />

* 0), TextFrames.menuH, X, Y); OSG.Decode(T) END Decode;<br />

*<br />

* PROCEDURE Load*; VAR S: Texts.Scanner; BEGIN IF ~OSS.error & ~loaded<br />

* THEN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);<br />

* OSG.Load(S); loaded := TRUE END END Load;<br />

*<br />

* PROCEDURE Exec*; VAR S: Texts.Scanner; BEGIN IF loaded THEN<br />

* Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);<br />

* IF S.class = Texts.Name THEN OSG.Exec(S) END END END Exec;<br />

*/<br />

void<br />

enter (int cl, long n, Ident name, Type type)<br />

{<br />

Object obj;<br />

obj = new ObjDesc;<br />

obj->Class = cl;<br />

obj->val = n;<br />

strcpy (obj->name, name);<br />

obj->type = type;<br />

obj->dsc = NULL;<br />

obj->next = topScope->next;<br />

topScope->next = obj;<br />

}<br />

void<br />

mainParser (void)<br />

{<br />

fprintf (W, "<strong>Portugol</strong> Compiler %s\n", VERSAO);<br />

guard = new ObjDesc;<br />

guard->Class = VARIAVEL;<br />

guard->type = intType;<br />

guard->val = 0;<br />

topScope = NULL;<br />

82


}<br />

OpenScope ();<br />

// Tipos predefinidos<br />

enter (Typ, 1, "LOGICO", boolType);<br />

enter (Typ, 2, "INTEIRO", intType);<br />

enter (Typ, 3, "LITERAL", litType);<br />

// Constantes<br />

enter (Const, 1, "VERDADEIRO", boolType);<br />

enter (Const, 0, "FALSO", boolType);<br />

// Funções Predefinidas<br />

enter (SProc, 1, "leia", NULL);<br />

enter (SProc, 2, "escreva", NULL);<br />

enter (SProc, 3, "escreva_hex", NULL);<br />

enter (SProc, 4, "escreva_nl", NULL);<br />

enter (SProc, 5, "inteiro", NULL);<br />

enter (SProc, 6, "tamanho", NULL);<br />

enter (SProc, 7, "ordem", NULL);<br />

enter (SProc, 8, "caractere", NULL);<br />

enter (SProc, 8, "número", NULL);<br />

enter (SProc, 9, "lit", NULL);<br />

universe = topScope;<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

83


CODEGENERATOR.H<br />

#ifndef ICODEGENERATOR<br />

#define ICODEGENERATOR<br />

#define maxCode 1000<br />

#define maxRel 200<br />

#define NofCom 16<br />

#define Head 0<br />

#define Var 1<br />

#define Par 2<br />

#define Const 3<br />

#define Fld 4<br />

#define Typ 5<br />

#define Proc 6<br />

#define SProc 7<br />

#define Reg 10<br />

#define Cond 11<br />

#define Boolean 0<br />

#define Integer 1<br />

#define Array 2<br />

#define Record 3<br />

#define Literal 4<br />

// Registradores reservados<br />

#define FP 29<br />

#define SP 30<br />

#define LNK 31<br />

// Tipos<br />

typedef struct ObjDesc *Object;<br />

typedef struct TypeDesc *Type;<br />

typedef struct Item<br />

{<br />

int mode, lev;<br />

Type type;<br />

long a, b, c, r;<br />

} Item;<br />

struct ObjDesc<br />

{<br />

int Class, lev;<br />

Object next, dsc;<br />

Type type;<br />

Ident name;<br />

long val;<br />

};<br />

struct TypeDesc<br />

{<br />

int form;<br />

Object fields;<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

84


Type base;<br />

int size, len;<br />

};<br />

#ifndef CODEGENERATOR<br />

extern Type boolType;<br />

extern Type intType;<br />

extern Type litType;<br />

extern int curlev;<br />

extern int pc;<br />

#endif<br />

void mainCodeGenerator (void);<br />

void ClearReg ();<br />

void GetReg (long &r);<br />

void Put (long op, long a, long b, long c);<br />

void EXCL (char *reg, int p);<br />

void TestRange (long x);<br />

void load (Item & x);<br />

void loadBool (Item & x);<br />

void PutOp (long cd, Item & x, Item & y);<br />

long negated (long cond);<br />

long merged (long L0, long L1);<br />

void fix (long at, long with);<br />

void FixWith (long L0, long L1);<br />

void FixLink (long L);<br />

void IncLevel (int n);<br />

void MakeConstItem (Item & x, Type typ, long val);<br />

void MakeItem (Item & x, Object y);<br />

void Field (Item & x, Object & y);<br />

void Index (Item & x, Item & y);<br />

void Op1 (int op, Item & x);<br />

void Op2 (int op, Item & x, Item & y);<br />

void Relation (int op, Item & x, Item & y);<br />

void Store (Item & x, Item & y);<br />

void Parameter (Item & x, Type & ftyp, int Class);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

85


void CJump (Item & x);<br />

void BJump (long L);<br />

void FJump (long &L);<br />

void Call (Item & x);<br />

void IOCall (Item & x, Item & y);<br />

void Header (long size);<br />

void Enter (long size);<br />

void Return (long size);<br />

void Open (void);<br />

void Close (FILE * S, long globals);<br />

void EnterCmd (char *name);<br />

void Load (FILE * S);<br />

void Exec (FILE * S);<br />

void Decode (FILE * T);<br />

#endif<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

86


CODEGENERATOR.CPP<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

/*<br />

* Módulo OSG - Code Generator Universidade do Amazonas Comport -<br />

* <strong>Compilador</strong> <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

*<br />

* Baseado no compilador Oberon-0 de Niklaus Wirth<br />

*<br />

*/<br />

#define CODEGENERATOR<br />

#include <br />

#include <br />

#include <br />

#include "scanner.h"<br />

#include "instrucoes.h"<br />

#include "risc.h"<br />

#include "funcoes.h"<br />

#include "codegenerator.h"<br />

// int curlev, pc;<br />

Type boolType, intType, litType;<br />

int curlev, pc;<br />

int relx, cno;<br />

long entry, fixlist;<br />

char regs[32]; // Verificar troca por SET -- forcar o<br />

// ClearReg!!!<br />

extern FILE *W;<br />

long code[maxCode];<br />

int rel[maxRel];<br />

Ident comname[NofCom];<br />

long comadr[NofCom];<br />

char mnemo[54][5];<br />

void<br />

ClearReg ()<br />

{<br />

int i;<br />

for (i = 0; i < 32; i++)<br />

regs[i] = 0;<br />

}<br />

void<br />

GetReg (long &r)<br />

{<br />

int i;<br />

for (i = 1; (i < FP && !regs[i]); i++);<br />

regs[i] = 1;<br />

r = i;<br />

}<br />

87


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

void<br />

Put (long op, long a, long b, long c)<br />

{<br />

if (op >= 32)<br />

op = op - 64;<br />

code[pc] = fASH (fASH (fASH (op, 5) + a, 5) + b, 16) + (c % 0x10000);<br />

pc++;<br />

}<br />

void<br />

EXCL (char *reg, int p)<br />

{<br />

reg[p] = 0;<br />

}<br />

void<br />

TestRange (long x)<br />

{<br />

if (x >= 0x8000 || x form != Boolean)<br />

88


}<br />

Mark ("Boolean ?");<br />

load (x);<br />

x.mode = Cond;<br />

x.a = 0;<br />

x.b = 0;<br />

x.c = 1;<br />

void<br />

PutOp (long cd, Item & x, Item & y)<br />

{<br />

long r;<br />

if (x.mode != Reg)<br />

load (x);<br />

if (x.r == 0)<br />

{<br />

GetReg (x.r);<br />

r = 0;<br />

}<br />

else<br />

{<br />

r = x.r;<br />

}<br />

if (y.mode == Const)<br />

{<br />

TestRange (y.a);<br />

Put (cd + 16, r, x.r, y.a);<br />

}<br />

else<br />

{<br />

if (y.mode != Reg)<br />

load (y);<br />

Put (cd, x.r, r, y.r);<br />

EXCL (regs, y.r);<br />

}<br />

}<br />

long<br />

negated (long cond)<br />

{<br />

if (ODD (cond))<br />

return (cond - 1);<br />

else<br />

return (cond + 1);<br />

}<br />

long<br />

merged (long L0, long L1)<br />

{<br />

long L2, L3;<br />

if (L0 != 0)<br />

{<br />

L2 = L0;<br />

do<br />

{<br />

L3 = code[L2] % 0x10000;<br />

if (L3 == 0)<br />

break;<br />

L2 = L3;<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

89


}<br />

while (1);<br />

code[L2] = code[L2] - L3 + L1;<br />

return (L0);<br />

}<br />

else<br />

return (L1);<br />

void<br />

fix (long at, long with)<br />

{<br />

code[at] = code[at] / 0x10000 * 0x10000 + (with % 0x10000);<br />

}<br />

void<br />

FixWith (long L0, long L1)<br />

{<br />

long L2;<br />

while (L0 != 0)<br />

{<br />

L2 = code[L0] % 0x10000;<br />

fix (L0, L1 - L0);<br />

L0 = L2;<br />

}<br />

}<br />

void<br />

FixLink (long L)<br />

{<br />

long L1;<br />

while (L != 0)<br />

{<br />

L1 = code[L] % 0x10000;<br />

fix (L, pc - L);<br />

L = L1;<br />

}<br />

}<br />

void<br />

IncLevel (int n)<br />

{<br />

curlev += n;<br />

}<br />

void<br />

MakeConstItem (Item & x, Type typ, long val)<br />

{<br />

x.mode = Const;<br />

x.type = typ;<br />

x.a = val;<br />

}<br />

void<br />

MakeItem (Item & x, Object y)<br />

{<br />

long r;<br />

x.mode = y->Class;<br />

x.type = y->type;<br />

x.lev = y->lev;<br />

x.a = y->val;<br />

if (y->lev == 0)<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

90


}<br />

x.r = 0;<br />

else if (y->lev == curlev)<br />

x.r = FP;<br />

else<br />

{<br />

Mark ("level!");<br />

x.r = 0;<br />

}<br />

if (y->Class == Par)<br />

{<br />

GetReg (r);<br />

Put (LDW, r, x.r, x.a);<br />

x.mode = Var;<br />

x.r = r;<br />

x.a = 0;<br />

}<br />

void<br />

Field (Item & x, Object & y)<br />

{<br />

x.a += y->val;<br />

x.type = y->type;<br />

}<br />

void<br />

Index (Item & x, Item & y)<br />

{<br />

if (y.type != intType)<br />

Mark ("index not integer");<br />

if (y.mode == Const)<br />

{<br />

if (y.a < 0 || y.a >= x.type->len)<br />

Mark ("bad index");<br />

x.a += y.a * x.type->base->size;<br />

}<br />

else<br />

{<br />

if (y.mode != Reg)<br />

load (y);<br />

Put (CHKI, y.r, 0, x.type->len);<br />

Put (MULI, y.r, y.r, x.type->base->size);<br />

if (x.r != 0)<br />

{<br />

Put (ADD, y.r, x.r, y.r);<br />

EXCL (regs, x.r);<br />

}<br />

x.r = y.r;<br />

}<br />

x.type = x.type->base;<br />

}<br />

void<br />

Op1 (int op, Item & x)<br />

{<br />

long t;<br />

if (op == MENOS)<br />

{<br />

if (x.type->form != Integer)<br />

Mark ("bad type");<br />

else<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

91


}<br />

{<br />

}<br />

if (x.mode == Const)<br />

x.a = -x.a;<br />

else<br />

{<br />

if (x.mode == Var)<br />

load (x);<br />

Put (SUB, x.r, 0, x.r);<br />

}<br />

}<br />

else<br />

{<br />

if (op == NAO)<br />

{<br />

if (x.mode != Cond)<br />

loadBool (x);<br />

x.c = negated (x.c);<br />

t = x.a;<br />

x.a = x.b;<br />

x.b = t;<br />

}<br />

else<br />

{<br />

if (op == E)<br />

{<br />

if (x.mode != Cond)<br />

loadBool (x);<br />

Put (BEQ + negated (x.c), x.r, 0, x.a);<br />

EXCL (regs, x.r);<br />

x.a = pc - 1;<br />

FixLink (x.b);<br />

x.b = 0;<br />

}<br />

else<br />

{<br />

if (op == OU)<br />

{<br />

if (x.mode != Cond)<br />

loadBool (x);<br />

Put (BEQ + x.c, x.r, 0, x.b);<br />

EXCL (regs, x.r);<br />

x.b = pc - 1;<br />

FixLink (x.a);<br />

x.a - 0;<br />

}<br />

}<br />

}<br />

}<br />

void<br />

Op2 (int op, Item & x, Item & y)<br />

{<br />

if (x.type->form == Integer && y.type->form == Integer)<br />

{<br />

if (x.mode == Const && y.mode == Const)<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

92


}<br />

{<br />

if (op == MAIS)<br />

x.a += y.a;<br />

else if (op == MENOS)<br />

x.a -= y.a;<br />

else if (op == MULTIPLICACAO)<br />

x.a *= y.a;<br />

else if (op == DIVISAO)<br />

x.a /= y.a;<br />

else if (op == RESTO)<br />

x.a %= y.a;<br />

else<br />

Mark ("bad type");<br />

}<br />

else<br />

{<br />

if (op == MAIS)<br />

PutOp (ADD, x, y);<br />

else if (op == MENOS)<br />

PutOp (SUB, x, y);<br />

else if (op == MULTIPLICACAO)<br />

PutOp (MUL, x, y);<br />

else if (op == DIVISAO)<br />

PutOp (DIV, x, y);<br />

else if (op == RESTO)<br />

PutOp (MOD, x, y);<br />

else<br />

Mark ("bad type");<br />

}<br />

}<br />

else<br />

{<br />

if (x.type->form == Boolean && y.type->form == Boolean)<br />

{<br />

if (y.mode != Cond)<br />

loadBool (y);<br />

if (op == OU)<br />

{<br />

x.a = y.a;<br />

x.b = merged (y.b, x.b);<br />

x.c = y.c;<br />

}<br />

else<br />

{<br />

if (op == E)<br />

{<br />

x.a = merged (y.a, x.a);<br />

x.b = y.b;<br />

x.c = y.c;<br />

}<br />

}<br />

}<br />

else<br />

Mark ("bad type");<br />

}<br />

void<br />

Relation (int op, Item & x, Item & y)<br />

{<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

93


}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

if (x.type->form != Integer || y.type->form != Integer)<br />

Mark ("bad type");<br />

else<br />

{<br />

if (y.mode == Const && y.a == 0)<br />

load (x);<br />

else<br />

PutOp (CMP, x, y);<br />

x.c = op - IGUAL; // Revisar esta construção misteriosa!!!<br />

EXCL (regs, y.r);<br />

}<br />

x.mode = Cond;<br />

x.type = boolType;<br />

x.a = 0;<br />

x.b = 0;<br />

void<br />

Store (Item & x, Item & y)<br />

{<br />

long r;<br />

if ((x.type->form == Boolean || x.type->form == Integer) &&<br />

x.type->form == y.type->form)<br />

{<br />

if (y.mode == Cond)<br />

{<br />

Put (BEQ + negated (y.c), y.r, 0, y.a);<br />

EXCL (regs, y.r);<br />

y.a = pc - 1;<br />

FixLink (y.b);<br />

GetReg (y.r);<br />

Put (ADDI, y.r, 0, 1);<br />

Put (BEQ, 0, 0, 2);<br />

FixLink (y.a);<br />

Put (ADDI, y.r, 0, 0);<br />

}<br />

else<br />

{<br />

if (y.mode != Reg)<br />

load (y);<br />

}<br />

if (x.mode == Var)<br />

{<br />

if (x.lev == 0)<br />

{<br />

rel[relx] = SHORT (pc);<br />

relx++;<br />

}<br />

Put (STW, y.r, x.r, x.a);<br />

}<br />

else<br />

Mark ("illegal assignment");<br />

EXCL (regs, x.r);<br />

EXCL (regs, y.r);<br />

}<br />

else<br />

Mark ("incompatible assignment");<br />

}<br />

void<br />

Parameter (Item & x, Type & ftyp, int Class)<br />

94


{<br />

}<br />

long r;<br />

if (x.type == ftyp)<br />

{<br />

if (Class == Par)<br />

{<br />

if (x.mode == Var)<br />

{<br />

if (x.a != 0)<br />

{<br />

if (x.lev != 0)<br />

{<br />

rel[relx] = SHORT (pc);<br />

relx++;<br />

}<br />

GetReg (r);<br />

Put (ADDI, r, x.r, x.a);<br />

}<br />

else<br />

r = x.r;<br />

}<br />

else<br />

Mark ("illegal parameter mode");<br />

Put (PSH, r, SP, 4);<br />

EXCL (regs, r);<br />

}<br />

else<br />

{<br />

if (x.mode != Reg)<br />

load (x);<br />

Put (PSH, x.r, SP, 4);<br />

EXCL (regs, x.r);<br />

}<br />

}<br />

else<br />

Mark ("bad parameter type");<br />

void<br />

CJump (Item & x)<br />

{<br />

if (x.type->form == Boolean)<br />

{<br />

if (x.mode != Cond)<br />

loadBool (x);<br />

Put (BEQ + negated (x.c), x.r, 0, x.a);<br />

EXCL (regs, x.r);<br />

FixLink (x.b);<br />

x.a = pc - 1;<br />

}<br />

else<br />

{<br />

Mark ("Boolean?");<br />

x.a = pc;<br />

}<br />

}<br />

void<br />

BJump (long L)<br />

{<br />

Put (BEQ, 0, 0, L - pc);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

95


}<br />

void<br />

FJump (long &L)<br />

{<br />

Put (BEQ, 0, 0, L);<br />

L = pc - 1;<br />

}<br />

void<br />

Call (Item & x)<br />

{<br />

Put (BSR, 0, 0, x.a - pc);<br />

}<br />

void<br />

IOCall (Item & x, Item & y)<br />

{<br />

Item z;<br />

if (x.a < 4)<br />

{<br />

if (y.type->form != Integer)<br />

Mark ("Integer?");<br />

}<br />

}<br />

if (x.a == 1)<br />

{<br />

GetReg (z.r);<br />

z.mode = Reg;<br />

z.type = intType;<br />

Put (RD, z.r, 0, 0);<br />

Store (y, z);<br />

}<br />

else<br />

{<br />

if (x.a == 2)<br />

{<br />

load (y);<br />

Put (WRD, 0, 0, y.r);<br />

EXCL (regs, y.r);<br />

}<br />

else<br />

{<br />

if (x.a == 3)<br />

{<br />

load (y);<br />

Put (WRH, 0, 0, y.r);<br />

EXCL (regs, y.r);<br />

}<br />

else<br />

Put (WRL, 0, 0, 0);<br />

}<br />

}<br />

void<br />

Header (long size)<br />

{<br />

entry = pc;<br />

Put (ADDI, SP, 0, MemSize - size);<br />

Put (PSH, LNK, SP, 4);<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

96


}<br />

void<br />

Enter (long size)<br />

{<br />

Put (PSH, LNK, SP, 4);<br />

Put (PSH, FP, SP, 4);<br />

Put (ADD, FP, 0, SP);<br />

Put (SUBI, SP, SP, size);<br />

}<br />

void<br />

Return (long size)<br />

{<br />

Put (ADD, SP, 0, FP);<br />

Put (POP, FP, SP, 4);<br />

Put (POP, LNK, SP, size + 4);<br />

Put (RET, 0, 0, LNK);<br />

}<br />

void<br />

Open (void)<br />

{<br />

curlev = 0;<br />

pc = 0;<br />

relx = 0;<br />

ClearReg ();<br />

}<br />

void<br />

Close (FILE * S, long globals)<br />

{<br />

Put (POP, LNK, SP, 4);<br />

Put (RET, 0, 0, LNK);<br />

}<br />

void<br />

EnterCmd (char *name)<br />

{<br />

strcpy (name, comname[cno]);<br />

comadr[cno] = pc * 4;<br />

cno++;<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

void<br />

Load (FILE * S)<br />

{<br />

long i = 0L, k;<br />

while (i < relx)<br />

{<br />

k = rel[i++];<br />

code[k] = (code[k] / 0x10000 * 0x10000) + (code[k] + MemSize) %<br />

0x10000;<br />

}<br />

RISC.Load (code, pc);<br />

fprintf (W, " code loaded\n");<br />

RISC.Execute (entry * 4, S, stderr);<br />

}<br />

void<br />

97


Exec (FILE * S)<br />

{<br />

int i = 0;<br />

//NILO: traduzir a pesquisa<br />

//Carrega o nome e endereco das procedures<br />

// while(i 0x8000)<br />

a -= 0x10000;<br />

fprintf (W, "%4d\t%s\t%4d,%4d,%8d\n",<br />

4 * i,<br />

mnemo[cd / 0x4000000 % 0x40],<br />

cd / 0x200000 % 0x20, cd / 0x10000 % 0x20, a);<br />

i++;<br />

}<br />

fprintf (W, "reloc\n");<br />

i = 0;<br />

while (i < relx)<br />

{<br />

fprintf (W, "%5d", rel[i++] * 4);<br />

if (i % 16 == 0)<br />

fprintf (W, "\n");<br />

}<br />

fprintf (W, "\n");<br />

// Concatena a saída de W em T ...<br />

}<br />

void<br />

mainCodeGenerator (void)<br />

{<br />

boolType = new TypeDesc;<br />

boolType->form = Boolean;<br />

boolType->size = 4;<br />

intType = new TypeDesc;<br />

intType->form = Integer;<br />

intType->size = 4;<br />

litType = new TypeDesc;<br />

litType->form = Literal;<br />

litType->size = 8;<br />

strcpy (mnemo[ADD], "ADD ");<br />

strcpy (mnemo[SUB], "SUB ");<br />

strcpy (mnemo[MUL], "MUL ");<br />

strcpy (mnemo[DIV], "DIV ");<br />

strcpy (mnemo[MOD], "MOD ");<br />

strcpy (mnemo[CMP], "CMP ");<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

98


}<br />

strcpy (mnemo[OR], "OR ");<br />

strcpy (mnemo[AND], "AND ");<br />

strcpy (mnemo[BIC], "BIC ");<br />

strcpy (mnemo[XOR], "XOR ");<br />

strcpy (mnemo[LSH], "LSH ");<br />

strcpy (mnemo[ASH1], "ASH ");<br />

strcpy (mnemo[CHK], "CHK ");<br />

strcpy (mnemo[ADDI], "ADDI");<br />

strcpy (mnemo[SUBI], "SUBI");<br />

strcpy (mnemo[MULI], "MULI");<br />

strcpy (mnemo[DIVI], "DIVI");<br />

strcpy (mnemo[MODI], "CMPI");<br />

strcpy (mnemo[CMPI], "MODI");<br />

strcpy (mnemo[ORI], "ORI ");<br />

strcpy (mnemo[ANDI], "ANDI");<br />

strcpy (mnemo[BICI], "BICI");<br />

strcpy (mnemo[XORI], "XORI");<br />

strcpy (mnemo[LSHI], "LSHI");<br />

strcpy (mnemo[ASHI], "ASHI");<br />

strcpy (mnemo[CHKI], "CHKI");<br />

strcpy (mnemo[LDW], "LDW ");<br />

strcpy (mnemo[LDB], "LDB ");<br />

strcpy (mnemo[POP], "POP ");<br />

strcpy (mnemo[STW], "STW ");<br />

strcpy (mnemo[STB], "STB ");<br />

strcpy (mnemo[PSH], "PSH ");<br />

strcpy (mnemo[BEQ], "BEQ ");<br />

strcpy (mnemo[BNE], "BNE ");<br />

strcpy (mnemo[BLT], "BLT ");<br />

strcpy (mnemo[BGE], "BGE ");<br />

strcpy (mnemo[BLE], "BLE ");<br />

strcpy (mnemo[BGT], "BGT ");<br />

strcpy (mnemo[BSR], "BSR ");<br />

strcpy (mnemo[JSR], "JSR ");<br />

strcpy (mnemo[RET], "RET ");<br />

strcpy (mnemo[RD], "READ");<br />

strcpy (mnemo[WRD], "WRD ");<br />

strcpy (mnemo[WRH], "WRH ");<br />

strcpy (mnemo[WRL], "WRL ");<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

99


FUNCOES.H<br />

#ifndef IFUNCOES<br />

#define IFUNCOES<br />

#define MAX_ELEM_CJ 128<br />

#ifndef FUNCOES<br />

extern char minusculaC(char texto);<br />

extern void minusculaS(char *texto);<br />

extern long fASH (long R, long c);<br />

extern long fLSH (long R, long c);<br />

extern long SHORT (long x);<br />

extern int ODD (long x);<br />

extern bool PertenceConjunto(char *a, int elemento);<br />

extern void AdicionaConjunto(char *a, int elemento);<br />

extern void CriaConjunto(char *a);<br />

#endif<br />

#endif<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

100


FUNCOES.CPP<br />

#include <br />

#include <br />

#define FUNCOES<br />

#include "funcoes.h"<br />

long<br />

fASH (long R, long c)<br />

{<br />

long t, s;<br />

const m = (1 = 0)<br />

for (; c >= 0; c--)<br />

t = 1;<br />

t = (t & !m) + s;<br />

return (t);<br />

}<br />

long<br />

fLSH (long R, long c)<br />

{<br />

long t;<br />

t = R;<br />

if (c >= 0)<br />

for (; c >= 0; c--)<br />

t = t > 1;<br />

return (t);<br />

}<br />

int<br />

ODD (long x)<br />

{<br />

return ((1 & x));<br />

}<br />

int<br />

SHORT (long x)<br />

{<br />

return ((0xFFFF & x));<br />

}<br />

char minusculaC(char texto)<br />

{<br />

char minus[] = "áéíóúâêîôûäëïöüÿãõàèìòùñç";<br />

char maius[] = "ÁÉÍÓÚÂÊÎÔÛÄËÏÖÜYÃÕÀÈÌÒÙÑÇ";<br />

char *c;<br />

if(texto>='A' && texto


}<br />

else {<br />

c = strchr(maius, texto);<br />

if(c)<br />

texto=minus[c-maius];<br />

}<br />

return texto;<br />

void minusculaS(char *texto)<br />

{<br />

int i;<br />

char *c;<br />

for (i=0; texto[i]!=0;i++)<br />

texto[i] = minusculaC(texto[i]);<br />

}<br />

void CriaConjunto(char *a)<br />

{<br />

memset(a, MAX_ELEM_CJ, 0);<br />

}<br />

void AdicionaConjunto(char *a, int elemento)<br />

{<br />

a[elemento]=1;<br />

}<br />

bool PertenceConjunto(char *a, int elemento)<br />

{<br />

return(a[elemento]==1);<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

102


RISC.H<br />

#ifndef IRISC<br />

#define IRISC<br />

#define MemSize 4096<br />

class TRisc<br />

{<br />

public:<br />

long PC, IR, R[32], M[MemSize / 4];<br />

void Execute (long pc0, FILE * in, FILE * out);<br />

void Load (long code[], long len);<br />

void State ();<br />

};<br />

extern TRisc RISC;<br />

#endif<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

103


RISC.CPP<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

/*<br />

*<br />

* Módulo RISC - Interpretador de código Universidade do Amazonas Comport<br />

* - <strong>Compilador</strong> <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />

*<br />

* Baseado no compilador Oberon-0 de Niklaus Wirth<br />

*<br />

*/<br />

#include <br />

#include <br />

#include <br />

#include "instrucoes.h"<br />

#include "risc.h"<br />

#include "funcoes.h"<br />

void<br />

TRisc::Execute (long pc0, FILE * in, FILE * out)<br />

{<br />

long opc, a, b, c, nxt;<br />

int ii;<br />

R[31] = 0;<br />

PC = pc0 / 4;<br />

do<br />

{<br />

R[0] = 0;<br />

nxt = PC + 1;<br />

IR = M[PC];<br />

opc = (IR / 0x4000000) % 0x40;<br />

a = (IR / 0x200000) % 0x20;<br />

b = (IR / 0x10000) % 0x20;<br />

c = (IR % 0x10000);<br />

if (opc < ADDI)<br />

c = R[c % 0x20];<br />

else<br />

{<br />

if (c > 0x8000)<br />

c -= 0x10000;<br />

}<br />

switch (opc)<br />

{<br />

case ADD:<br />

case ADDI:<br />

R[a] = R[b] + c;<br />

break;<br />

case SUB:<br />

case SUBI:<br />

case CMP:<br />

case CMPI:<br />

R[a] = R[b] - c;<br />

break;<br />

case MUL:<br />

case MULI:<br />

104


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

R[a] = R[b] * c;<br />

break;<br />

case DIV:<br />

case DIVI:<br />

R[a] = R[b] / c;<br />

break;<br />

case MOD:<br />

case MODI:<br />

R[a] = R[b] % c;<br />

break;<br />

case OR:<br />

case ORI:<br />

R[a] = R[b] | c;<br />

break;<br />

case AND:<br />

case ANDI:<br />

R[a] = R[b] & c;<br />

break;<br />

case BIC:<br />

case BICI:<br />

R[a] = R[b] & !c;<br />

break;<br />

case XOR:<br />

case XORI:<br />

R[a] = R[b] ^ c;<br />

break;<br />

case LSH:<br />

case LSHI:<br />

fLSH (R[b], c);<br />

break;<br />

case ASH1:<br />

case ASHI:<br />

R[a] = fASH (R[b], c);<br />

break;<br />

case CHK:<br />

case CHKI:<br />

if (R[a] < 0 || R[a] > c)<br />

{<br />

fprintf (stderr, "Trap at %d\n", PC);<br />

return;<br />

}<br />

break;<br />

case LDW:<br />

R[a] = M[(R[b] + c) / 4];<br />

break;<br />

case LDB:<br />

R[a] = fLSH (M[(R[b] + c) / 4], (R[b] + c) / 4 * 8) % 0x100;<br />

break;<br />

case POP:<br />

R[a] = M[R[b] / 4];<br />

R[b] += c;<br />

break;<br />

case STW:<br />

M[(R[b] + c) / 4] = R[a];<br />

break;<br />

case STB:<br />

break; // Não implementado<br />

case PSH:<br />

R[b] -= c;<br />

M[(R[b] / 4)] = R[a];<br />

break;<br />

105


}<br />

case BEQ:<br />

if (R[a] == R[b])<br />

nxt = PC + c;<br />

break;<br />

case BNE:<br />

if (R[a] != R[b])<br />

nxt = PC + c;<br />

break;<br />

case BLT:<br />

if (R[a] < R[b])<br />

nxt = PC + c;<br />

break;<br />

case BGE:<br />

if (R[a] >= R[b])<br />

nxt = PC + c;<br />

break;<br />

case BLE:<br />

if (R[a] R[b])<br />

nxt = PC + c;<br />

break;<br />

case BSR:<br />

nxt = PC + c;<br />

R[31] = (PC + 1) * 4;<br />

break;<br />

case JSR:<br />

nxt = IR % 0x4000000;<br />

R[31] = (PC + 1) * 4;<br />

break;<br />

case RET:<br />

nxt = R[c % 0x20] / 4;<br />

if (nxt == 0)<br />

return;<br />

break;<br />

case RD:<br />

fscanf (in, "%d", &ii);<br />

R[a] = ii;<br />

break;<br />

case WRD:<br />

fprintf (stdout, " %d", R[c]);<br />

break;<br />

case WRH:<br />

fprintf (stdout, "%x", R[c]);<br />

break;<br />

case WRL:<br />

fprintf (stdout, "\n");<br />

break;<br />

}<br />

PC = nxt;<br />

}<br />

while (1);<br />

void<br />

TRisc::Load (long code[], long len)<br />

{<br />

int i;<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

106


}<br />

for (i = 0; i < len; i++)<br />

M[i] = code[i];<br />

void<br />

TRisc::State ()<br />

{<br />

fprintf (stderr, "PC=%d\n", PC * 4);<br />

fprintf (stderr, "SP=%d\n", R[30]);<br />

fprintf (stderr, "FP=%d\n", R[29]);<br />

fprintf (stderr, "R1=%d\n", R[1]);<br />

fprintf (stderr, "R2=%d\n", R[2]);<br />

fprintf (stderr, "R3=%d\n", R[3]);<br />

fprintf (stderr, "R4=%d\n", R[4]);<br />

}<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

107


INSTRUCOES.H<br />

// Instruções<br />

#define ADD 0<br />

#define SUB 1<br />

#define MUL 2<br />

#define DIV 3<br />

#define MOD 4<br />

#define CMP 5<br />

#define OR 8<br />

#define AND 9<br />

#define BIC 10<br />

#define XOR 11<br />

#define LSH 12<br />

#define ASH1 13<br />

#define CHK 14<br />

#define ADDI 16<br />

#define SUBI 17<br />

#define MULI 18<br />

#define DIVI 19<br />

#define MODI 20<br />

#define CMPI 21<br />

#define ORI 24<br />

#define ANDI 25<br />

#define BICI 26<br />

#define XORI 27<br />

#define LSHI 28<br />

#define ASHI 29<br />

#define CHKI 30<br />

#define LDW 32<br />

#define LDB 33<br />

#define POP 34<br />

#define STW 36<br />

#define STB 37<br />

#define PSH 38<br />

#define BEQ 40<br />

#define BNE 41<br />

#define BLT 42<br />

#define BGE 43<br />

#define BLE 44<br />

#define BGT 45<br />

#define BSR 46<br />

#define JSR 48<br />

#define RET 49<br />

#define RD 50<br />

#define WRD 51<br />

#define WRH 52<br />

#define WRL 53<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

108


PRINCIPAL.CPP<br />

#include <br />

#include <br />

#include <br />

// extern void mainScanner(void);<br />

// extern void mainCodeGenerator(void);<br />

#include "scanner.h"<br />

#include "codegenerator.h"<br />

#include "risc.h"<br />

#include "parser.h"<br />

#define VERSAO "0.92"<br />

#define DATA "2003-09-06"<br />

TRisc RISC;<br />

int<br />

main (int argc, char **argv)<br />

{<br />

FILE *FONTE;<br />

spawnl(P_WAIT, "pagina.bat", "pagina.bat","1252",NULL);<br />

}<br />

mainScanner ();<br />

mainCodeGenerator ();<br />

mainParser ();<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

if(argc==2)<br />

{<br />

FONTE = fopen(argv[1],"r");<br />

if(FONTE==NULL)<br />

{<br />

fprintf(stderr, "Erro ao abrir arquivo fonte!! [%s]\n", argv[1]);<br />

exit(1);<br />

}<br />

}<br />

else<br />

{<br />

FONTE=stdin;<br />

fprintf(stderr, "Lendo fonte da entrada padrão [stdin]\n");<br />

}<br />

Compile (FONTE);<br />

// Pausa para manter a janela aberta (tecla para terminar)<br />

fgetc(stdin);<br />

109


MAKEFILE<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

# -------------------------------------------------------------------------<br />

--<br />

!if !$d(BCB)<br />

BCB = $(MAKEDIR)\..<br />

!endif<br />

# -------------------------------------------------------------------------<br />

--<br />

# IDE SECTION<br />

# -------------------------------------------------------------------------<br />

--<br />

# The following section of the project makefile is managed by the BCB IDE.<br />

# It is recommended to use the IDE to change any of the values in this<br />

# section.<br />

# -------------------------------------------------------------------------<br />

--<br />

VERSION = BCB.06.00<br />

# -------------------------------------------------------------------------<br />

--<br />

PROJECT = portugol.exe<br />

OBJFILES = scanner.obj parser.obj risc.obj codegenerator.obj funcoes.obj<br />

principal.obj<br />

RESFILES =<br />

MAINSOURCE = portugol.bpf<br />

RESDEPEN = $(RESFILES)<br />

LIBFILES =<br />

IDLFILES =<br />

IDLGENFILES =<br />

LIBRARIES =<br />

PACKAGES = dbrtl.bpi vcldb.bpi adortl.bpi ibsmp.bpi bdertl.bpi vcldbx.bpi<br />

qrpt.bpi \<br />

teeui.bpi teedb.bpi tee.bpi dss.bpi teeqr.bpi ibxpress.bpi dsnap.bpi \<br />

vclie.bpi inetdb.bpi inet.bpi nmfast.bpi webdsnap.bpi bcbie.bpi \<br />

bcb2kaxserver.bpi<br />

SPARELIBS =<br />

DEFFILE =<br />

OTHERFILES =<br />

# -------------------------------------------------------------------------<br />

--<br />

DEBUGLIBPATH = $(BCB)\lib\debug<br />

RELEASELIBPATH = $(BCB)\lib\release<br />

USERDEFINES = _DEBUG;PRINCIPAL<br />

SYSDEFINES = NO_STRICT;_NO_VCL<br />

INCLUDEPATH = $(BCB)\include;$(BCB)\include\vcl<br />

LIBPATH = $(BCB)\lib\obj;$(BCB)\lib<br />

WARNINGS= -w-par<br />

PATHCPP = .;<br />

PATHASM = .;<br />

PATHPAS = .;<br />

PATHRC = .;<br />

PATHOBJ = .;$(LIBPATH)<br />

# -------------------------------------------------------------------------<br />

--<br />

110


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

CFLAG1 = -Od -H=c:\ARQUIV~1\borland\CBUILD~1\lib\vcl60.csm -Hc -Q -Vx -X- -<br />

A -r- \<br />

-a8 -6 -b- -k -y -v -vi- -tWC -tWM- -c<br />

IDLCFLAGS = -src_suffix cpp -D_DEBUG -DPRINCIPAL -I$(BCB)\include -<br />

I$(BCB)\include\vcl \<br />

-boa<br />

PFLAGS = -$YD -$W -$O- -$A8 -v -JPHNE -M<br />

RFLAGS =<br />

AFLAGS = /mx /w2 /zi<br />

LFLAGS = -D"" -ap -Tpe -x -Gn -v<br />

# -------------------------------------------------------------------------<br />

--<br />

ALLOBJ = c0x32.obj $(OBJFILES)<br />

ALLRES = $(RESFILES)<br />

ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cw32.lib<br />

# -------------------------------------------------------------------------<br />

--<br />

!ifdef IDEOPTIONS<br />

[Version Info]<br />

IncludeVerInfo=0<br />

AutoIncBuild=0<br />

MajorVer=1<br />

MinorVer=0<br />

Release=0<br />

Build=0<br />

Debug=0<br />

PreRelease=0<br />

Special=0<br />

Private=0<br />

DLL=0<br />

[Version Info Keys]<br />

CompanyName=<br />

FileDescription=<br />

FileVersion=1.0.0.0<br />

InternalName=<br />

LegalCopyright=<br />

LegalTrademarks=<br />

OriginalFilename=<br />

ProductName=<br />

ProductVersion=1.0.0.0<br />

Comments=<br />

[Debugging]<br />

DebugSourceDirs=$(BCB)\source\vcl<br />

!endif<br />

# -------------------------------------------------------------------------<br />

--<br />

# MAKE SECTION<br />

# -------------------------------------------------------------------------<br />

--<br />

# This section of the project file is not used by the BCB IDE. It is for<br />

# the benefit of building from the command-line using the MAKE utility.<br />

111


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

# -------------------------------------------------------------------------<br />

--<br />

.autodepend<br />

# -------------------------------------------------------------------------<br />

--<br />

!if "$(USERDEFINES)" != ""<br />

AUSERDEFINES = -d$(USERDEFINES:;= -d)<br />

!else<br />

AUSERDEFINES =<br />

!endif<br />

!if !$d(BCC32)<br />

BCC32 = bcc32<br />

!endif<br />

!if !$d(CPP32)<br />

CPP32 = cpp32<br />

!endif<br />

!if !$d(DCC32)<br />

DCC32 = dcc32<br />

!endif<br />

!if !$d(TASM32)<br />

TASM32 = tasm32<br />

!endif<br />

!if !$d(LINKER)<br />

LINKER = ilink32<br />

!endif<br />

!if !$d(BRCC32)<br />

BRCC32 = brcc32<br />

!endif<br />

# -------------------------------------------------------------------------<br />

--<br />

!if $d(PATHCPP)<br />

.PATH.CPP = $(PATHCPP)<br />

.PATH.C = $(PATHCPP)<br />

!endif<br />

!if $d(PATHPAS)<br />

.PATH.PAS = $(PATHPAS)<br />

!endif<br />

!if $d(PATHASM)<br />

.PATH.ASM = $(PATHASM)<br />

!endif<br />

!if $d(PATHRC)<br />

.PATH.RC = $(PATHRC)<br />

!endif<br />

!if $d(PATHOBJ)<br />

.PATH.OBJ = $(PATHOBJ)<br />

!endif<br />

# -------------------------------------------------------------------------<br />

--<br />

112


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

$(PROJECT): $(OTHERFILES) $(IDLGENFILES) $(OBJFILES) $(RESDEPEN) $(DEFFILE)<br />

$(BCB)\BIN\$(LINKER) @&&!<br />

$(LFLAGS) -L$(LIBPATH) +<br />

$(ALLOBJ), +<br />

$(PROJECT),, +<br />

$(ALLLIB), +<br />

$(DEFFILE), +<br />

$(ALLRES)<br />

!<br />

# -------------------------------------------------------------------------<br />

--<br />

.pas.hpp:<br />

$(BCB)\BIN\$(DCC32) $(PFLAGS) -U$(INCLUDEPATH) -<br />

D$(USERDEFINES);$(SYSDEFINES) -O$(INCLUDEPATH) --BCB {$< }<br />

.pas.obj:<br />

$(BCB)\BIN\$(DCC32) $(PFLAGS) -U$(INCLUDEPATH) -<br />

D$(USERDEFINES);$(SYSDEFINES) -O$(INCLUDEPATH) --BCB {$< }<br />

.cpp.obj:<br />

$(BCB)\BIN\$(BCC32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />

D$(USERDEFINES);$(SYSDEFINES) -n$(@D) {$< }<br />

.c.obj:<br />

$(BCB)\BIN\$(BCC32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />

D$(USERDEFINES);$(SYSDEFINES) -n$(@D) {$< }<br />

.c.i:<br />

$(BCB)\BIN\$(CPP32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />

D$(USERDEFINES);$(SYSDEFINES) -n. {$< }<br />

.cpp.i:<br />

$(BCB)\BIN\$(CPP32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />

D$(USERDEFINES);$(SYSDEFINES) -n. {$< }<br />

.asm.obj:<br />

$(BCB)\BIN\$(TASM32) $(AFLAGS) -i$(INCLUDEPATH:;= -i) $(AUSERDEFINES) -<br />

d$(SYSDEFINES:;= -d) $


APENDICE B <strong>–</strong> TABELA ASCII<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

114


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

APENDICE C <strong>–</strong> OPCODES DA MÁQUINA VIRTUAL<br />

Tipo da<br />

Instrução/opcode<br />

Transferência de<br />

dados<br />

LB, LBU, SB<br />

LH, LHU, SH<br />

LW, SW<br />

LF, LD, SF, SD<br />

MOVI2S, MOVS2I<br />

MOVF, MOVD<br />

MOVFP2I, MOVI2FP<br />

Aritmético/Lógico<br />

ADD, ADDI, ADDU,<br />

ADDUI<br />

SUB, SUBI, SUBU,<br />

SUBUI<br />

Significado<br />

Movimentação de dados entre os registradores e<br />

a memória ou entre um registrador inteiro, de<br />

ponto flutuante ou de propósito especial. Só há<br />

uma forma de endereçamento: deslocamento de<br />

16 bits + o valor de um registrador de uso geral.<br />

Carrega byte, carrega byte sem sinal e armazena<br />

byte<br />

Carrega meia-palavra, carrega meia-palavra sem<br />

sinal, armazena meia palavra<br />

Carrega palavra, armazena palavra (de/para)<br />

registradores inteiros<br />

Carrega número de ponto flutuante de precisão<br />

simples, carrega número de ponto flutuante de<br />

precisão dupla, armazena número de ponto<br />

flutuante de precisão simples, armazena número<br />

de ponto flutuante de precisão dupla<br />

Move de ou para um registrador de uso geral de<br />

ou para um registrador de uso especial<br />

Copia um registrador de ponto flutuante ou um<br />

para de dupla precisão para outro registrador ou<br />

par.<br />

Move 32 bits de/para um registrador de ponto<br />

flutuante de/para um registrador inteiro<br />

Operações em inteiros ou tipos lógicos em<br />

registros de uso geral. Operações aritméticas<br />

com sinalsetam o trap em caso de overflow<br />

Adiciona, adiciona com constante (16 bits); com<br />

sinal e sem.<br />

Subtraia, subtraia com constante (16 bits); com e<br />

sem sinal<br />

MULT, MULTU, DIV, Multiplique e divida, com e sem sinal<br />

115


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

DIVU paraoperadores de ponto flutuante. Todas as<br />

operações com valores de 32-bits<br />

AND, ANDI E lógico e E lógico com constante<br />

OR, ORI, XOP, XOPI<br />

LHI<br />

SLL, SRL, SRA,<br />

SLLI, SRLI, SRAI<br />

S__, S__I<br />

Controle<br />

BEQZ, BNEZ<br />

BFPT, BFPF<br />

J, JR<br />

JAL, JALR<br />

TRAP<br />

RFE<br />

Ponto Flutuante<br />

Ou, Ou com constante, Ou exclusivo e Ou<br />

exclusive com constante<br />

Carrega a metade superior de um registro com<br />

uma constante<br />

Deslocamentos: com constante (S__I) ou com<br />

variável (S__); deslocamentos a esquerda lógico,<br />

a direita lógico e a direita aritmético<br />

Marca se condição: "__" pode ser LT, GT, LE, GE,<br />

EQ, NE (menor, maior, menor ou igual, maior ou<br />

igual, igual, não igual)<br />

Saltos condicionais e desvios. Relativos ao PC<br />

(program counter) ou através de registrador<br />

Salta se o registrador é igual ou diferente a zero.<br />

Deslocamento de 16 bits a partir do PC<br />

Testa o bit de comparação do registrador de<br />

status FP e salta (16 bits a partir do PC)<br />

Salta a partir do PC com deslocamento de 26 bits<br />

ou para endereço no registrador (JR)<br />

Salta e marca retorno: salva PC+4 no R31. O<br />

endereço destino é relative a PC(JAL) ou a um<br />

registro (JALR)<br />

Transfere a execução para o sistema operacional<br />

num endereço armazenado em um vetor<br />

Retorna para o código do usuário de uma<br />

exceção. Retorna a execução para o código do<br />

usuário.<br />

Operações de ponto flutuante em dupla<br />

precisão (DP) ou precisão simples (SP)<br />

ADDD, ADDF Soma números de DP, SP<br />

SUBD, SUBF Subtrai números de DP, SP<br />

MULTD, MULTF Multiplica números de DP, SP<br />

DIVD, DIVF Divide números de DP, SP<br />

CVTF2D, CVTF2I, Instruções de converção: CVTx2y converte do tipo<br />

116


CVTD2F,<br />

CVTD2I, CVTI2F,<br />

CVTI2D<br />

__D, __F<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

x para o tipo y, onde x e y podem ser I para<br />

inteiro, D para precisão dupla e F para simples<br />

precisão. Ambos operandos devem estar em<br />

registradores FP.<br />

Compara números de DP e SP compares: "__"<br />

pode ser LT, GT, LE, GE, EQ, NE(menor, maior,<br />

menor ou igual, maior ou igual, igual, não igual);<br />

Ativa o bit de comparação no registrador de status<br />

FP.<br />

117


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

APENDICE D <strong>–</strong> EMENTAS DE CURSOS DE COMPILAÇÃO<br />

DE OUTRAS UNIVERSIDADES<br />

Instituição: UNESP<br />

URL: http://www.dcce.ibilce.unesp.br/comp/alldisc.html<br />

Disciplina: Construção de <strong>Compilador</strong>es<br />

Pré requisito: Fundamentos em Linguagens e Teoria da Computação e Autorização<br />

do Coordenador do Curso<br />

Ementa: Estudo dos componentes de um compilador, com o projeto de um<br />

compilador para uma linguagem simples, incluíndo os módulos de análise léxica,<br />

sintática e semântica, além do gerador de código e otimizador.<br />

Instituição: UFMG<br />

URL: http://www.dcc.ufmg.br/~mariza/Cursos/<strong>Compilador</strong>es/Comp2001-2/Prog2001-<br />

2/comp_txt.html<br />

Disciplina: <strong>Compilador</strong>es<br />

Pré-Requisitos: Esta disciplina é oferecida aos alunos do sexto período do<br />

Bacharelado em Ciência da Computação da UFMG. Os pré-requisitos da disciplina<br />

são: Algoritmos e Estruturas de Dados I, Algoritmos e Estruturas de Dados II e<br />

Fundamentos da Teoria da Computação.<br />

Programa do Curso: O objetivo da disciplina é ensinar técnicas básicas de<br />

construção de compiladores e conceitos relacionados com linguagens de<br />

programação. A matéria apresentada tem aplicação não somente em projeto de<br />

linguagens de programação, mas é também importante para a compreensão e<br />

implementação de interfaces que tornem mais natural a comunicação<br />

homem/máquina. Concluindo o curso, os alunos deverão ser capazes de definir a<br />

gramática de uma linguagem e programar seu compilador ou interpretador.<br />

Ementa: Gramáticas. Análise léxica. Análise sintática. Tabela de símbolos.<br />

Linguagens intermediárias. Alocação de memória em tempo de execução. Tradução<br />

dirigida por sintaxe.<br />

118


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Instituição: UFMG - Pós-graduação<br />

URL: http://www.dcc.ufmg.br/pos/html/node5.html<br />

Disciplina: Linguagens de Programação e <strong>Compilador</strong>es<br />

Ementa: <strong>Compilador</strong>es, Teoria de Linguagens, Semântica Formal, Tópicos em<br />

<strong>Compilador</strong>es, Tópicos em Linguagens de Programação.<br />

Instituição: Centro Universitário Feevale<br />

URL: http://www.feevale.tche.br/graduacao/icet/cico/ementa.htm#compiladores-B<br />

Disciplina: <strong>Compilador</strong>es.<br />

Ementa: Organização e estrutura de compiladores e interpretadores. Análise léxica.<br />

Análise sintática. Alocação e gerência de memória. Formas internas de programa<br />

fonte. Análise semântica. Geração de código. Optimização de código.<br />

Instituição: Universidade Estadual Vale do Acaraú - Sobral/CE<br />

URL: http://uvanet.br/computacao/ementa.php<br />

Curso: Bacharelado em Ciências da Computação<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: Organização de um compilador. Tabela de símbolos durante a compilação<br />

e execução. Varredura Léxica. Varredura Sintática. Geração de código objeto.<br />

Otimização e Recuperação de Erros. Linguagens para escrever compiladores.<br />

Instituição: Universidade Estadual de Ponta Grossa<br />

URL: http://www.deinfo.uepg.br/ementas.html<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: Estrutura lógica dos compiladores. Fases de análise e síntese. Obtenção de<br />

compiladores. Teoria das linguagens. Gramáticas formais. Autômatos finitos<br />

determinísticos e não determinísticos. Reconhecedores léxicos. Autômatos de pilha.<br />

Reconhecedores sintáticos. Geração e otimização de código. Projeto de um<br />

compilador.<br />

Instituição: Pontifícia Unive rsidade Católica do Rio Grande do Sul<br />

URL: http://pucrs.campus2.br/faci/info/5/<br />

Disciplina: <strong>Compilador</strong>es I<br />

119


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Objetivos: O cumprimento da disciplina busca dar ao aluno, ao final do semestre,<br />

capacidade de: Descrever, formalmente, os componentes de um compilador;<br />

Projetar linguagens de programação; Elaborar rotinas para análise lexicográfica,<br />

gerenciamento de tabelas de símbolos e análise sintática; Projetar compiladores.<br />

Ementa: Tradução e compilação, etapas da compilação. Análise léxica: tabelas de<br />

símbolos. Análise sintática: construção e geração de analisadores, precedência de<br />

operadores, LR. Tradução dirigida à sintaxe: translação, definições, gramáticas de<br />

atributos. Análise semântica estática: verificação de tipos, escopo, equivalência e<br />

compatibilidade, coerção, sobrecarga e polimorfismo.<br />

Programa: Introdução à Compilação, Introdução: Fases de um compilador, Fase de<br />

Análise, Fase de Síntese, Tabela de Símbolos, Detecção de erros, Análise Léxica,<br />

Funções de Analisador Léxico, A relação: Analisadores Léxicos X Autômatos Finitos<br />

X Expressões Regulares, Implementação de Analisadores Léxicos, Tabela de<br />

símbolos, Ferramentas para construção de Analisadores Léxicos, Análise Sintática,<br />

Funções de Analisador Sintático, A relação: Analisadores Sintáticos X Gramáticas<br />

Livres de Contexto, Analisadores Sintáticos Descendentes, Analisador Preditivo,<br />

Analisador Sintático Descendente Recursivo, Analisadores Sintáticos Ascendentes,<br />

Precedência de Operadores, Técnicas LR, Ferramentas para construção de<br />

Analisadores Sintáticos, Tradução dirigida por Sintaxe, Introdução a Tradução<br />

Dirigida por Sintaxe, Definição Dirigida pos Sintaxe, Esquemas de Tradução,<br />

Verificação Semântica, Sistemas de tipos, Sub-linguagem de tipos genérica,<br />

Verificação de tipos estática X dinâmica, Verificação de tipos simples: expressões e<br />

comandos, Equivalência de tipos, Coerção, Sobrecarga, Polimorfismo.<br />

Instituição: Universidade do Planalto Catarinense - UNIPLAC<br />

URL: http://www.uniplac.rct-sc.br/Ensino/Informatica/ementa_biblio_.htm<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: Análise Léxica e Sintática. Tabelas de Símbolos. Esquemas de Tradução.<br />

Ambientes de Tempo de Execução. Linguagens intermediárias. Geração de Código.<br />

Otimização de Código. Montadores. Ligadores.<br />

Sociedade Brasileira de Computação<br />

120


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

URL:http://www.sbc.org.br/notitia/servlet/newstorm.notitia.apresentacao.ServletDeNo<br />

ticia?codigoDaNoticia=38&dataDoJornal=atual<br />

Currículo de Referência da SBC para Cursos de Graduação em Computação e<br />

Informática<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: Análise léxica e sintática. Tabelas de símbolos. Esquemas de tradução.<br />

Ambientes de tempo de execução. Linguagens intermediárias. Geração de código.<br />

Otimização de código. Montadores, ligadores.<br />

Instituição: PUC-Minas<br />

URL: http://www.inf.pucminas.br/dcc/bh/disciplinas/cmpl.html<br />

Curso: Ciência da Computação<br />

Disciplina: <strong>Compilador</strong>es<br />

Objetivos: preparar o aluno para entender o processo de compilação no que tange<br />

aos seus processos internos nos métodos de análise léxica, sintática e semântica,<br />

com o objetivo de otimizar o projeto de sistemas e detalhamento de programas, e<br />

para iniciar o aluno no processo de construção de um compilador.<br />

Ementa: análise léxica, sintática e semântica, geração de código<br />

Instituição: Universidade Federal de Goiás<br />

URL: http://www.inf.ufg.br/~cedric/comp.html<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: O processo de compilação. Análise léxica. O analisador léxico como um<br />

autômato finito. Análise sintática Ascendente e descendente. Tabelas de símbolos:<br />

estruturas de blocos. Análise de contexto e geração de código. Recuperação de<br />

erros. Implementação de um compilador para uma linguagem de alto nível.<br />

Instituição: Universidade Federal de Mato Grosso do Sul<br />

URL: http://www.ufms.br/ensino/grad/ccet/ccomp/ementa.htm<br />

Curso: Ciência da Computação<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: Introdução à compilação. Análise léxica. Análise sintática. Tradução dirigida<br />

por sintaxe. Checagem de tipos. Ambiente de execução. Geração de código<br />

121


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

intermediário. Geração de código. Otimização de código. A construção de um<br />

compilador.<br />

Instituição: Universidade Tiradentes - Sergipe<br />

URL: http://www.unit.br/graduacao/sistemas_de_informacao/ementasgrade2000.htm<br />

Disciplina: Linguagens Formais e <strong>Compilador</strong>es<br />

Ementa: Gramáticas e Autômatos. Gramáticas Livres de Contexto e Autômatos a<br />

Pilha. Gramáticas Irrestritas e Sensíveis ao contexto. Introdução à Arquitetura de<br />

<strong>Compilador</strong>es. Análise Léxica, Sintática e Semântica. Geração de Código<br />

Intermediário. Otimização e Geração de Código.<br />

Instituição: Universidade Federal de Uberlândia<br />

URL: http://www.feelt.ufu.br/graduacao/ementas/ELT81.htm<br />

Disciplina: Construção de <strong>Compilador</strong>es 1<br />

Objetivo: Apresentar noções da teoria de Linguagens Formais e Automáticas.<br />

Capacitar o aluno a construir parte de um compilador de interpretador para<br />

linguagem de alto nível. Ensinar as técnicas de análise léxica e sintática.<br />

Disciplina: Construção de <strong>Compilador</strong>es 2<br />

Ementa: Análise de contexto. Geração de código intermediário. Geração de código.<br />

Otimização de códigos. Recuperação de erros.<br />

Instituição: UFRJ<br />

URL: http://www.dcc.ufrj.br/informatica/curriculo/obrigatorias.html<br />

Disciplina: <strong>Compilador</strong>es I<br />

Ementa: Visão Geral. Tabelas de símbolos. Análise Léxica. Especificação Sintática<br />

de Linguagens de Programação. Análise Sintática Top-Down e Bottom-Up. Formas<br />

intermediárias. Conceitos Básicos de tradução dirigida pela sintaxe. Conceitos<br />

Básicos de Otimização. Recuperação de erros. Conceitos Básicos de Alocação de<br />

Registradores.<br />

Disciplina: <strong>Compilador</strong>es II<br />

Ementa: Revisão de Análise Léxica e Sintática. Especificação Semântica através de<br />

Gramáticas de Atributos. Avaliação de Atributos. Otimização e Geração de Código.<br />

122


ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

Instituição: USP<br />

URL: http://www.ime.usp.br/grad/catalogo/2000/mac/node40.html<br />

Disciplina: Projeto de <strong>Compilador</strong>es<br />

Objetivos: Construção de um compilador e o ensino associado à geração de código<br />

e otimização.<br />

Instituição: Universidade Federal de Lavras - UFLA / MG<br />

URL: http://www.prg.ufla.br/cursos/cienc_comp/ementas_cc.htm<br />

Disciplina: <strong>Compilador</strong>es<br />

Ementa: Gramáticas e Linguagens Formais. Estrutura de um compilador. Análise<br />

léxica. Análise sintática. Análise semântica. Gerador de código intermediário.<br />

Otimização de código.<br />

Conteúdo: O processo de compilação. Implementação de analisadores sintáticos.<br />

recuperação de erros sintáticos. Tabela de símbolos; estrutura de blocos. A análise<br />

de contexto e geração de código objeto. Expressões aritméticas e booleanas.<br />

Comandos repetitivos e de seleção. Variáveis indexadas. Procedimentos e<br />

recursividade. Otimização e alocação de registradores.<br />

123


-, 27<br />

( ), 27<br />

*, 27<br />

?, 27<br />

[ ], 27<br />

{ }, 27<br />

|, 27<br />

+, 27<br />

a<br />

(<br />

*<br />

?<br />

[<br />

{<br />

|<br />

+<br />

A<br />

alfabeto, 19<br />

analisador léxico, 26<br />

analisador sintático, 28<br />

autômato finito<br />

ÍNDICE REMISSIVO<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

determinístico, 21<br />

fita, 21<br />

não-determinísticos, 23<br />

programa, 21<br />

unidade de controle, 21<br />

Backus-Naur-Form. Consulte BNF<br />

BNF, 28<br />

compilador, 24<br />

comprimento, 20<br />

B<br />

C<br />

E<br />

Expressões regulares, 26<br />

gramática, 28<br />

G<br />

L<br />

Lexemas, 26<br />

linguagem, 19<br />

linguagem de origem, 24<br />

padrão, 26<br />

palavra, 20<br />

palavra vazia, 20<br />

P<br />

124


símbolos, 19<br />

inicial, 19<br />

não-terminais, 19<br />

terminais, 19<br />

S<br />

Tokens, 26<br />

vocabulário, 19<br />

ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />

T<br />

V<br />

125

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!