17.01.2013 Views

COMPORT – Compilador Portugol - Nilo Menezes

COMPORT – Compilador Portugol - Nilo Menezes

COMPORT – Compilador Portugol - Nilo Menezes

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

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!