COMPORT – Compilador Portugol - Nilo Menezes
COMPORT – Compilador Portugol - Nilo Menezes
COMPORT – Compilador Portugol - Nilo Menezes
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
UNIVERSIDADE DO AMAZONAS<br />
Instituto de Ciências Exatas<br />
Departamento de Ciência da Computação<br />
<strong>COMPORT</strong> <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
MANAUS <strong>–</strong> AM<br />
SETEMBRO 2003<br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
I
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
<strong>COMPORT</strong> <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Monografia apresentada à banca<br />
examinadora da Universidade do<br />
Amazonas, como exigência parcial para<br />
obtenção do grau de Bacharel em<br />
Processamento de Dados sob a orientação<br />
do Professor Doutor Alberto Nogueira de<br />
Castro Júnior.<br />
MANAUS <strong>–</strong> AM<br />
SETEMBRO 2003<br />
II
<strong>Menezes</strong>, <strong>Nilo</strong><br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Acadêmico [Manaus] 2003.<br />
125p, 29,7cm<br />
Monografia de conclusão de curso <strong>–</strong> Universidade do Amazonas<br />
Área de concentração: <strong>Compilador</strong>es<br />
Orientador(a): Prof(a). Alberto Nogueira de Castro Júnior, PhD<br />
1. <strong>Compilador</strong>es<br />
2. <strong>Portugol</strong><br />
3. Linguagens de programação<br />
III
À memória de José Ney Farias de <strong>Menezes</strong>, meu avô,<br />
responsável pela minha introdução à computação.<br />
IV
Aos meus pais pelo incentivo e suporte.<br />
A minha esposa e filhos pela paciência e finais de semana perdidos.<br />
V
“Quem quer fazer alguma coisa encontra um meio.<br />
Quem não quer fazer nada encontra uma desculpa”<br />
(provérbio árabe)<br />
“Quando se busca o cume da montanha,<br />
não se dá importância às pedras no caminho”<br />
(provérbio oriental)<br />
“As maiores distâncias que devemos percorrer estão dentro de nós mesmos”<br />
(Charles de Gaulle)<br />
VI
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
ESTA MONOGRAFIA FOI SUBMETIDA À COORDENAÇÃO DO CURSO DE<br />
PROCESSAMENTO DE DADOS, COMO PARTE DOS REQUISITOS NECESSÁRIOS À OBTENÇÃO DO<br />
TÍTULO DE BACHAREL EM PROCESSAMENTO DE DADOS, OUTORGADO PELA UNIVERSIDADE DO<br />
AMAZONAS - UA E ENCONTRA-SE À DISPOSIÇÃO DOS INTERESSADOS NA BIBLIOTECA DA REFERIDA<br />
UNIVERSIDADE.<br />
A CITAÇÃO DE QUALQUER TRECHO DESTA MONOGRAFIA É PERMITIDA, DESDE<br />
QUE FEITA DE ACORDO COM AS NORMAS DE ÉTICA CIENTÍFICA.<br />
Banca Examinadora:<br />
_______________________________<br />
Prof. Alberto Nogueira de Castro Júnior, PhD<br />
Universidade do Amazonas<br />
_______________________________<br />
Prof. Edjar de Souza Mota, PhD<br />
Universidade do Amazonas<br />
_______________________________<br />
Prof. Ruiter Braga, MsC<br />
Universidade do Amazonas<br />
Julgado em: ____ / ____ / _______<br />
MANAUS <strong>–</strong> AM<br />
SETEMBRO 2003<br />
VII
DECLARAÇÃO<br />
Declaro que esta monografia foi desenvolvida por mim e, através deste instrumento,<br />
concedo ao Departamento de Ciência da Computação da Universidade do Amazonas<br />
(DCC/UA) o direito de utilizá-la, bem como aos produtos resultantes do trabalho nela<br />
descrito (software, hardware, modelos, algoritmos, etc) nas suas atividades de ensino,<br />
pesquisa e extensão.<br />
_________________________________<br />
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
VIII
RESUMO<br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
Setembro 2003<br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Orientador: Prof. Alberto Nogueira de Castro Júnior, PhD<br />
Este trabalho visa reunir informações sobre a construção de um compilador<br />
da linguagem <strong>Portugol</strong>, com objetivo de servir como um estudo de caso para a disciplina de<br />
Construção de <strong>Compilador</strong>es do curso de Ciência da Computação da Universidade do<br />
Amazonas. A disponibilização de uma ferramenta para estudo e ensino de programação em<br />
português pretende quebrar a barreira da língua inglesa, presente em praticamente todas<br />
as linguagens de programação conhecidas. O trabalho inclui um estudo e especificação de<br />
uma máquina RISC virtual que pode ser analisada e estendida durante cursos de<br />
Organização de Computadores. Foi incluída uma pequena referência bibliográfica que pode<br />
servir como base para o estudo das técnicas de compilação e geração de código.<br />
9
ABSTRACT<br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
Setembro 2001<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Supervisor: Prof. Alberto Nogueira de Castro Júnior, PhD<br />
The purpose of this paper is to collect information about the <strong>Portugol</strong> language<br />
compiler construction and specification. The learning of the English language is a<br />
very difficult problem to Brazilian students who want to learn their first programming<br />
language as they are always written in English. This paper can be used in Compiler<br />
Construction courses. The virtual RISC machine specification included can be used<br />
in the Computers Organization course. It includes a little reference about compiling<br />
and code generation.<br />
10
SUMÁRIO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
DECLARAÇÃO......................................................................................................... VIII<br />
RESUMO.......................................................................................................................9<br />
ABSTRACT.................................................................................................................10<br />
SUMÁRIO....................................................................................................................11<br />
LISTA DE TABELAS ..................................................................................................15<br />
LISTA DE FIGURAS...................................................................................................16<br />
INTRODUÇÃO ............................................................................................................17<br />
1. A COMPILAÇÃO.................................................................................................18<br />
1.1. Linguagem e Sintaxe ..................................................................................................18<br />
1.1.1. Símbolos ...............................................................................................................19<br />
1.1.2. Alfabeto, palavra e comprimento .........................................................................19<br />
1.1.3. Gramática .............................................................................................................20<br />
1.1.4. Autômatos Finitos ................................................................................................21<br />
1.2. <strong>Compilador</strong> .................................................................................................................24<br />
1.3. Análise Léxica e Analisador Léxico ..........................................................................25<br />
1.3.1. Tokens, Padrões e Lexemas .................................................................................26<br />
1.3.2. Expressões regulares.............................................................................................26<br />
1.3.3. Tabela de Símbolos ..............................................................................................28<br />
1.4. Análise Sintática .........................................................................................................28<br />
11
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
1.4.1. Gramáticas livres de contexto...............................................................................28<br />
1.5. Análise Semântica.......................................................................................................29<br />
1.6. Geração de Código .....................................................................................................29<br />
1.7. Otimização de Código ................................................................................................30<br />
2. PORTUGOL.........................................................................................................31<br />
2.1. Comentários ................................................................................................................31<br />
2.2. Tipos básicos ...............................................................................................................31<br />
2.2.1. Numérico ..............................................................................................................31<br />
2.2.2. Literal ...................................................................................................................32<br />
2.2.3. Lógico...................................................................................................................32<br />
2.2.4. Vetores e matrizes ................................................................................................32<br />
2.2.5. Registros ...............................................................................................................32<br />
2.3. Variáveis e identificadores.........................................................................................33<br />
2.4. Declaração de variáveis..............................................................................................33<br />
2.5. Atribuição....................................................................................................................34<br />
2.6. Operadores..................................................................................................................34<br />
2.6.1. Operadores Aritméticos........................................................................................34<br />
2.6.2. Operadores Lógicos..............................................................................................35<br />
2.6.3. Operadores Relacionais ........................................................................................35<br />
2.6.4. Operadores Literais ..............................................................................................35<br />
2.7. Estrutura seqüencial ..................................................................................................36<br />
2.8. Estruturas condicionais..............................................................................................36<br />
2.9. Estruturas de repetição..............................................................................................37<br />
2.10. Procedimentos e Funções .......................................................................................38<br />
12
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
2.11. Módulos ...................................................................................................................39<br />
2.12. Funções pré-definidas ............................................................................................39<br />
2.13. Especificação BNF ..................................................................................................40<br />
3. O COMPILADOR PORTUGOL ...........................................................................43<br />
3.1. Analisador Léxico.......................................................................................................43<br />
3.2. Analisador Sintático ...................................................................................................43<br />
3.3. Gerador de Código .....................................................................................................43<br />
3.4. Funções Adicionais .....................................................................................................43<br />
4. A MÁQUINA VIRTUAL........................................................................................44<br />
4.1. Registradores ..............................................................................................................44<br />
4.2. Formato de Instruções ...............................................................................................45<br />
4.3. Instruções ....................................................................................................................46<br />
4.4. Limitações ...................................................................................................................48<br />
4.5. Implementação............................................................................................................48<br />
CONCLUSÃO .............................................................................................................49<br />
REFERÊNCIA BIBLIOGRÁFICA ...............................................................................50<br />
APÊNDICE A <strong>–</strong> CÓDIGO FONTE ..............................................................................51<br />
SCANNER.H...........................................................................................................................51<br />
SCANNER.CPP ......................................................................................................................55<br />
PARSER.H ..............................................................................................................................65<br />
13
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
PARSER.CPP .........................................................................................................................67<br />
CODEGENERATOR.H.........................................................................................................84<br />
CODEGENERATOR.CPP ....................................................................................................87<br />
FUNCOES.H.........................................................................................................................100<br />
FUNCOES.CPP ....................................................................................................................101<br />
RISC.H ..................................................................................................................................103<br />
RISC.CPP..............................................................................................................................104<br />
INSTRUCOES.H ..................................................................................................................108<br />
PRINCIPAL.CPP .................................................................................................................109<br />
MAKEFILE ..........................................................................................................................110<br />
APENDICE B <strong>–</strong> TABELA ASCII...............................................................................114<br />
APENDICE C <strong>–</strong> OPCODES DA MÁQUINA VIRTUAL.............................................115<br />
APENDICE D <strong>–</strong> EMENTAS DE CURSOS DE COMPILAÇÃO DE OUTRAS<br />
UNIVERSIDADES.....................................................................................................118<br />
ÍNDICE REMISSIVO .................................................................................................124<br />
14
LISTA DE TABELAS<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Tabela 1 - Função programa _________________________________________________ 22<br />
Tabela 2 - Token x Lexema x Padrão___________________________________________ 26<br />
Tabela 3 - Notação para as expressões regulares _________________________________ 27<br />
Tabela 4 - Operadores aritméticos_____________________________________________ 34<br />
Tabela 5 - Operadores lógicos ________________________________________________ 35<br />
Tabela 6 - Operadores Relacionais ____________________________________________ 35<br />
Tabela 7 - Operadores literais ________________________________________________ 35<br />
Tabela 8 - Funções pré-definidas______________________________________________ 39<br />
Tabela 9 <strong>–</strong> Instruções da Máquina Virtual_______________________________________ 47<br />
15
LISTA DE FIGURAS<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Figura 1 - Fita e unidade de controle ......................................................................................21<br />
Figura 2 - Representação gráfica de um autômato..................................................................22<br />
Figura 3 - Exemplo de autômato finito ....................................................................................23<br />
Figura 4 - Diagrama de tradução ............................................................................................24<br />
Figura 5 - Fases de um compilador .........................................................................................25<br />
Figura 6 - O papel do analisador léxico ..................................................................................25<br />
16
INTRODUÇÃO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
A aprendizagem de uma linguagem de programação, normalmente<br />
com símbolos e palavras-chave em inglês, por estudantes brasileiros que não<br />
dominam o idioma é um obstáculo a mais no estudo da computação. Para resolver<br />
este tipo de problema e garantir independência de conteúdo em relação à<br />
linguagens comerciais ou não padronizadas, muitos autores criaram uma linguagem<br />
aportuguesada, normalmente utilizada para descrever algoritmos, geralmente<br />
chamada de <strong>Portugol</strong>.<br />
No entanto, vários autores definiram o <strong>Portugol</strong> como uma forma<br />
traduzida de Pascal ou de “Pascal sem ponto-e-vírgula em português”. Além disso,<br />
a escassez ou inexistência de compiladores de <strong>Portugol</strong> faz com que a tradução<br />
para uma outra linguagem de programação seja etapa necessária e obrigatória para<br />
o teste da lógica num computador.<br />
O objetivo deste trabalho é construir um compilador <strong>Portugol</strong>,<br />
detalhando as fases de construção, mostrando opções e justificando escolhas. Não<br />
só criando uma ferramenta de testes, mas também, material para estudo nas<br />
disciplinas de Construção de <strong>Compilador</strong>es e Linguagens de Programação; e talvez<br />
Sistemas Operacionais e Organização de Computadores.<br />
O texto foi dividido em quatro capítulos. O primeiro capítulo trata da<br />
definição dos termos básicos para o entendimento de todo o texto, desde a<br />
definição de linguagem até as partes e fases de um compilador. O segundo capítulo<br />
cobre a modelagem do <strong>Portugol</strong>, desta vez uma linguagem em português com<br />
características próprias. O terceiro capítulo é a aplicação dos conceitos dos dois<br />
primeiros, nele constrói-se o compilador <strong>Portugol</strong> propriamente dito. No quarto e<br />
último capítulo define-se a máquina virtual, uma vez que o compilador gera<br />
pseudocódigo, com objetivo de garantir portabilidade e transparência entre<br />
plataformas e sistemas operacionais. O código fonte de todos os programas<br />
desenvolvidos se encontram nos apêndices e tabelas importantes nos anexos.<br />
<strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
17
1. A COMPILAÇÃO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
O entendimento do processo de compilação exige o conhecimento de<br />
uma série de termos como linguagem, sintaxe, tokens e lexemas entre outros. O<br />
objetivo deste capítulo é explicar estes termos, dando uma noção geral do que está<br />
por vir, formando uma base comum de conhecimento.<br />
1.1. LINGUAGEM E SINTAXE<br />
Em WIRTH (1996), cada linguagem mostra uma estrutura chamada<br />
gramática ou sintaxe. Por exemplo, uma sentença correta consiste de um sujeito<br />
seguido por um predicado, onde correto significa bem formada. Este fato pode ser<br />
descrito pela seguinte fórmula:<br />
sentença = sujeito predicado.<br />
Se adicionarmos a esta fórmula outras duas:<br />
sujeito = “João” | “Maria”<br />
predicado = “come” | “fala”<br />
Então definiríamos conseqüentemente quatro possíveis sentenças:<br />
João come<br />
João fala<br />
Maria come<br />
Maria fala<br />
Onde o símbolo “|” é pronunciado como “ou”. Estas fórmulas são<br />
chamadas regras sintáticas, produções ou simplesmente equações sintáticas.<br />
Sujeito e predicado são classes sintáticas. Uma notação simplificada omite<br />
identificadores significativos:<br />
S = AB.<br />
A=”a”|”b”.<br />
B=”c”|”d”.<br />
L={ac,ad,bc,bd}<br />
18
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Ao conjunto L de sentenças que são geradas desta forma, ou seja, pela<br />
substituição repetida de sentenças do lado esquerdo pelas do lado direito da<br />
equação; é chamado linguagem.<br />
Formulando os conceitos apresentados mais rigorosamente, uma<br />
linguagem é definida pelo seguinte:<br />
1. Um conjunto de símbolos terminais. São símbolos que ocorrem<br />
em suas sentenças. São chamados terminais por não poderem<br />
ser substituídos por nenhum outro símbolo. O processo de<br />
substituição termina com símbolos terminais. No exemplo, este<br />
conjunto consiste dos elementos a,b,c e d. Este conjunto<br />
também é chamado de vocabulário.<br />
2. Um conjunto de símbolos não-terminais. Estes denotam classes<br />
sintáticas e podem ser substituídos. No exemplo, são os<br />
elementos S, A e B.<br />
3. Um conjunto de equações sintáticas. Estas definem as possíveis<br />
substituições de símbolos não terminais. Uma equação é<br />
especificada para cada símbolo não terminal.<br />
4. Um símbolo inicial. É um símbolo não-terminal. No exemplo S.<br />
Uma linguagem é um conjunto de seqüências de símbolos<br />
terminais que, começando pelo símbolo inicial, podem ser gerados pela<br />
aplicação repetitiva de equações sintáticas, ou seja, substituições.<br />
1.1.1. Símbolos<br />
Símbolos não possuem uma definição formal, são entidades abstratas<br />
básicas, um conceito primitivo, como o ponto na Geometria.<br />
Exemplos de símbolos são as letras do nosso alfabeto ou dígitos de um<br />
número.<br />
1.1.2. Alfabeto, palavra e comprimento<br />
Um alfabeto é um conjunto finito de símbolos. Por exemplo, o alfabeto<br />
da língua portuguesa é composto de letras de “A” até “Z”. No estudo de<br />
19
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
compiladores podemos definir outros alfabetos para fins específicos. Por exemplo:<br />
Σ={a,b} indica um alfabeto chamado Σ, com dois elementos (a e b). Utilizaremos o<br />
símbolo Σ* para denotar todas as palavras que podem ser formadas por um alfabeto<br />
Σ.<br />
Entende-se por palavra uma seqüência ou cadeia de símbolos de um<br />
alfabeto. A palavra vazia será representada por ε e utilizaremos Σ+ para denotar<br />
todas as palavras de um alfabeto Σ, com exceção da palavra vazia. Logo, podemos<br />
concluir que Σ+ = Σ* - { ε }. É bom lembrar que Σ = { } é um alfabeto válido, mesmo<br />
sem possuir símbolos.<br />
Exemplo:<br />
Utilizando a nossa definição anterior de Σ={a,b}, teríamos Σ*={ε, a, b,<br />
aa, bb, aaa, bbb, ...} e Σ+={a, b, aa, bb, aaa, bbb, ...}.<br />
O comprimento de uma palavra é igual ao número de símbolos que ela<br />
possui. Exemplo:<br />
| a | = 1 lê-se o comprimento de “a” é 1.<br />
| aaa | = 3 lê-se o comprimento de “aaa” é 3.<br />
1.1.3. Gramática<br />
Em MENEZES (2001), obtemos a definição formal de gramática:<br />
“Uma gramática é uma quádrupla ordenada G = (V, T, P, S) onde:<br />
V conjunto de símbolos variáveis ou não terminais;<br />
T conjunto de símbolos terminais, disjunto de V;<br />
P conjunto finitos de pares, denominados regras de produção;<br />
S elemento de V denominado variável inicial.”<br />
Na notação acima, a linguagem anterior poderia ser representada por:<br />
G = ( { A, B, S}, { a, b, c, d }, P, S )<br />
Onde P = { S � AB, A � a | b, B � c | d }<br />
Desta forma podemos dizer que L é a linguagem gerada por G, ou seja,<br />
L(G) ou simplesmente GERA(G).<br />
Dizemos que duas gramáticas são equivalentes se e somente se as<br />
linguagens por ela geradas forem iguais, ou seja, supondo G1 e G2 gramáticas, G1<br />
e G2 são equivalentes se e somente se GERA(G1)=GERA(G2).<br />
20
1.1.4. Autômatos Finitos<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Segundo AHO (1995), um reconhecedor para uma linguagem é um<br />
programa que toma como entrada uma cadeia x e responde “sim” se x for uma<br />
sentença da linguagem e “não” caso contrário. Compilamos expressões regulares<br />
(veja 1.3.2) num reconhecedor através da construção de um diagrama de transições<br />
generalizado, chamado autômato finito.<br />
Os autômatos finitos se classificam em determinísticos e nãodeterminísticos.<br />
Um autômato finito determinístico pode ser visto como uma máquina<br />
simples, composta de fita, unidade de controle e programa ou função.<br />
A fita é finita (nos dois sentidos), sendo dividida em células de um símbolo<br />
ou caractere. Esta fita não permite gravação e contém toda a informação de entrada.<br />
Os símbolos pertencem ao alfabeto de entrada.<br />
Figura 1 - Fita e unidade de controle<br />
A unidade de controle possui um número finito e predefinido de estados.<br />
Inicialmente a cabeça de leitura está posicionada no símbolo mais à esquerda da<br />
fita. A cada símbolo lido, desloca-se a cabeça de leitura uma célula para a direita.<br />
O programa é uma função parcial que dependendo do símbolo lido<br />
determina o estado corrente do autômato. É importante notar que um autômato não<br />
possui memória, devendo-se utilizar estados intermediários para armazenar<br />
resultados.<br />
Formalmente, podemos definir um autômato finito determinístico como<br />
uma quíntupla:<br />
M=(Σ,Q,δ,q0,F)<br />
Onde:<br />
Σ Alfabeto de símbolos de entrada<br />
Q Conjunto de estados possíveis do autômato<br />
21
δ Função programa ou de transição<br />
q0 Estado inicial<br />
F Conjunto de estados finais, tal que F ⊂ Q<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
O processamento de um autômato finito M, para uma palavra de entrada<br />
w, consiste na sucessiva aplicação de δ para cada símbolo de w (da esquerda para<br />
a direita), até ocorrer uma condição de parada.<br />
Um autômato finito determinístico pode parar em três casos:<br />
1. Quando o processamento da entrada leva a um estado finito e a<br />
entrada é aceita.<br />
2. Quando um símbolo de entrada possui uma saída indeterminada pela<br />
função programa, neste caso a entrada é rejeitada.<br />
3. Quando a fita acaba e o autômato está num estado não-final, a entrada<br />
é rejeitada.<br />
Um autômato finito sempre pára, uma vez que um novo símbolo de<br />
entrada é lido a cada aplicação da função programa, não existindo a possibilidade<br />
de loop infinito, dada a natureza finita da fita.<br />
Figura 2 - Representação gráfica de um autômato<br />
Um exemplo de autômato finito determinístico seria aquele responsável<br />
por validar uma entrada que possua a seqüência ab, considerando-se Σ={a,b} como<br />
alfabeto, Q={q0, q1,qf} como os possíveis estados e F={qf}.<br />
Sendo δ a função programa abaixo:<br />
Tabela 1 - Função programa<br />
δ a b<br />
q0 q1 q0<br />
q1 q1 qf<br />
Qf qf qf<br />
Graficamente este autômato seria representado por:<br />
22
Figura 3 - Exemplo de autômato finito<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Supondo aabab como entrada, iniciaríamos no estado q0, lendo o “a”<br />
mais à esquerda. Pela função programa da Tabela 1, teríamos trocado de estado<br />
para q1 e leríamos o segundo “a”, permanecendo em q1. Ao lermos o “b”,<br />
trocaríamos de estado para qf, onde permaneceremos, enquanto “a” ou “b” forem<br />
lidos até o fim da fita. Como chegamos a um estado final no fim da fita, este<br />
autômato diz que a seqüência é válida.<br />
Em autômatos finitos não-determinísticos temos a mesma definição<br />
formal, exceto em relação a função programa que pode gerar um conjunto de<br />
estados para um símbolo de entrada.<br />
Ao executar um autômato finito não-determinístico e obtermos um<br />
conjunto de estados como resultado da função programa, “cria-se” uma linha de<br />
execução independente para cada elemento do conjunto. Como se tivéssemos uma<br />
nova máquina para cada elemento, com recursos e destinos próprios.<br />
Todo autômato finito não determinístico pode ser transformado em<br />
autômato finito determinístico, como é provado em MENEZES (2001).<br />
Segundo AHO (1995), tanto os autômatos finitos determinísticos<br />
quanto os não-determinísticos são capazes de reconhecer precisamente expressões<br />
regulares. Conseqüentemente, ambos podem validar exatamente o que estas<br />
expressões podem denotar. Entretanto, existe uma barganha tempo-espaço:<br />
enquanto os autômatos finitos determinísticos podem levar a reconhecedores mais<br />
rápidos que os não determinísticos, um autômato finito determinístico pode ser muito<br />
maior que um não determinístico equivalente.<br />
23
1.2. COMPILADOR<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Segundo WIRTH (1996), programas de computador são formulados em<br />
uma linguagem de programação e especificam classes de processos<br />
computacionais. Computadores, entretanto, interpretam seqüências de instruções<br />
particulares, mas não textos de programas. Assim sendo, o texto do programa deve<br />
ser traduzido em uma seqüência de instruções específicas, antes de poder ser<br />
processado por um computador. Esta tradução pode ser automatizada, o que implica<br />
que pode ser formulada como um programa. O programa de tradução é chamado<br />
compilador e o texto a ser traduzido é chamado de texto fonte ou código fonte.<br />
Definido em AHO (1995) como: “um compilador é um programa que lê<br />
um programa escrito em uma linguagem <strong>–</strong> a linguagem de origem <strong>–</strong> e o traduz em<br />
um programa equivalente em outra linguagem <strong>–</strong> a linguagem destino. Como uma<br />
importante parte no processo de tradução, o compilador reporta ao seu usuário a<br />
presença de erros no programa origem”.<br />
Figura 4 - Diagrama de tradução<br />
A linguagem de origem pode ser qualquer linguagem de alto nível<br />
como C, Pascal ou Modula e a de destino qualquer outra linguagem de alto nível ou<br />
código de máquina de qualquer processador.<br />
Na Figura 4, vemos o programa fonte, escrito na linguagem de origem,<br />
o compilador e o programa objeto, escrito na linguagem destino.<br />
Um compilador pode ter várias partes como: analisador léxico,<br />
analisador sintático, analisador semântico, otimizador e gerador de código. Um<br />
esquema de todas as suas partes e interelações pode ser visto na Figura 5 abaixo.<br />
24
Figura 5 - Fases de um compilador<br />
1.3. ANÁLISE LÉXICA E ANALISADOR LÉXICO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Em AHO (1995), análise léxica é a primeira fase de um compilador.<br />
Sua principal tarefa é ler os caracteres de entrada e produzir como saída uma<br />
seqüência de tokens que serão utilizados na análise sintática. Esta interação é<br />
normalmente implementada fazendo com que o analisador léxico seja uma subrotina<br />
do analisador sintático (parser). Ao receber o comando “obter próximo token”<br />
do parser, o analisador léxico lê caracteres da entrada até que identifique o próximo<br />
token. Este processo pode ser visualizado na figura abaixo:<br />
Figura 6 - O papel do analisador léxico<br />
25
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Como o analisador léxico é a parte do compilador que lê o texto fonte<br />
(origem), ele também pode realizar outras funções secundárias como remover<br />
espaços em branco, comentários e geração de mensagens de erro com referências<br />
a linhas do programa.<br />
1.3.1. Tokens, Padrões e Lexemas<br />
É impossível falar sobre análise léxica e analisadores léxicos sem<br />
definir o significado de tokens, padrões e lexemas.<br />
Tokens são símbolos terminais na gramática de uma linguagem. Na<br />
maioria das linguagens de programação, as seguintes construções são tratadas<br />
como tokens: palavras-chave, operadores, identificadores, constantes, cadeias<br />
literais (strings) e símbolos de pontuação como parênteses, vírgulas e pontos.<br />
Um padrão (pattern) é uma regra descrevendo o conjunto de lexemas<br />
que podem representar um token na linguagem. Estas regras normalmente são<br />
descritas na forma de expressões regulares (Ver 1.3.2).<br />
Lexemas são seqüências de caracteres descritas por um padrão de um<br />
token. Ou seja, o lexema é o valor do token, muitas vezes aparecendo como um<br />
atributo para as fases seguintes de compilação. Enquanto o analisador léxico<br />
procura por tokens, na geração de código precisaremos dos lexemas para produzir<br />
significado.<br />
Exemplo: 3.1415<br />
Tabela 2 - Token x Lexema x Padrão<br />
Token Lexema Padrão<br />
Numero 3.1415 ([+,-])([0-9])*(.([0-9])+)<br />
1.3.2. Expressões regulares<br />
Expressões regulares são uma forma muito interessante de descrever<br />
padrões, especialmente aqueles que consistem em cadeias de caracteres. Através<br />
destas expressões podemos especificar que seqüências de caracteres são aceitas<br />
em um token, especificando caracteres opcionais e o número de repetições aceitos.<br />
26
3, abaixo:<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
A notação utilizada nos exemplos deste texto é especificada na Tabela<br />
Tabela 3 - Notação para as expressões regulares<br />
Símbolo Significado<br />
+ Indica repetição de 1..n.<br />
Exemplo: [a-z]+<br />
* Indica repetição de 0..n.<br />
Exemplo: [0-9]*<br />
? Denota que um item é opcional.<br />
Exemplo: [0-9]?<br />
[ ] Utilizados para definir conjuntos de caracteres.<br />
Exemplo: [afgh] [159]<br />
( ) Utilizados para agrupar itens.<br />
Exemplo: ([0-9]+)?<br />
- Indica faixa em conjuntos.<br />
Exemplo: [0-9] [a-z] [A-Z]<br />
{ } Indicam um número conhecido de repetições.<br />
Caso haja um número mínimo e um máximo,<br />
pode-se representar a faixa utilizando uma “,“.<br />
| Significa “ou”. Aparece entre parênteses e<br />
separa os elementos de uma lista. Somente um<br />
item da lista pode ser usado por vez.<br />
^ Denota início de linha<br />
$ Fim de linha<br />
Exemplos de uso:<br />
Exemplo 1: [0-9] Indica que um caractere, na faixa de 0 à 9 é aceito, ou seja, o<br />
conjunto {0,1,2,3,4,5,6,7,8,9}.<br />
Exemplo 2: [a-z] O mesmo do exemplo anterior, mas para letras minúsculas. É<br />
importante notar que para aceitar maiúsculas e minúsculas é necessário a<br />
expressão: [A-Za-z]<br />
Exemplo 3: (+|-)?[0-9]{1,10} Indica que podemos ter o símbolo “-“ ou “+” uma ou<br />
zero vezes, seguido de dígitos de 0 à 9 em número mínimo de uma ocorrência e<br />
máximo de 10.<br />
27
1.3.3. Tabela de Símbolos<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
É uma estrutura de dados utilizada para armazenar atributos dos<br />
tokens. Ela começa a ser preenchida pelo analisador léxico, mas continua<br />
recebendo dados das outras fases de compilação. Um exemplo é o reconhecimento<br />
de um número, considerando-se como referência a Tabela 2, teríamos dois campos<br />
na tabela de símbolos: o token e o lexema. Em identificadores mais complexos,<br />
como variáveis, poderíamos ter outros campos como o tipo da variável e até mesmo<br />
informações sobre diversos identificadores, como se são nomes de procedimentos,<br />
funções ou rótulos.<br />
O uso de uma tabela de símbolos para a representação das palavras<br />
reservadas de uma linguagem dá flexibilidade à sua extensão, além de proporcionar<br />
um método único para identificação de identificadores, como visto em AHO (1995) e<br />
WIRTH (1996).<br />
As tabelas de símbolos também são responsáveis pelo registro do<br />
endereço de identificadores, possibilitando a tradução de instruções de salto,<br />
chamadas de procedimentos e acesso a variáveis de memória.<br />
1.4. ANÁLISE SINTÁTICA<br />
Segundo AHO (1995), o analisador sintático (parser) obtém uma<br />
seqüência de tokens do analisador léxico e verifica se esta seqüência pode ser<br />
gerada pela gramática da linguagem.<br />
Todas as linguagens de programação possuem regras que descrevem<br />
a estrutura sintática de programas corretamente formados. A sintaxe de uma<br />
linguagem de programação pode ser descrita através de uma gramática livre de<br />
contexto ou notação BNF (Backus-Naur-Form).<br />
1.4.1. Gramáticas livres de contexto<br />
Segundo WIRTH (1996), o termo livre de contexto deve-se a Chomsky<br />
e indica que a substituição do símbolo à esquerda da � pela seqüência derivada da<br />
direita é sempre permitida, independente do contexto em que o símbolo foi inserido.<br />
28
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Esta restrição de liberdade de contexto é aceitável e desejável para linguagens de<br />
programação.<br />
Muitas linguagens de programação possuem estruturas que são<br />
naturalmente recursivas que podem ser definidas por gramáticas livres de contexto.<br />
Por exemplo, poderíamos ter uma declaração condicional definida por uma regra<br />
como:<br />
se E então S1 senão S2<br />
Esta forma de declaração condicional não pode ser expressa através<br />
de uma expressão regular. Por outro lado, utilizando a variável sintática stmt para<br />
denotar a classe da declaração e expr a classe das expressões, poderíamos<br />
expressar a declaração condicional como:<br />
1.5. ANÁLISE SEMÂNTICA<br />
stmt � se expr então stmt senão stmt<br />
Segundo AHO (1995), a fase de análise semântica verifica o código<br />
fonte para detectar erros de semântica e ao mesmo tempo coleta informações de<br />
tipo para a geração de código. Usando a estrutura hierárquica gerada pela fase de<br />
análise sintática, operadores e operandos de expressões e declarações são<br />
identificados. Um importante componente da análise semântica é a verificação de<br />
tipos. Nesta fase o compilador verifica se cada operador tem os operandos<br />
permitidos pela especificação da linguagem. Um exemplo é a utilização de números<br />
para índices de vetores. A maioria das linguagens permite o uso apenas de números<br />
inteiros, sendo números reais tratados como erro neste caso.<br />
1.6. GERAÇÃO DE CÓDIGO<br />
Nesta fase a representação intermediária do código é traduzida para a<br />
linguagem de máquina da máquina alvo, ou para a linguagem destino. Entre as<br />
tarefas do gerador de código estão: gerenciamento de memória, seleção de<br />
instruções e alocação de registradores entre outras.<br />
29
1.7. OTIMIZAÇÃO DE CÓDIGO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Segundo AHO (1995), compiladores devem produzir código tão bons<br />
quanto se fossem escritos à mão. A realidade é que este objetivo só é alcançado em<br />
poucos casos e com dificuldade. Entretanto, o código produzido por compiladores<br />
pode quase sempre rodar mais rápido ou ocupar menos espaço, ou ainda ambos.<br />
Esta melhoria é alcançada através de transformações que tradicionalmente são<br />
chamadas de “otimizações”, sendo o termo otimização não muito preciso, já que não<br />
há garantias de que o código resultante é o melhor possível.<br />
O nível e o tipo de otimizações podem variar entre otimizações<br />
independentes de máquina e otimizações dependentes de máquina. As<br />
independentes são normalmente simplificações de expressões através de regras<br />
matemáticas como no exemplo: x = x * 1. As dependentes podem ocorrer em função<br />
da plataforma destino, como o uso de registradores e operações especiais de<br />
máquina.<br />
30
2. PORTUGOL<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
O portugol como linguagem não é bem definido, variando de autor para<br />
autor. Na maioria das vezes é apenas uma tradução de Pascal para o português,<br />
inclusive trazendo símbolos que o tornam perigoso para uso no estudo de<br />
algoritmos, justamente por o tornar tão dependente de uma certa linguagem. O<br />
<strong>Portugol</strong>, aqui definido, será baseado em [FARRER], mas com algumas<br />
modificações, principalmente, nas estruturas de repetição e de bloco.<br />
2.1. COMENTÁRIOS<br />
Várias formas de comentários são aceitas, com o objetivo de se estimular<br />
seu uso no código. Tanto o // usado no C e C++ quanto o # (cerquilha) usado no<br />
Shell do Unix são aceitos como comentários de uma linha. Os { } (colchetes) são a<br />
única forma aceita de comentários para várias linhas ou comentários de bloco.<br />
2.2. TIPOS BÁSICOS<br />
Como o objetivo do <strong>Portugol</strong> aqui definido é o ensino de lógica de<br />
programação e algoritmos, os tipos básicos serão o mais restritos possíveis, a fim de<br />
promover a independência de linguagem e de máquina.<br />
2.2.1. Numérico<br />
O tipo numérico resume todos os tipos para cálculo aritmético. Não se faz<br />
distinção entre números inteiros ou números reais (ponto flutuante). Caso um<br />
algoritmo necessite de alguma propriedade específica de algum desses tipos deverá<br />
especificá-la através de funções. A vírgula é o símbolo usado para separar a parte<br />
decimal dos números. Não se escrevem os separadores de milhar.<br />
31
2.2.2. Literal<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Tipo responsável por armazenar seqüências de letras e símbolos, o<br />
popular tipo string de muitas linguagens. Para simplificar o entendimento do<br />
<strong>Portugol</strong>, o tipo caractere, será suprimido e tratado como um literal de comprimento<br />
um. O tratamento do tamanho do caractere será tratado via funções. A alocação de<br />
espaço para armazenamento é automática.<br />
2.2.3. Lógico<br />
Responsável pelo armazenamento das constantes verdadeiro e falso. O<br />
tipo lógico é muito importante na definição de algoritmos, sendo o tipo básico<br />
retornado pela execução de várias operações.<br />
2.2.4. Vetores e matrizes<br />
É permitida a criação de vetores e matrizes de qualquer tipo básico,<br />
incluindo registros definidos pelo usuário. As operações sobre matrizes e vetores<br />
deverão ser especificadas na forma de algoritmos escritos em <strong>Portugol</strong>, logo não são<br />
definidas na linguagem. As operações básicas deste tipo são as mesmas permitidas<br />
em seus tipos básicos. A palavra-chave matriz é reservada para este tipo. A base ou<br />
número inicial dos índices sempre é 1.<br />
Exemplo:<br />
a matriz numérico[30] // Cria uma matriz 30x1<br />
b matriz lógico[3][3] // Cria uma matriz 3x3<br />
2.2.5. Registros<br />
São definidos pela palavra-chave registro e são compostos pelos campos<br />
declarados, da mesma forma que variáveis, até a palavra fimregistro.<br />
Exemplo:<br />
registro dia, mês, ano numérico<br />
nome literal<br />
matriculado lógico<br />
fimregistro<br />
32
2.3. VARIÁVEIS E IDENTIFICADORES<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
As variáveis são uma importante parte da linguagem. Qualquer<br />
identificador válido tem como primeiro símbolo uma letra. Números e _ (sublinha)<br />
são aceitos após o segundo caractere. Fica estabelecido o tamanho máximo de 32<br />
caracteres para o tamanho do maior nome válido.<br />
É importante observar que símbolos ignorados ou proibidos por outros<br />
compiladores são aceitos em <strong>Portugol</strong>. Como exemplo os caracteres acentuados da<br />
língua portuguesa: â, á, ã, à, ê, é, è, ..., ç.<br />
Uma vez declarado um nome de identificador com acentos, estes não<br />
serão considerados opcionais. Assim sendo, a variável avião é diferente da variável<br />
aviao. Não há distinção entre maiúsculas e minúsculas.<br />
2.4. DECLARAÇÃO DE VARIÁVEIS<br />
Não há uma seção específica para declaração de variáveis, mas esta<br />
deve ser feita no início de uma seção, seja o programa principal ou um<br />
procedimento/função. O comando declare será usado para declarar as variáveis em<br />
<strong>Portugol</strong>, sendo permitida a enumeração de identificadores do mesmo tipo, mas não<br />
a declaração de tipos diferentes na mesma linha.<br />
Exemplo:<br />
declare a, b, c numérico<br />
declare d, e, f literal<br />
declare g, h, i lógico<br />
declare j registro dia, mês, ano inteiro<br />
nome literal<br />
matriculado lógico<br />
fimregistro<br />
Exemplo de declaração inválida:<br />
declare a numérico, b literal<br />
33
declarou.<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
A visibilidade de uma variável é definida pelo escopo da estrutura que a<br />
2.5. ATRIBUIÇÃO<br />
A atribuição de valores será denotada pelo símbolo :=.<br />
Só é permitido a atribuição de um valor por vez. Construções do tipo<br />
a:=b:=c:=0 não são aceitas. Uma atribuição válida possui um identificador válido à<br />
esquerda e uma expressão do mesmo tipo do identificador a direita.<br />
Exemplos:<br />
declare a,b numérico<br />
declare c,d literal<br />
declare e,f lógico<br />
a := 5<br />
b := 4,5<br />
2.6. OPERADORES<br />
2.6.1. Operadores Aritméticos<br />
Tabela 4 - Operadores aritméticos<br />
Operação Símbolo<br />
Adição +<br />
Subtração -<br />
Divisão /<br />
Multiplicação *<br />
34
2.6.2. Operadores Lógicos<br />
Tabela 5 - Operadores lógicos<br />
Operação Símbolo<br />
inversão <strong>–</strong> não não<br />
junção e<br />
disjunção ou<br />
2.6.3. Operadores Relacionais<br />
2.6.4. Operadores Literais<br />
Tabela 6 - Operadores Relacionais<br />
Operação Símbolo<br />
Igualdade =<br />
Maior ><br />
Menor <<br />
Maior ou igual >=<br />
Menor ou igual <br />
Menor <<br />
Maior ou igual >=<br />
Menor ou igual
2.7. ESTRUTURA SEQÜENCIAL<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
O programa começa com a palavra programa e termina em<br />
fimprograma. A importação de outros módulos deve ser especificada como um<br />
comando, logo após a declaração de programa.<br />
Em portugol não se utilizam símbolos especiais ou visuais para marcar o<br />
fim de linha e sim o retorno de carro, mais conhecido pela tecla ENTER, definido na<br />
posição 13 da tabela ASCII. Para manter uma independência de sistemas<br />
operacionais, mas para não dificultar a criação dos programas, seqüências de<br />
símbolos 10 e 13, utilizadas no MS-DOS, como o 10 do UNIX serão tratadas como<br />
fim de linha.<br />
Qualquer símbolo ou comando, exceto comentários, feitos fora da<br />
declaração de programa serão considerados erro. Funções e procedimentos devem<br />
ser declarados em módulos externos e importados pelo programa que as utilize.<br />
Esta decisão visa estimular a modularização do código, bem como a criação de<br />
arquivos menores e mais fáceis de entender.<br />
2.8. ESTRUTURAS CONDICIONAIS<br />
Apenas duas são definidas em <strong>Portugol</strong>, o se e o caso.<br />
O se avalia uma condição ou expressão condicional, que<br />
obrigatoriamente retorna um valor lógico. Dependendo deste valor a execução passa<br />
para o bloco então, ou senão, para valores verdadeiros e falsos, respectivamente. A<br />
fim de eliminar a criação de blocos, tipo início e fim, define-se em <strong>Portugol</strong> o<br />
fimentão e o fimsenão, de uso obrigatório.<br />
Exemplo:<br />
se a > b<br />
então a = 1<br />
fimentão<br />
senão b = 1<br />
fimsenão<br />
fimse<br />
36
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
A estrutura caso permite a avaliação de múltiplos valores e admite<br />
variável dos tipos lógico, numérico e literal.<br />
caso idade<br />
10: i := 10<br />
20: j := 10<br />
30: k := 30<br />
fimcaso<br />
2.9. ESTRUTURAS DE REPETIÇÃO<br />
Utiliza-se o faça, enquanto e repita.<br />
O faça substitui o for da maioria das outras linguagens. Sua construção é<br />
demonstrada abaixo:<br />
faça a de 1 até 10<br />
<br />
fimfaça<br />
A estrutura acima executará os comandos dez vezes, variando o valor de<br />
a de 1 até 10. A variável de controle, no exemplo acima “a”, não deve ter seu valor<br />
alterado pelos comandos internos. Sempre ao chegar no fimfaça o valor da variável<br />
de controle é incrementado de 1. O valor de “a” após o fimfaça será igual ao limite<br />
estipulado, no caso 10.<br />
O enquanto substitui o while.<br />
enquando a > b<br />
<br />
fimenquanto<br />
A estrutura enquanto executa o bloco de comandos até que a condição<br />
seja falsa. É importante notar que os comandos podem nem ser executados,<br />
dependendo da condição inicial.<br />
O repita é definido como uma estrutura de repetição básica. O ponto de<br />
verificação e interrupção é livre, sendo especificado pelo comando interrompa.<br />
repita<br />
<br />
37
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
interrompa<br />
fimrepita<br />
Após a execução do interrompa, a execução vai para depois de<br />
fimrepita.<br />
2.10. PROCEDIMENTOS E FUNÇÕES<br />
Procedimentos e funções seguem as mesmas regras de um programa,<br />
exceto por não poderem importar módulos.<br />
A declaração de procedimento é exemplificada abaixo:<br />
procedimento calculaA ( i numérico<br />
j literal<br />
k lógico<br />
)<br />
<br />
fimprocedimento<br />
As variáveis declaradas em uma função ou procedimento são internas a<br />
eles, ou seja, possuem escopo local.<br />
Para denotar a passagem por parâmetro, colocamos o prefixo param<br />
antes do nome do parâmetro. Exemplo:<br />
procedimento calculaA ( param i numérico<br />
j literal<br />
k lógico<br />
)<br />
<br />
fimprocedimento<br />
Neste caso somente o parâmetro i é passado por referência. Caso haja<br />
mais de um parâmetro na mesma linha, todos serão marcados como passados por<br />
referência:<br />
procedimento calculaA (param i, j, k numérico)<br />
38
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
As funções obedecem todas as regras e possuem todas as propriedades<br />
dos procedimentos. O que diferencia uma função é sua capacidade de retornar um<br />
valor. O valor a ser retornado deve ser atribuído a um identificador, com o mesmo<br />
nome e tipo da função de seu tipo de retorno, antes do fimfunção. Observar que<br />
esta atribuição não força o retorno, o que só ocorre ao executarmos o fimfunção.<br />
Exemplo:<br />
função calculaB( i numérico<br />
j literal<br />
k lógico<br />
) numérico<br />
<br />
calculaB:=r<br />
fimfunção<br />
2.11. MÓDULOS<br />
Os módulos iniciam com a palavra módulo seguida do nome e terminam<br />
com fimmodulo. Este nome deve ser utilizado na hora de importar o módulo no<br />
programa principal ou em outro módulo, através da cláusula importe.<br />
As variáveis declaradas dentro do módulo, mas fora de funções e<br />
procedimentos são globais ao módulo, podendo ser acessadas de fora se utilizando<br />
o nome do módulo seguido de ponto e nome da variável. Não é permitida a<br />
repetição de nomes de módulos ou a re-declaração destes na forma de variável.<br />
2.12. FUNÇÕES PRÉ-DEFINIDAS<br />
Tabela 8 - Funções pré-definidas<br />
Formato Função<br />
inteiro(x numérico) numérico Retorna a parte inteira de um número.<br />
tamanho(y literal) numérico Retorna o tamanho em caracteres de uma<br />
variável literal. 0 caso esteja vazia.<br />
ordem(x literal) numérico Retorna o valor correspondente ao primeiro<br />
caractere da seqüência passada na tabela<br />
39
Formato Função<br />
ASCII.<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
caractere(x numérico) literal Retorna o caractere correspondente a posição<br />
denotada por x na tabela ASCII.<br />
número(x literal) numérico Converte uma seqüência literal em número.<br />
Caso não consiga, retorna 0.<br />
lit(n numérico) literal Converte um número em seqüência literal.<br />
2.13. ESPECIFICAÇÃO BNF 1<br />
S = “programa” identificador novalinha comandos “fimprograma” novalinha<br />
digito = [“0”| ”1”| ”2”| “3”| ”4”| ”5”| ”6”| ”7”| “8”| ”9”]<br />
letras-minusculas = [“a”|”b”|”c”|”d”| “e”| “f”| “g”| “h”| “i”| “j”| “k”| “l”| “m”| “n”| “o”| “p”|<br />
“q”| “r”|”s”|”t”| “u”| “v”| “w”| “x”| “y”| “z”| “á”| “é”| “í”| “ó”| “ú”| “ý”|<br />
“ã”| “õ”| “ñ”| “à”| “è”| “ì”| “ò”| “ù”| “ä”| “ë”| “ï”| “ö”| “ü”| “ÿ”| “â”| “ê”|<br />
“î”| “ô”| “û”| “ç”]<br />
letras-maiusculas = [“A”|”B”|”C”|”D”| “E”| “F”| “G”| “H”| “I”| “J”| “K”| “L”| “M”| “N”| “O”|<br />
“P”| “Q”| “R”|”S”|”T”| “U”| “V”| “W”| “X”| “Y”| “Z”| “Á”| “É”| “Í”| “Ó”|<br />
“Ú”| “Ý”| “Ô| “Õ”| “Ñ”| “À”| “È”| “Ì”| “Ò”| “Ù”| “Ä”| “Ë”| “Ï”| “Ö”|<br />
“Ü”| “Ÿ”| “”| “Ê”| “Δ| “Ô”| “Û”| “Ç”]<br />
letra = (letras-minusculas|letras-maiusculas)<br />
numeral = digito{digito}<br />
numero = [+|-] numeral<br />
valor = numero | identificador<br />
literal = \"{*}\"<br />
logico = “verdadeiro” | ”falso”<br />
identificador = letra{letra|digito|”_”}<br />
novalinha = \n | \r | \n\r<br />
op-logico = “não” | “e” | “ou”<br />
op-numerico = “+” | “-“ | “*” | “/”<br />
op-literal = “+” | “=” | “>” | “=” | “
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
op-relacional = “” | “>=” | “
expressao-logica = valor-logico |<br />
expressão-numerica op-relacional expressao-numerica |<br />
valor-logico op-logico expressao-logica<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
42
3. O COMPILADOR PORTUGOL<br />
3.1. ANALISADOR LÉXICO<br />
3.2. ANALISADOR SINTÁTICO<br />
3.3. GERADOR DE CÓDIGO<br />
3.4. FUNÇÕES ADICIONAIS<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
43
4. A MÁQUINA VIRTUAL<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
A máquina virtual escolhida é baseada na de WIRTH (1996), que por<br />
sua vez se baseia na máquina DLX de Hannessy e Patterson (1995) 2 , aproximandose<br />
da arquitetura da máquina MIPS.<br />
O conjunto completo de instruções da máquina DLX encontra se no<br />
apêndice C. O subconjunto particular implementado é descrito a seguir.<br />
4.1. REGISTRADORES<br />
Registradores são memórias especiais à disposição do processador<br />
para diversos fins. Em linguagem de máquina, valores são guardados na memória e<br />
as operações com estes são realizadas nos registradores. Diversas instruções,<br />
especialmente em máquinas RISC, utilizam registradores como seus operandos.<br />
Diferente de máquinas CISC (conjunto de instruções complexo) que possuem<br />
dúzias de formas diferentes de endereçamento (gerando uma instruções para cada<br />
um deles), as máquinas RISC trocam o número de instruções pelo número de<br />
registradores. Uma máquina CISC tem normalmente de 4 a 6 registradores e<br />
enquanto máquinas RISC operam com 32. Este número também é justificado pelo<br />
pequeno número de formas de endereçamento disponível para máquinas RISC, o<br />
que obriga que valores sejam movidos da memória para um registrador antes de<br />
serem utilizados em uma instrução.<br />
A máquina virtual possui 32 registradores de 32 bits cada. Estes<br />
registradores são nomeados de R0 a R31, sendo alguns de uso específico:<br />
R0 sempre contém o valor 0.<br />
R31 é utilizado para armazenar o endereço de retorno em instruções<br />
de salto.<br />
2 HANNESEY J.L., PATTERSON D.A. Computer Architecture <strong>–</strong> A Quantitative<br />
Approach. Morgan Kaufmann:1995<br />
44
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
IR, ou Instruction Register, contém a instrução atualmente sendo<br />
executada.<br />
PC, ou Program Counter, contém o endereço da próxima instrução a<br />
ser lida da memória.<br />
4.2. FORMATO DE INSTRUÇÕES<br />
A máquina virtual utiliza três formatos de instruções:<br />
Formato 1 <strong>–</strong> Operações com constantes<br />
6 5 5 16<br />
Op a b c<br />
op é o código de 6 bits do opcode<br />
a é o número de um registrador (5 bits)<br />
b é o número de um registrador (5 bits)<br />
c é a constante de 16 bits<br />
Formato 2 <strong>–</strong> Operações com registros<br />
6 5 5 11 5<br />
Op a b c<br />
op é o código de 6 bits do opcode<br />
a é o número de um registrador (5 bits)<br />
b é o número de um registrador (5 bits)<br />
c é o número de um registrador (5 bits)<br />
Formato 3 <strong>–</strong> Operações de Salto<br />
6 26<br />
Op c<br />
op é o código de 6 bits do opcode<br />
c é o deslocamento com 26 bits<br />
45
4.3. INSTRUÇÕES<br />
Instrução Significado Formato Descrição<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
ADD a,b,c R.a := R.b + R.c 2 Adição entre registradores<br />
ADDI a,b,c R.a := R.b + c 1 Adição com constante<br />
SUB a,b,c R.a := R.b - R.c 2 Subtração entre<br />
registradores<br />
SUBI a,b,c R.a := R.b - c 1 Subtração com constante<br />
MUL a,b,c R.a := R.b * R.c 2 Multiplicação entre<br />
registradores<br />
MULI a,b,c R.a := R.b * c 1 Multiplicação com constante<br />
DIV a,b,c R.a := R.b / R.c 2 Divisão entre registradores<br />
DIVI a,b,c R.a := R.b / c 1 Divisão com constante<br />
MOD a,b,c R.a := Rb % R.c 2 Módulo entre registradores<br />
MODI a,b,c R.a := Rb % c 1 Módulo com constante<br />
CMP a,b,c R.a := Ra <strong>–</strong> Rc 2 Comparação entre<br />
registradores<br />
CMPI a,b,c R.a := Ra <strong>–</strong> c 1 Comparação com constante<br />
CHK a,c 0
Instrução Significado Formato Descrição<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
XOR a,b,c R.a := R.b ^ R.c 2 Ou exclusivo entre<br />
registradores<br />
XORI a,b,c R.a := R.b ^ c 1 Ou exclusivo com constante<br />
LSH a,b,c R.a := LSH(R.b,R.c) 2 Deslocamento à esquerda<br />
LSHI a,b,c R.a := LSH(R.b, c) 1 Deslocamento à esquerda<br />
com constante<br />
ASH a,b,c R.a := ASH(R.b,R.c) 2 Ajuste aritmético entre<br />
registradores<br />
ASHI a,b,c R.a := ASH(R.b,c) 1 Ajuste aritmético com<br />
constante<br />
LDW a,b,c R.a := Mem[R.b+c] 1 Carrega palavra<br />
LDB a,b,c R.a := Mem[R.b+c] 1 Carrega byte<br />
POP a,b,c R.a := Mem[R.b];<br />
R.b := R.b+c<br />
1 Retira da pilha (pop)<br />
STW a,b,c Mem[R.b+c]:=R.a 1 Armazena palavra<br />
STB a,b,c Mem[R.b+c]:=R.a 1 Armazena byte<br />
PSH a,b,c R.b:=R.b-c;<br />
Mem[R.b]:=R.a<br />
1 Coloca na pilha (push)<br />
BEQ a,c 2 Salta para c seR.a = 0<br />
BNE a,c 2 Salta para c seR.a 0<br />
BLT a,c 2 Salta para c seR.a < 0<br />
BGE a,c 2 Salta para c seR.a >= 0<br />
BGT a,c 2 Salta para c seR.a > 0<br />
BLE a,c 2 Salta para c seR.a
4.4. LIMITAÇÕES<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
A máquina implementada não possui sistema operacional ou suporte a<br />
operações de ponto flutuante. Tais limitações são candidatas para futuras extensões<br />
deste projeto.<br />
A implementação de ponto flutuante exige o suporte de instruções para<br />
operação de simples e dupla precisão, bem como suporte aos registradores de<br />
ponto flutuante. Instruções para conversão de tipo também são necessárias. A<br />
adoção de um padrão numérico deve observar as normas do IEEE<br />
4.5. IMPLEMENTAÇÃO<br />
A máquina virtual encontra-se nos arquivos RISC.H e RISC.CPP,<br />
ambos no anexo A.<br />
48
CONCLUSÃO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
O estudo de compiladores se mostra fundamental, não só para a área de<br />
compilação, mas para diversos assuntos afins. Compreender o processo de<br />
construção e implementação de uma linguagem é um processo rico e proveitoso. A<br />
criação do ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong> é de grande valor para futuras extensões<br />
e pode ser o embrião para projetos mais ambiciosos, como orientação a objetos e<br />
interface gráfica, entre outros.<br />
49
REFERÊNCIA BIBLIOGRÁFICA<br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
AHO, Alfred. SETHI, Ravi. ULLMAN Jeffrey. <strong>Compilador</strong>es <strong>–</strong> Princípios, Técnicas e<br />
Ferramentas. 1. ed. <strong>–</strong> Rio de Janeiro: LTC <strong>–</strong> Livros Técnicos e Científicos:1995.<br />
FARRER, Henry. BECKER, Cristiano Gonçalves. FARIA, Eduardo Chaves. MATOS,<br />
Helton Fábio de. SANTOS, Marcos Augusto. MAIA, Miriam Lourenço. Programação<br />
Estruturada de Computadores - Algoritmos Estruturados. 2. ed. <strong>–</strong> Rio de Janeiro:<br />
Editora Guanabara: 1989<br />
FRIEDL, Jeffrey E. F. Mastering Regular Expressions <strong>–</strong> Powerful Techniques for Perl<br />
and Other Tools. 7. ed. <strong>–</strong> Sebastopol, Califórnia, EEUU:O’Reilly Associates:1998.<br />
MENEZES, Paulo Blauth. Linguagens Formais e Autômatos. 4. ed. - Porto Alegre:<br />
Instituto de Informática da UFRGS:Editora Sagra Luzzatto:2001<br />
PRICE, Ana Maria de Alencar. TOSCANI, Simão Sirineo. Implementação de<br />
Linguagens de Programação: <strong>Compilador</strong>es. 1. ed. - Porto Alegre: Instituto de<br />
Informática da UFRGS:Editora Sagra Luzzatto:2000<br />
SEBESTA, Robert W. Conceitos de Linguagens de Programação. 4. ed. <strong>–</strong> Porto<br />
Alegre:Bookman:2000.<br />
WIRTH, Niklaus. Compiler Construction. 1. ed. <strong>–</strong> Essex, Inglaterra:Addison-<br />
Wesley:1996.<br />
50
SCANNER.H<br />
#ifndef ISCANNER<br />
#define ISCANNER<br />
#include "funcoes.h"<br />
// Tamanho do maior identificador<br />
#define IdLen 32<br />
// Número máximo de palavras chaves<br />
#define KW 50<br />
APÊNDICE A <strong>–</strong> CÓDIGO FONTE<br />
#define LISTA_DE_ACENTOS "áéíóúâêîôûäëïöüÿãõàèìòùñç"<br />
/*<br />
#define null 0<br />
#define times 1<br />
#define div 3<br />
#define mod 4<br />
#define and 5<br />
#define plus 6<br />
#define minus 7<br />
#define or 8<br />
#define eql 9<br />
#define neq 10<br />
#define lss 11<br />
#define geq 12<br />
#define leq 13<br />
#define gtr 14<br />
#define period 18<br />
#define comma 19<br />
#define colon 20<br />
#define rparen 22<br />
#define rbrak 23<br />
#define of 25<br />
#define then 26<br />
#define DO 27<br />
#define lparen 29<br />
#define lbrak 30<br />
#define not 32<br />
#define becomes 33<br />
#define number 34<br />
#define ident 37<br />
#define semicolon 38<br />
#define END 40<br />
#define ELSE 41<br />
#define ELSIF 42<br />
#define IF 44<br />
#define WHILE 46<br />
Comport <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
51
#define ARRAY 54<br />
#define RECORD 55<br />
#define CONST 57<br />
#define TYPE 58<br />
#define VAR 59<br />
#define PROCEDURE 60<br />
#define BEGIN 61<br />
#define MODULE 63<br />
#define eof 64<br />
#define TRUE 1<br />
#define FALSE 0<br />
*/<br />
#define MAXLONGINT 1000000<br />
#define NULO 0<br />
#define NUMERICO 1<br />
#define LITERAL 2<br />
#define LOGICO 3<br />
#define MATRIZ 4<br />
#define REGISTRO 5<br />
#define FIMREGISTRO 6<br />
#define DECLARE 7<br />
#define PROGRAMA 8<br />
#define FIMPROGRAMA 9<br />
#define SE 10<br />
#define FIMSE 11<br />
#define ENTAO 12<br />
#define SENAO 13<br />
#define FIMENTAO 14<br />
#define FIMSENAO 15<br />
#define CASO 16<br />
#define FIMCASO 17<br />
#define DEFINA 18<br />
#define FACA 20<br />
#define FIMFACA 21<br />
#define ENQUANTO 22<br />
#define FIMENQUANTO 23<br />
#define REPITA 24<br />
#define FIMREPITA 25<br />
#define INTERROMPA 26<br />
#define DE 27<br />
#define ATE 28<br />
#define PROCEDIMENTO 30<br />
#define FIMPROCEDIMENTO 31<br />
#define FUNCAO 32<br />
#define FIMFUNCAO 33<br />
#define MODULO 40<br />
#define FIMMODULO 41<br />
#define INTEIRO 50<br />
#define TAMANHO 51<br />
#define ORDEM 52<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
52
#define CARACTERE 53<br />
#define NUMERO 54<br />
#define LIT 55<br />
#define ATRIBUICAO 60<br />
#define MAIS 61<br />
#define MENOS 62<br />
#define DIVISAO 63<br />
#define MULTIPLICACAO 64<br />
#define RESTO 65<br />
#define NAO 70<br />
#define E 71<br />
#define OU 72<br />
#define IGUAL 80<br />
#define MAIOR 81<br />
#define MENOR 82<br />
#define MAIOR_IGUAL 83<br />
#define MENOR_IGUAL 84<br />
#define DIFERENTE 85<br />
#define VIRGULA 86<br />
#define PONTO 87<br />
#define DOIS_PONTOS 88<br />
#define VERDADEIRO 90<br />
#define FALSO 91<br />
#define PARENTESE_E 92<br />
#define PARENTESE_D 93<br />
#define CHAVE_E 94<br />
#define CHAVE_D 95<br />
#define IDENTIFICADOR 96<br />
#define ENUMERO 97<br />
#define NOVALINHA 100<br />
#define FDA 101<br />
#define TIPO 102<br />
#define VARIAVEL 103<br />
#define CONSTANTE 104<br />
#define LITERALVALOR 105<br />
#define NUMEROVALOR 106<br />
#define BOOLEANOVALOR 107<br />
#define COLCHETE_E 108<br />
#define COLCHETE_D 109<br />
typedef char Ident[IdLen];<br />
// Valores temporários<br />
extern long val;<br />
extern char sval[255];<br />
extern bool bval;<br />
extern Ident id;<br />
extern unsigned int error;<br />
extern char ch;<br />
extern int numerodeid;<br />
extern long errpos;<br />
extern long linha;<br />
extern long coluna;<br />
extern FILE *R;<br />
extern FILE *W;<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
53
Listas de tokens<br />
extern char comandos[MAX_ELEM_CJ];<br />
extern char fimdecomandos[MAX_ELEM_CJ];<br />
extern char cjfator[MAX_ELEM_CJ];<br />
void Mark (char *msg);<br />
void fIdent (int &sym);<br />
void Number (int &sym);<br />
//void comment (int &sym);<br />
void Get (int &sym);<br />
void EnterKW (int sym, char *name);<br />
void Init (long pos, FILE *C);<br />
void mainScanner (void);<br />
char leiaMinC(FILE *R);<br />
#endif<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
54
SCANNER.CPP<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
/*<br />
* Módulo OSS - Scanner Universidade do Amazonas Comport - <strong>Compilador</strong><br />
* <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
*<br />
* Baseado no compilador Oberon-0 de Niklaus Wirth<br />
*<br />
*/<br />
#define SCANNER<br />
#include <br />
#include <br />
#include <br />
#include <br />
#include "scanner.h"<br />
#include "funcoes.h"<br />
long val;<br />
char sval[255]={0};<br />
bool bval=false;<br />
// Identificador<br />
// id é usado para retornar o resultado da pesquisa de um identificador<br />
Ident id;<br />
// Código do erro<br />
unsigned int error;<br />
char ch;<br />
// Número de palavras chaves cadastradas<br />
// numerodeid e KW é o máximo<br />
int numerodeid;<br />
// Posição do erro<br />
long errpos;<br />
long linha=1;<br />
long coluna=1;<br />
// R é o arquivo fonte em <strong>Portugol</strong><br />
FILE *R;<br />
// W é o stdout, mas pode ser usada para redirecionar a saída se necessário<br />
FILE *W;<br />
// Estrutura que armazena as palavras-chaves já cadastradas,<br />
// Associando um código (sym) com o nome da palavra-chave (id)<br />
struct<br />
{<br />
int sym;<br />
char id[IdLen];<br />
}<br />
keyTab[KW]; // Vetor de palavras-chave<br />
55
char comandos[MAX_ELEM_CJ];<br />
char fimdecomandos[MAX_ELEM_CJ];<br />
char cjfator[MAX_ELEM_CJ];<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
// Função usada para ler um caracter e converte-lo para minuscula<br />
char leiaMinC(FILE *R)<br />
{<br />
return minusculaC(fgetc(R));<br />
}<br />
// Função usada para imprimir mensagens de erro<br />
void<br />
Mark (char *msg)<br />
{<br />
long p;<br />
p = ftell (R);<br />
if (p > errpos)<br />
{<br />
fprintf (W, " Linha: %d Coluna: %d Posição %d %s\n", linha, pcoluna+1,<br />
p, msg);<br />
}<br />
errpos = p;<br />
error = VERDADEIRO;<br />
}<br />
// Função usada para ler e localizar um identificador<br />
void<br />
fIdent (int &sym)<br />
{<br />
int i = 0, k;<br />
do<br />
{<br />
if (i < IdLen)<br />
{<br />
id[i] = ch;<br />
i++;<br />
}<br />
ch = minusculaC(fgetc (R));<br />
}<br />
while ((ch >= '0' && ch = 'a' && ch
}<br />
sym = ENUMERO;<br />
do<br />
{<br />
if (val = '0' && ch
}<br />
do<br />
{<br />
while (ch == '{')<br />
{<br />
ch = fgetc (R);<br />
if (ch == '*')<br />
Comentario (sym);<br />
}<br />
if (ch == '*')<br />
{<br />
ch = fgetc (R);<br />
break;<br />
}<br />
if (feof (R))<br />
break;<br />
ch = fgetc (R);<br />
}<br />
while (1);<br />
if (ch == ')')<br />
{<br />
ch = fgetc (R);<br />
break;<br />
}<br />
if (feof (R))<br />
{<br />
Mark ("Comentário não terminado");<br />
break;<br />
}<br />
}<br />
while (1);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
// Função mais importante do parser. Usada para caminhar na árvore léxica<br />
// Sempre é chamada para identificar o tipo do próximo sym.<br />
void<br />
Get (int &sym)<br />
{<br />
// Ignora espaços e caracteres de controle<br />
while (!feof (R) && ch
case '-':<br />
ch = fgetc (R);<br />
sym = MENOS;<br />
break;<br />
case '=':<br />
ch = fgetc (R);<br />
sym = IGUAL;<br />
break;<br />
// case '#':<br />
// ch = fgetc (R);<br />
// sym = ;<br />
// break;<br />
case '')<br />
{<br />
ch=leiaMinC(R);<br />
sym = DIFERENTE;<br />
}<br />
else<br />
{<br />
sym = MENOR;<br />
}<br />
break;<br />
case '>':<br />
ch = fgetc (R);<br />
if (ch == '=')<br />
{<br />
ch = fgetc (R);<br />
sym = MAIOR_IGUAL;<br />
}<br />
else<br />
{<br />
sym = MAIOR;<br />
}<br />
break;<br />
case 10: // LF<br />
case 13: // NL<br />
do<br />
{<br />
ch=leiaMinC(R);<br />
} while (ch==13 || ch==10);<br />
sym = NOVALINHA;<br />
linha++;<br />
coluna=ftell(R);<br />
break;<br />
case ',':<br />
ch = fgetc (R);<br />
sym = VIRGULA;<br />
break;<br />
case '"':<br />
Literal(sym);<br />
break;<br />
case ':':<br />
ch = fgetc (R);<br />
if (ch == '=')<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
59
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
{<br />
ch = fgetc (R);<br />
sym = ATRIBUICAO;<br />
}<br />
else<br />
{<br />
sym = DOIS_PONTOS;<br />
}<br />
break;<br />
case '.':<br />
ch = fgetc (R);<br />
sym = PONTO;<br />
break;<br />
//NILO: Ver o caso do comentário // e #<br />
case '(':<br />
ch = fgetc (R);<br />
if (ch == '*')<br />
{<br />
Comentario (sym);<br />
Get (sym);<br />
}<br />
else<br />
sym = PARENTESE_E;<br />
break;<br />
case ')':<br />
ch = fgetc (R);<br />
sym = PARENTESE_D;<br />
break;<br />
//NILO: Mudar de chave para colchete<br />
case '[':<br />
ch = fgetc (R);<br />
sym = COLCHETE_E;<br />
break;<br />
case ']':<br />
ch = fgetc (R);<br />
sym = COLCHETE_D;<br />
break;<br />
// case '~':<br />
// ch = fgetc (R);<br />
// sym = not;<br />
// break;<br />
default:<br />
if ((ch >= 'A' && ch = 'a' && ch = '0' && ch
{<br />
}<br />
error = FALSO;<br />
errpos = pos;<br />
R = C;<br />
ch = fgetc (R);<br />
void<br />
EnterKW (int sym, char *name)<br />
{<br />
keyTab[numerodeid].sym = sym;<br />
strcpy (keyTab[numerodeid].id, name);<br />
numerodeid++;<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
// Para testar o cadastro de identificadores, defina SPRINCIPAL.<br />
// Isso fará com que a mainScanner se torne a main<br />
#ifndef SPRINCIPAL<br />
void mainScanner(void)<br />
#else<br />
int main (int argc, char **argv)<br />
#endif<br />
{<br />
W = stdout;<br />
error = VERDADEIRO;<br />
numerodeid = 0; // Inicializa o índice de palavras-chave<br />
EnterKW( NUMERICO, "numérico"); // 1<br />
EnterKW( LITERAL, "literal"); // 2<br />
EnterKW( LOGICO, "lógico"); // 3<br />
EnterKW( MATRIZ, "matriz"); // 4<br />
EnterKW( REGISTRO, "registro"); // 5<br />
EnterKW( FIMREGISTRO, "fimregistro"); // 6<br />
EnterKW( DECLARE, "declare"); // 7<br />
EnterKW( PROGRAMA, "programa"); // 8<br />
EnterKW( FIMPROGRAMA, "fimprograma"); // 9<br />
EnterKW( SE, "se"); // 10<br />
EnterKW( FIMSE, "fimse"); // 11<br />
EnterKW( ENTAO, "então"); // 12<br />
EnterKW( SENAO, "senão"); // 13<br />
EnterKW( FIMENTAO, "fimentão"); // 14<br />
EnterKW( FIMSENAO, "fimsenão"); // 15<br />
EnterKW( CASO, "caso"); // 16<br />
EnterKW( FIMCASO, "fimcaso"); // 17<br />
EnterKW( FACA, "faça"); // 20<br />
EnterKW( FIMFACA, "fimfaça"); // 21<br />
EnterKW( ENQUANTO, "enquanto"); // 22<br />
EnterKW( FIMENQUANTO, "fimenquanto"); // 23<br />
EnterKW( REPITA, "repita"); // 24<br />
EnterKW( FIMREPITA, "fimrepita"); // 25<br />
EnterKW( INTERROMPA, "interrompa"); // 26<br />
EnterKW( DE, "de"); // 27<br />
EnterKW( ATE, "ate"); // 28<br />
EnterKW( PROCEDIMENTO,"procedimento");// 30<br />
EnterKW( FIMPROCEDIMENTO, "fimprocedimento"); // 31<br />
61
EnterKW( FUNCAO, "função"); // 32<br />
EnterKW( FIMFUNCAO, "fimfunção"); // 33<br />
EnterKW( MODULO, "módulo"); // 40<br />
EnterKW( FIMMODULO, "fimmódulo"); // 41<br />
EnterKW( INTEIRO, "inteiro"); // 50<br />
EnterKW( TAMANHO, "tamanho"); // 51<br />
EnterKW( ORDEM, "ordem"); // 52<br />
EnterKW( CARACTERE, "caractere"); // 53<br />
EnterKW( NUMERO, "número"); // 54<br />
EnterKW( LIT, "lit"); // 55<br />
// EnterKW( ATRIBUICAO 60<br />
// EnterKW( MAIS 61<br />
// EnterKW( MENOS 62<br />
// EnterKW( DIVISAO 63<br />
// EnterKW( MULTIPLICACAO 64<br />
EnterKW( NAO, "não"); // 70<br />
EnterKW( E, "e"); // 71<br />
EnterKW( OU, "ou"); // 72<br />
// EnterKW( IGUAL, ""); 80<br />
// EnterKW( MAIOR, ""); 81<br />
// EnterKW( MENOR, ""); 82<br />
// EnterKW( MAIOR_IGUAL, ""); 83<br />
// EnterKW( MENOR_IGUAL, ""); 84<br />
// EnterKW( DIFERENTE, ""); 85<br />
EnterKW( VERDADEIRO, "verdadeiro"); // 90<br />
EnterKW( FALSO, "falso"); // 91<br />
// EnterKW( NOVALINHA, "\n"); // 100<br />
// Conjuntos<br />
// Conjunto de Comandos (Statements)<br />
CriaConjunto(comandos);<br />
AdicionaConjunto(comandos, SE);<br />
AdicionaConjunto(comandos, FIMSE);<br />
AdicionaConjunto(comandos, ENTAO);<br />
AdicionaConjunto(comandos, FIMENTAO);<br />
AdicionaConjunto(comandos, SENAO);<br />
AdicionaConjunto(comandos, FIMSENAO);<br />
AdicionaConjunto(comandos, ENQUANTO);<br />
AdicionaConjunto(comandos, REPITA);<br />
AdicionaConjunto(comandos, FIMREPITA);<br />
AdicionaConjunto(comandos, FACA);<br />
AdicionaConjunto(comandos, FIMFACA);<br />
AdicionaConjunto(comandos, CASO);<br />
AdicionaConjunto(comandos, FIMCASO);<br />
AdicionaConjunto(comandos, MATRIZ);<br />
AdicionaConjunto(comandos, REGISTRO);<br />
AdicionaConjunto(comandos, FIMREGISTRO);<br />
AdicionaConjunto(comandos, DECLARE);<br />
AdicionaConjunto(comandos, FIMPROGRAMA);<br />
AdicionaConjunto(comandos, PROGRAMA);<br />
AdicionaConjunto(comandos, MODULO);<br />
AdicionaConjunto(comandos, FIMMODULO);<br />
AdicionaConjunto(comandos, PROCEDIMENTO);<br />
AdicionaConjunto(comandos, FIMPROCEDIMENTO);<br />
AdicionaConjunto(comandos, FUNCAO);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
62
AdicionaConjunto(comandos, FIMFUNCAO);<br />
AdicionaConjunto(comandos, FDA);<br />
CriaConjunto(fimdecomandos);<br />
AdicionaConjunto(fimdecomandos, FIMSE);<br />
AdicionaConjunto(fimdecomandos, FIMENTAO);<br />
AdicionaConjunto(fimdecomandos, FIMSENAO);<br />
AdicionaConjunto(fimdecomandos, FIMREPITA);<br />
AdicionaConjunto(fimdecomandos, FIMFACA);<br />
AdicionaConjunto(fimdecomandos, FIMCASO);<br />
AdicionaConjunto(fimdecomandos, MATRIZ);<br />
AdicionaConjunto(fimdecomandos, REGISTRO);<br />
AdicionaConjunto(fimdecomandos, FIMREGISTRO);<br />
AdicionaConjunto(fimdecomandos, DECLARE);<br />
AdicionaConjunto(fimdecomandos, FIMPROGRAMA);<br />
AdicionaConjunto(fimdecomandos, PROGRAMA);<br />
AdicionaConjunto(fimdecomandos, MODULO);<br />
AdicionaConjunto(fimdecomandos, FIMMODULO);<br />
AdicionaConjunto(fimdecomandos, PROCEDIMENTO);<br />
AdicionaConjunto(fimdecomandos, FIMPROCEDIMENTO);<br />
AdicionaConjunto(fimdecomandos, FUNCAO);<br />
AdicionaConjunto(fimdecomandos, FIMFUNCAO);<br />
AdicionaConjunto(fimdecomandos, FDA);<br />
CriaConjunto(cjfator);<br />
AdicionaConjunto(cjfator,NULO);<br />
AdicionaConjunto(cjfator,MULTIPLICACAO);<br />
AdicionaConjunto(cjfator,DIVISAO);<br />
AdicionaConjunto(cjfator,E);<br />
AdicionaConjunto(cjfator,MAIS);<br />
AdicionaConjunto(cjfator,MENOS);<br />
AdicionaConjunto(cjfator,OU);<br />
AdicionaConjunto(cjfator,IGUAL);<br />
AdicionaConjunto(cjfator,DIFERENTE);<br />
AdicionaConjunto(cjfator,MENOR);<br />
AdicionaConjunto(cjfator,MAIOR_IGUAL);<br />
AdicionaConjunto(cjfator,MENOR_IGUAL);<br />
AdicionaConjunto(cjfator,MAIOR);<br />
AdicionaConjunto(cjfator,VIRGULA);<br />
AdicionaConjunto(cjfator,DOIS_PONTOS);<br />
AdicionaConjunto(cjfator,PARENTESE_D);<br />
AdicionaConjunto(cjfator,CHAVE_D);<br />
AdicionaConjunto(cjfator,COLCHETE_D);<br />
AdicionaConjunto(cjfator,ENTAO);<br />
#ifdef SPRINCIPAL<br />
Init(0);<br />
if(argc==2)<br />
R=fopen(argv[1],"r");<br />
ch=leiaMinC(R);<br />
int i;<br />
for(i=0;i
eturn(0);<br />
#endif<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
64
PARSER.H<br />
#ifndef IPARSER<br />
#define IPARSER<br />
#include <br />
#include <br />
#include <br />
#include "scanner.h"<br />
#include "codegenerator.h"<br />
#include "risc.h"<br />
#include "funcoes.h"<br />
#define WordSize 4<br />
#ifndef PARSER<br />
extern int sym;<br />
extern int loaded;<br />
extern Object topScope;<br />
extern Object universe;<br />
extern Object guard;<br />
#endif<br />
#define VERSAO "0.92"<br />
void NewObj (Object & obj, int Class);<br />
void find (Object & obj);<br />
void FindField (Object & obj, Object list);<br />
int IsParam (Object obj);<br />
void OpenScope (void);<br />
void CloseScope (void);<br />
void selector (Item & x);<br />
void factor (Item & x);<br />
void term (Item & x);<br />
void SimpleExpression (Item & x);<br />
void expression (Item & x);<br />
void parameter (Object & fp);<br />
void param (Item & x);<br />
void StatSequence (void);<br />
void IdentList (int Class, Object & first);<br />
void fType (Type & type);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
65
void declarations (long varsize);<br />
void FPSection (long &parblksize);<br />
void ProcedureDecl (void);<br />
void Module (FILE * S);<br />
void Compile (FILE *C);<br />
void enter (int cl, long n, Ident name, Type type);<br />
void mainParser (void);<br />
#endif<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
66
PARSER.CPP<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
/*<br />
* Módulo OSP - Parser Universidade do Amazonas Comport - <strong>Compilador</strong><br />
* <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
*<br />
* Baseado no compilador Oberon-0 de Niklaus Wirth<br />
*<br />
*/<br />
#include <br />
#include <br />
#include <br />
#define PARSER<br />
#include "parser.h"<br />
#include "codegenerator.h"<br />
int sym, loaded;<br />
Object topScope, universe, guard;<br />
void<br />
NewObj (Object & obj, int Class)<br />
{<br />
Object nova, x;<br />
x = topScope;<br />
strcpy(guard->name, id);<br />
while (strcmp(x->next->name, id)!=0)<br />
x = x->next;<br />
if (x->next==guard)<br />
{<br />
nova = new ObjDesc;<br />
strcpy(nova->name, id);<br />
nova->Class = Class;<br />
nova->next = guard;<br />
x->next = nova;<br />
obj = nova;<br />
}<br />
else<br />
{<br />
obj = x->next;<br />
Mark ("Definição múltipla !");<br />
}<br />
}<br />
void<br />
find (Object & obj)<br />
{<br />
Object s, x;<br />
s = topScope;<br />
strcpy(guard->name, id);<br />
do<br />
{<br />
x = s->next;<br />
while (!strcmp (x->name, id))<br />
67
}<br />
x = x->next;<br />
if (x != guard)<br />
{<br />
obj = x;<br />
break;<br />
}<br />
if (s == universe)<br />
{<br />
obj = x;<br />
Mark ("Não definido");<br />
break;<br />
}<br />
s = s->dsc;<br />
}<br />
while (1);<br />
//NILO: Verificar se não há problema caso não encontre<br />
void<br />
FindField (Object & obj, Object list)<br />
{<br />
strcpy(guard->name,id);<br />
while (!strcmp (list->name, id))<br />
list = list->next;<br />
obj = list;<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
int<br />
IsParam (Object obj)<br />
{<br />
return (obj->Class == Par || obj->Class == Var && obj->val > 0);<br />
}<br />
void<br />
OpenScope (void)<br />
{<br />
Object s;<br />
s = new ObjDesc;<br />
s->Class = Head;<br />
s->dsc = topScope;<br />
s->next = guard;<br />
topScope = s;<br />
}<br />
void<br />
CloseScope (void)<br />
{<br />
topScope = topScope->dsc;<br />
}<br />
void<br />
selector (Item & x)<br />
{<br />
Item y;<br />
Object obj;<br />
while (sym == COLCHETE_E || sym == PONTO)<br />
{<br />
switch(sym)<br />
{<br />
case COLCHETE_E:<br />
68
}<br />
}<br />
}<br />
Get (sym);<br />
expression (y);<br />
if (x.type->form == MATRIZ)<br />
{<br />
Index (x, y);<br />
}<br />
else<br />
{<br />
Mark ("Não é uma matriz");<br />
}<br />
if (sym == COLCHETE_D)<br />
{<br />
Get (sym);<br />
}<br />
else<br />
Mark ("Falta ]?");<br />
break;<br />
case PONTO:<br />
Get (sym);<br />
if (sym == IDENTIFICADOR)<br />
{<br />
if (x.type->form == REGISTRO)<br />
{<br />
FindField (obj, x.type->fields);<br />
Get (sym);<br />
if (obj != guard)<br />
Field (x, obj);<br />
else<br />
Mark ("Não definido");<br />
}<br />
else<br />
Mark ("Não é um registro");<br />
}<br />
break;<br />
default:<br />
Mark ("IDENTIFICADOR?");<br />
//NILO: Verificar a equivalencia de Simbolos<br />
void<br />
factor (Item & x)<br />
{<br />
Object obj;<br />
if (PertenceConjunto(cjfator, sym))<br />
{<br />
Mark ("IDENTIFICADOR?");<br />
do<br />
{<br />
Get (sym);<br />
} while (PertenceConjunto(cjfator, sym));<br />
}<br />
switch(sym)<br />
{<br />
case IDENTIFICADOR:<br />
find (obj);<br />
Get (sym);<br />
MakeItem (x, obj);<br />
selector (x);<br />
break;<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
69
}<br />
}<br />
case ENUMERO:<br />
MakeConstItem (x, intType, val);<br />
Get (sym);<br />
break;<br />
case PARENTESE_E:<br />
Get (sym);<br />
expression (x);<br />
if (sym == PARENTESE_D)<br />
Get (sym);<br />
else<br />
Mark (")?");<br />
break;<br />
case COLCHETE_E:<br />
Get (sym);<br />
expression (x);<br />
if (sym == COLCHETE_D)<br />
Get (sym);<br />
else<br />
Mark ("]?");<br />
break;<br />
case NAO:<br />
Get (sym);<br />
factor (x);<br />
Op1 (NAO, x);<br />
break;<br />
default:<br />
Mark ("factor?");<br />
MakeItem (x, guard);<br />
void<br />
term (Item & x)<br />
{<br />
Item y;<br />
int op;<br />
factor (x);<br />
// Modulo retirado, pois não é definido em portugol<br />
while (sym == MULTIPLICACAO || sym==DIVISAO || sym == E)<br />
{<br />
op = sym;<br />
Get (sym);<br />
if (op == E)<br />
Op1 (op, x);<br />
factor (y);<br />
Op2 (op, x, y);<br />
}<br />
}<br />
void<br />
SimpleExpression (Item & x)<br />
{<br />
Item y;<br />
int op;<br />
switch(sym)<br />
{<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
70
}<br />
case MAIS:<br />
Get (sym);<br />
term (x);<br />
break;<br />
case MENOS:<br />
Get (sym);<br />
term (x);<br />
Op1 (MENOS, x);<br />
break;<br />
default:<br />
term (x);<br />
}<br />
while (sym == MAIS || sym==MENOS || sym == OU)<br />
{<br />
op = sym;<br />
Get (sym);<br />
if (op == OU)<br />
{<br />
Op1 (op, x);<br />
}<br />
term (y);<br />
Op2 (op, x, y);<br />
}<br />
//NILO: Verificar a equivalencia de Simbolos<br />
void<br />
expression (Item & x)<br />
{<br />
Item y;<br />
int op;<br />
SimpleExpression (x);<br />
}<br />
if (sym == IGUAL || sym == MAIOR || sym == MENOR<br />
|| sym == MAIOR_IGUAL || sym == MENOR_IGUAL<br />
|| sym == DIFERENTE)<br />
{<br />
op = sym;<br />
Get (sym);<br />
SimpleExpression (y);<br />
Relation (op, x, y);<br />
}<br />
void<br />
parameter (Object & fp)<br />
{<br />
Item x;<br />
expression (x);<br />
if (IsParam (fp))<br />
{<br />
Parameter (x, fp->type, fp->Class);<br />
fp = fp->next;<br />
}<br />
else<br />
Mark ("Parâmetros demais");<br />
}<br />
void<br />
param (Item & x)<br />
{<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
71
if (sym == PARENTESE_E)<br />
Get (sym);<br />
else<br />
Mark ("(?");<br />
expression (x);<br />
if (sym == PARENTESE_D)<br />
Get (sym);<br />
else<br />
Mark (")?");<br />
}<br />
//NILO: Verificar a equivalencia de Simbolos<br />
void<br />
StatSequence (void)<br />
{<br />
Object par, obj;<br />
Item x, y;<br />
long L;<br />
do<br />
{<br />
obj = guard;<br />
if (!PertenceConjunto(comandos, sym))<br />
{<br />
Mark ("Comando?");<br />
do<br />
{<br />
Get (sym);<br />
}<br />
while (!PertenceConjunto(comandos,sym));<br />
}<br />
switch(sym)<br />
{<br />
case IDENTIFICADOR:<br />
find (obj);<br />
Get (sym);<br />
MakeItem (x, obj);<br />
selector (x);<br />
switch(sym)<br />
{<br />
case ATRIBUICAO:<br />
Get (sym);<br />
expression (y);<br />
Store (x, y);<br />
break;<br />
case IGUAL:<br />
Mark (":= ?");<br />
Get (sym);<br />
expression (y);<br />
break;<br />
default:<br />
if (x.mode == Proc)<br />
{<br />
par = obj->dsc;<br />
if (sym == PARENTESE_E)<br />
{<br />
Get (sym);<br />
if (sym == PARENTESE_D)<br />
Get (sym);<br />
else<br />
{<br />
do<br />
{<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
72
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
parameter (par);<br />
if (sym == VIRGULA)<br />
Get (sym);<br />
else<br />
{<br />
if (sym == PARENTESE_D)<br />
{<br />
Get (sym);<br />
break;<br />
}<br />
else<br />
{<br />
if (sym == NOVALINHA)<br />
break;<br />
else<br />
Mark (") or , ?");<br />
}<br />
}<br />
} while (1);<br />
}<br />
if (obj->val < 0)<br />
Mark ("forward call");<br />
else if (!IsParam (par))<br />
Call (x);<br />
else<br />
Mark ("Poucos parâmetros");<br />
}<br />
else if (x.mode == SProc)<br />
{<br />
if (obj->val Class == Typ)<br />
Mark ("Atribuição ilegal?");<br />
else<br />
Mark ("Comando?");<br />
}<br />
break;<br />
case SE:<br />
Get (sym);<br />
expression (x);<br />
CJump (x);<br />
if (sym == ENTAO)<br />
Get (sym);<br />
else<br />
Mark ("então?");<br />
StatSequence ();<br />
L = 0L;<br />
while (sym == SENAO)<br />
{<br />
Get (sym);<br />
FJump (L);<br />
FixLink (x.a);<br />
expression (x);<br />
CJump (x);<br />
if (sym == ENTAO)<br />
Get (sym);<br />
else<br />
Mark ("Então?");<br />
73
}<br />
StatSequence ();<br />
}<br />
if (sym == SENAO)<br />
{<br />
Get (sym);<br />
FJump (L);<br />
FixLink (x.a);<br />
StatSequence ();<br />
}<br />
else<br />
FixLink (x.a);<br />
FixLink (L);<br />
if (sym == FIMSE)<br />
Get (sym);<br />
else<br />
Mark ("Fimse?");<br />
break;<br />
case ENQUANTO:<br />
Get (sym);<br />
L = pc;<br />
expression (x);<br />
CJump (x);<br />
// if (sym == DO)<br />
// Get (sym);<br />
// else<br />
// Mark ("DO?");<br />
StatSequence ();<br />
BJump (L);<br />
FixLink (x.a);<br />
if (sym == FIMENQUANTO)<br />
Get (sym);<br />
else<br />
Mark ("fimenquanto?");<br />
break;<br />
}<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else if (PertenceConjunto(fimdecomandos, sym))<br />
break;<br />
else<br />
Mark ("Fim de linha ?");<br />
} while (1);<br />
void<br />
IdentList (int Class, Object & first)<br />
{<br />
Object obj;<br />
if (sym == IDENTIFICADOR)<br />
{<br />
NewObj (first, Class);<br />
Get (sym);<br />
while (sym == VIRGULA)<br />
{<br />
Get (sym);<br />
if (sym == IDENTIFICADOR)<br />
{<br />
NewObj (obj, Class);<br />
Get (sym);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
74
}<br />
}<br />
else<br />
Mark ("IDENTIFICADOR?");<br />
//NILO: Aqui vem o tipo da variável<br />
// if (sym == DOIS_PONTOS)<br />
// Get (sym);<br />
// else<br />
// Mark (":?");<br />
}<br />
}<br />
void<br />
fType (Type & type)<br />
{<br />
Object obj, first;<br />
Item x;<br />
Type tp;<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
if (sym != IDENTIFICADOR && sym != MATRIZ && sym != REGISTRO &&<br />
sym != NUMERICO && sym !=LITERAL && sym !=LOGICO)<br />
{<br />
Mark ("Tipo ?");<br />
do<br />
{<br />
Get (sym);<br />
}<br />
while (sym != IDENTIFICADOR && sym !=NOVALINHA);<br />
}<br />
switch (sym) {<br />
case LITERAL:<br />
type = litType;<br />
Get(sym);<br />
break;<br />
case NUMERICO:<br />
type = intType;<br />
Get(sym);<br />
break;<br />
case LOGICO:<br />
type = boolType;<br />
Get(sym);<br />
break;<br />
case IDENTIFICADOR: // Tipo definido pelo usuário<br />
find (obj);<br />
Get (sym);<br />
if (obj->Class == Typ)<br />
type = obj->type;<br />
else<br />
Mark ("Tipo ?");<br />
break;<br />
case MATRIZ:<br />
Get (sym);<br />
expression (x);<br />
if (x.mode != Const || x.a < 0)<br />
Mark ("Índice inválido");<br />
// if (sym == of)<br />
// Get (sym);<br />
// else<br />
// Mark ("OF?");<br />
tp = new TypeDesc;<br />
type->form = MATRIZ;<br />
75
}<br />
type->base = tp;<br />
type->len = SHORT (x.a);<br />
type->size = type->len * tp->size;<br />
break;<br />
case REGISTRO:<br />
Get (sym);<br />
type = new TypeDesc;<br />
type->form = REGISTRO;<br />
type->size = 0;<br />
OpenScope ();<br />
do<br />
{<br />
if (sym == IDENTIFICADOR)<br />
{<br />
IdentList (Fld, first);<br />
fType (tp);<br />
obj = first;<br />
while (obj != guard)<br />
{<br />
obj->type = tp;<br />
obj->val = type->size;<br />
type->size += (obj->type->size);<br />
obj = obj->next;<br />
}<br />
}<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else if (sym == IDENTIFICADOR)<br />
Mark (" ?");<br />
else break;<br />
} while (1);<br />
type->fields = topScope->next;<br />
CloseScope ();<br />
if (sym == FIMREGISTRO)<br />
Get (sym);<br />
else<br />
Mark ("fimregistro ?");<br />
break;<br />
default:<br />
Mark ("Identificador ?");<br />
}<br />
int EInicioDeDeclaracaoDefinicaoOuFim(int s)<br />
{<br />
switch(s)<br />
{<br />
case PROCEDIMENTO:<br />
case FUNCAO:<br />
case FIMPROGRAMA:<br />
case FIMMODULO:<br />
case FDA:<br />
case DECLARE:<br />
case DEFINA:<br />
return(VERDADEIRO);<br />
}<br />
return(FALSO);<br />
}<br />
//NILO: Verificar a equivalencia de Simbolos<br />
void<br />
declarations (long varsize)<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
76
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
{<br />
Object obj, first;<br />
Item x;<br />
Type tp;<br />
long L;<br />
if (sym != DECLARE && sym != DEFINA)<br />
{<br />
Mark ("declaração?");<br />
do // Pula o código até a próxima declaração de bloco<br />
{<br />
Get (sym);<br />
}<br />
while (EInicioDeDeclaracaoDefinicaoOuFim(sym));<br />
}<br />
do<br />
{<br />
switch (sym) {<br />
case DEFINA:<br />
{<br />
Get (sym);<br />
while (sym == IDENTIFICADOR)<br />
{<br />
NewObj (obj, Const);<br />
Get (sym);<br />
if (sym == IGUAL)<br />
Get (sym);<br />
else<br />
Mark ("= ?");<br />
expression (x);<br />
fprintf(stderr, "Constante %s definida como %d", id, x.a);<br />
if (x.mode == Const)<br />
{<br />
obj->val = x.a;<br />
obj->type = x.type;<br />
}<br />
else<br />
Mark ("A expressão não é uma constante!");<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark ("?");<br />
}<br />
break;<br />
}<br />
/* TODO: não há no portugol sintaxe para declaração de tipo */<br />
case TIPO:<br />
{<br />
Get (sym);<br />
while (sym == IDENTIFICADOR)<br />
{<br />
NewObj (obj, Typ);<br />
Get (sym);<br />
if (sym == IGUAL)<br />
Get (sym);<br />
else<br />
Mark ("=?");<br />
fType (obj->type);<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark ("?");<br />
77
lista<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
}<br />
break;<br />
}<br />
case DECLARE:<br />
{<br />
Get (sym);<br />
while (sym == IDENTIFICADOR)<br />
{<br />
IdentList (Var, first);<br />
fType (tp);<br />
//atualiza a informação de tipo do primeiro ao ultimo da<br />
obj = first;<br />
while (obj != guard)<br />
{<br />
obj->type = tp;<br />
obj->lev = curlev;<br />
varsize = varsize + obj->type->size;<br />
obj->val = -varsize;<br />
fprintf(stderr, "Variável %s criada sendo do tipo %s\n",<br />
obj->name , id);<br />
obj = obj->next;<br />
}<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark (" ?");<br />
}<br />
break;<br />
}<br />
}<br />
}<br />
while (sym == DECLARE || sym == DEFINA);<br />
}<br />
void<br />
FPSection (long &parblksize)<br />
{<br />
Object obj, first;<br />
Type tp;<br />
long parsize;<br />
if (sym == VARIAVEL)<br />
{<br />
Get (sym);<br />
IdentList (Par, first);<br />
}<br />
else<br />
IdentList (VARIAVEL, first);<br />
if (sym == IDENTIFICADOR)<br />
{<br />
find (obj);<br />
Get (sym);<br />
if (obj->Class == Typ)<br />
tp = obj->type;<br />
else<br />
{<br />
Mark ("type?");<br />
tp = intType;<br />
}<br />
}<br />
else<br />
78
}<br />
{<br />
Mark ("IDENTIFICADOR?");<br />
tp = intType;<br />
}<br />
if (first->Class == VARIAVEL)<br />
{<br />
parsize = tp->size;<br />
if (tp->form >= MATRIZ)<br />
Mark ("no struct params");<br />
}<br />
else<br />
parsize = WordSize;<br />
obj = first;<br />
while (obj != guard)<br />
{<br />
obj->type = tp;<br />
parblksize += parsize;<br />
obj = obj->next;<br />
}<br />
void<br />
ProcedureDecl (void)<br />
{<br />
const int marksize = 8;<br />
Object proc, obj;<br />
Ident procid;<br />
long locblksize, parblksize;<br />
Get (sym);<br />
if (sym == IDENTIFICADOR)<br />
{<br />
strcpy(procid,id);<br />
NewObj (proc, Proc);<br />
Get (sym);<br />
parblksize = marksize;<br />
IncLevel (1);<br />
OpenScope ();<br />
proc->val = -1;<br />
if (sym == PARENTESE_E)<br />
{<br />
Get (sym);<br />
if (sym == PARENTESE_D)<br />
Get (sym);<br />
else<br />
{<br />
FPSection (parblksize);<br />
while (sym == NOVALINHA)<br />
{<br />
Get (sym);<br />
FPSection (parblksize);<br />
}<br />
if (sym == PARENTESE_D)<br />
Get (sym);<br />
else<br />
Mark (")?");<br />
}<br />
}<br />
else if (curlev == 1)<br />
EnterCmd (procid);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
79
obj = topScope->next;<br />
locblksize = parblksize;<br />
while (obj != guard)<br />
{<br />
obj->lev = curlev;<br />
if (obj->Class == Par)<br />
locblksize -= WordSize;<br />
else<br />
locblksize -= obj->type->size;<br />
obj->val = locblksize;<br />
obj = obj->next;<br />
}<br />
proc->dsc = topScope->next;<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark ("?");<br />
locblksize = 0;<br />
declarations (locblksize);<br />
while (sym == PROCEDIMENTO)<br />
{<br />
ProcedureDecl ();<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark ("?");<br />
}<br />
proc->val = pc;<br />
Enter (locblksize);<br />
// if (sym == BEGIN)<br />
// {<br />
Get (sym);<br />
StatSequence ();<br />
// }<br />
if (sym == FIMPROCEDIMENTO)<br />
Get (sym);<br />
else<br />
Mark ("fimprocedimento?");<br />
if (sym == IDENTIFICADOR)<br />
{<br />
if (procid != id)<br />
Mark ("no match");<br />
Get (sym);<br />
}<br />
Return (parblksize - marksize);<br />
CloseScope ();<br />
IncLevel (-1);<br />
}<br />
}<br />
void<br />
Module (FILE * S)<br />
{<br />
Ident modid;<br />
long varsize;<br />
fprintf (W, " compilando: ");<br />
if (sym == MODULO)<br />
{<br />
Get (sym);<br />
Open ();<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
80
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
OpenScope ();<br />
varsize = 0;<br />
if (sym == IDENTIFICADOR)<br />
{<br />
strcpy(modid, id);<br />
Get (sym);<br />
fprintf (W, "%s\n", modid);<br />
}<br />
else<br />
Mark ("IDENTIFICADOR?");<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark ("?");<br />
if(sym==DECLARE || sym ==DEFINA)<br />
declarations (varsize);<br />
while (sym == PROCEDIMENTO)<br />
{<br />
ProcedureDecl ();<br />
if (sym == NOVALINHA)<br />
Get (sym);<br />
else<br />
Mark ("?");<br />
}<br />
Header (varsize);<br />
// if (sym == BEGIN)<br />
// {<br />
// Get (sym);<br />
StatSequence ();<br />
// }<br />
if (sym == FIMMODULO)<br />
Get (sym);<br />
else<br />
Mark ("fimmódulo?");<br />
if (sym == IDENTIFICADOR)<br />
{<br />
if (modid != id)<br />
Mark ("Nome do módulo diferente do declarado");<br />
Get (sym);<br />
}<br />
else<br />
Mark ("Nome do módulo ?");<br />
if (sym != PONTO)<br />
Mark (". ?");<br />
CloseScope ();<br />
if (!error)<br />
{<br />
/* TODO: Vericar este item no código original do Wirth */<br />
/*<br />
IF ~OSS.error THEN<br />
COPY(modid, S.s); OSG.Close(S, varsize); Texts.WriteString(W, "code<br />
generated");<br />
Texts.WriteInt(W, OSG.pc, 6); Texts.WriteLn(W);<br />
Texts.Append(Oberon.Log, W.buf)<br />
END<br />
*/<br />
}<br />
fscanf (S, "%s", modid);<br />
Close (S, varsize);<br />
fprintf (W, "code generated%6d\n", pc);<br />
81
}<br />
}<br />
else<br />
Mark ("módulo?");<br />
void<br />
Compile (FILE *C)<br />
{<br />
long beg, end, time;<br />
FILE *S;<br />
loaded = FALSO;<br />
S = C;<br />
Init (0,C);<br />
Get (sym);<br />
Module (S);<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
/* TODO: Ver o que fazem estas funções: Decode, Load e Exec */<br />
/*<br />
*<br />
*<br />
* PROCEDURE Decode*; VAR V: MenuViewers.Viewer; T: Texts.Text; X, Y:<br />
* INTEGER; BEGIN T := TextFrames.Text("");<br />
* Oberon.AllocateSystemViewer(Oberon.Par.frame.X, X, Y); V :=<br />
* MenuViewers.New( TextFrames.NewMenu("Log.Text", "System.Close<br />
* System.Copy System.Grow Edit.Search Edit.Store"), TextFrames.NewText(T,<br />
* 0), TextFrames.menuH, X, Y); OSG.Decode(T) END Decode;<br />
*<br />
* PROCEDURE Load*; VAR S: Texts.Scanner; BEGIN IF ~OSS.error & ~loaded<br />
* THEN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);<br />
* OSG.Load(S); loaded := TRUE END END Load;<br />
*<br />
* PROCEDURE Exec*; VAR S: Texts.Scanner; BEGIN IF loaded THEN<br />
* Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);<br />
* IF S.class = Texts.Name THEN OSG.Exec(S) END END END Exec;<br />
*/<br />
void<br />
enter (int cl, long n, Ident name, Type type)<br />
{<br />
Object obj;<br />
obj = new ObjDesc;<br />
obj->Class = cl;<br />
obj->val = n;<br />
strcpy (obj->name, name);<br />
obj->type = type;<br />
obj->dsc = NULL;<br />
obj->next = topScope->next;<br />
topScope->next = obj;<br />
}<br />
void<br />
mainParser (void)<br />
{<br />
fprintf (W, "<strong>Portugol</strong> Compiler %s\n", VERSAO);<br />
guard = new ObjDesc;<br />
guard->Class = VARIAVEL;<br />
guard->type = intType;<br />
guard->val = 0;<br />
topScope = NULL;<br />
82
}<br />
OpenScope ();<br />
// Tipos predefinidos<br />
enter (Typ, 1, "LOGICO", boolType);<br />
enter (Typ, 2, "INTEIRO", intType);<br />
enter (Typ, 3, "LITERAL", litType);<br />
// Constantes<br />
enter (Const, 1, "VERDADEIRO", boolType);<br />
enter (Const, 0, "FALSO", boolType);<br />
// Funções Predefinidas<br />
enter (SProc, 1, "leia", NULL);<br />
enter (SProc, 2, "escreva", NULL);<br />
enter (SProc, 3, "escreva_hex", NULL);<br />
enter (SProc, 4, "escreva_nl", NULL);<br />
enter (SProc, 5, "inteiro", NULL);<br />
enter (SProc, 6, "tamanho", NULL);<br />
enter (SProc, 7, "ordem", NULL);<br />
enter (SProc, 8, "caractere", NULL);<br />
enter (SProc, 8, "número", NULL);<br />
enter (SProc, 9, "lit", NULL);<br />
universe = topScope;<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
83
CODEGENERATOR.H<br />
#ifndef ICODEGENERATOR<br />
#define ICODEGENERATOR<br />
#define maxCode 1000<br />
#define maxRel 200<br />
#define NofCom 16<br />
#define Head 0<br />
#define Var 1<br />
#define Par 2<br />
#define Const 3<br />
#define Fld 4<br />
#define Typ 5<br />
#define Proc 6<br />
#define SProc 7<br />
#define Reg 10<br />
#define Cond 11<br />
#define Boolean 0<br />
#define Integer 1<br />
#define Array 2<br />
#define Record 3<br />
#define Literal 4<br />
// Registradores reservados<br />
#define FP 29<br />
#define SP 30<br />
#define LNK 31<br />
// Tipos<br />
typedef struct ObjDesc *Object;<br />
typedef struct TypeDesc *Type;<br />
typedef struct Item<br />
{<br />
int mode, lev;<br />
Type type;<br />
long a, b, c, r;<br />
} Item;<br />
struct ObjDesc<br />
{<br />
int Class, lev;<br />
Object next, dsc;<br />
Type type;<br />
Ident name;<br />
long val;<br />
};<br />
struct TypeDesc<br />
{<br />
int form;<br />
Object fields;<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
84
Type base;<br />
int size, len;<br />
};<br />
#ifndef CODEGENERATOR<br />
extern Type boolType;<br />
extern Type intType;<br />
extern Type litType;<br />
extern int curlev;<br />
extern int pc;<br />
#endif<br />
void mainCodeGenerator (void);<br />
void ClearReg ();<br />
void GetReg (long &r);<br />
void Put (long op, long a, long b, long c);<br />
void EXCL (char *reg, int p);<br />
void TestRange (long x);<br />
void load (Item & x);<br />
void loadBool (Item & x);<br />
void PutOp (long cd, Item & x, Item & y);<br />
long negated (long cond);<br />
long merged (long L0, long L1);<br />
void fix (long at, long with);<br />
void FixWith (long L0, long L1);<br />
void FixLink (long L);<br />
void IncLevel (int n);<br />
void MakeConstItem (Item & x, Type typ, long val);<br />
void MakeItem (Item & x, Object y);<br />
void Field (Item & x, Object & y);<br />
void Index (Item & x, Item & y);<br />
void Op1 (int op, Item & x);<br />
void Op2 (int op, Item & x, Item & y);<br />
void Relation (int op, Item & x, Item & y);<br />
void Store (Item & x, Item & y);<br />
void Parameter (Item & x, Type & ftyp, int Class);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
85
void CJump (Item & x);<br />
void BJump (long L);<br />
void FJump (long &L);<br />
void Call (Item & x);<br />
void IOCall (Item & x, Item & y);<br />
void Header (long size);<br />
void Enter (long size);<br />
void Return (long size);<br />
void Open (void);<br />
void Close (FILE * S, long globals);<br />
void EnterCmd (char *name);<br />
void Load (FILE * S);<br />
void Exec (FILE * S);<br />
void Decode (FILE * T);<br />
#endif<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
86
CODEGENERATOR.CPP<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
/*<br />
* Módulo OSG - Code Generator Universidade do Amazonas Comport -<br />
* <strong>Compilador</strong> <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
*<br />
* Baseado no compilador Oberon-0 de Niklaus Wirth<br />
*<br />
*/<br />
#define CODEGENERATOR<br />
#include <br />
#include <br />
#include <br />
#include "scanner.h"<br />
#include "instrucoes.h"<br />
#include "risc.h"<br />
#include "funcoes.h"<br />
#include "codegenerator.h"<br />
// int curlev, pc;<br />
Type boolType, intType, litType;<br />
int curlev, pc;<br />
int relx, cno;<br />
long entry, fixlist;<br />
char regs[32]; // Verificar troca por SET -- forcar o<br />
// ClearReg!!!<br />
extern FILE *W;<br />
long code[maxCode];<br />
int rel[maxRel];<br />
Ident comname[NofCom];<br />
long comadr[NofCom];<br />
char mnemo[54][5];<br />
void<br />
ClearReg ()<br />
{<br />
int i;<br />
for (i = 0; i < 32; i++)<br />
regs[i] = 0;<br />
}<br />
void<br />
GetReg (long &r)<br />
{<br />
int i;<br />
for (i = 1; (i < FP && !regs[i]); i++);<br />
regs[i] = 1;<br />
r = i;<br />
}<br />
87
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
void<br />
Put (long op, long a, long b, long c)<br />
{<br />
if (op >= 32)<br />
op = op - 64;<br />
code[pc] = fASH (fASH (fASH (op, 5) + a, 5) + b, 16) + (c % 0x10000);<br />
pc++;<br />
}<br />
void<br />
EXCL (char *reg, int p)<br />
{<br />
reg[p] = 0;<br />
}<br />
void<br />
TestRange (long x)<br />
{<br />
if (x >= 0x8000 || x form != Boolean)<br />
88
}<br />
Mark ("Boolean ?");<br />
load (x);<br />
x.mode = Cond;<br />
x.a = 0;<br />
x.b = 0;<br />
x.c = 1;<br />
void<br />
PutOp (long cd, Item & x, Item & y)<br />
{<br />
long r;<br />
if (x.mode != Reg)<br />
load (x);<br />
if (x.r == 0)<br />
{<br />
GetReg (x.r);<br />
r = 0;<br />
}<br />
else<br />
{<br />
r = x.r;<br />
}<br />
if (y.mode == Const)<br />
{<br />
TestRange (y.a);<br />
Put (cd + 16, r, x.r, y.a);<br />
}<br />
else<br />
{<br />
if (y.mode != Reg)<br />
load (y);<br />
Put (cd, x.r, r, y.r);<br />
EXCL (regs, y.r);<br />
}<br />
}<br />
long<br />
negated (long cond)<br />
{<br />
if (ODD (cond))<br />
return (cond - 1);<br />
else<br />
return (cond + 1);<br />
}<br />
long<br />
merged (long L0, long L1)<br />
{<br />
long L2, L3;<br />
if (L0 != 0)<br />
{<br />
L2 = L0;<br />
do<br />
{<br />
L3 = code[L2] % 0x10000;<br />
if (L3 == 0)<br />
break;<br />
L2 = L3;<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
89
}<br />
while (1);<br />
code[L2] = code[L2] - L3 + L1;<br />
return (L0);<br />
}<br />
else<br />
return (L1);<br />
void<br />
fix (long at, long with)<br />
{<br />
code[at] = code[at] / 0x10000 * 0x10000 + (with % 0x10000);<br />
}<br />
void<br />
FixWith (long L0, long L1)<br />
{<br />
long L2;<br />
while (L0 != 0)<br />
{<br />
L2 = code[L0] % 0x10000;<br />
fix (L0, L1 - L0);<br />
L0 = L2;<br />
}<br />
}<br />
void<br />
FixLink (long L)<br />
{<br />
long L1;<br />
while (L != 0)<br />
{<br />
L1 = code[L] % 0x10000;<br />
fix (L, pc - L);<br />
L = L1;<br />
}<br />
}<br />
void<br />
IncLevel (int n)<br />
{<br />
curlev += n;<br />
}<br />
void<br />
MakeConstItem (Item & x, Type typ, long val)<br />
{<br />
x.mode = Const;<br />
x.type = typ;<br />
x.a = val;<br />
}<br />
void<br />
MakeItem (Item & x, Object y)<br />
{<br />
long r;<br />
x.mode = y->Class;<br />
x.type = y->type;<br />
x.lev = y->lev;<br />
x.a = y->val;<br />
if (y->lev == 0)<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
90
}<br />
x.r = 0;<br />
else if (y->lev == curlev)<br />
x.r = FP;<br />
else<br />
{<br />
Mark ("level!");<br />
x.r = 0;<br />
}<br />
if (y->Class == Par)<br />
{<br />
GetReg (r);<br />
Put (LDW, r, x.r, x.a);<br />
x.mode = Var;<br />
x.r = r;<br />
x.a = 0;<br />
}<br />
void<br />
Field (Item & x, Object & y)<br />
{<br />
x.a += y->val;<br />
x.type = y->type;<br />
}<br />
void<br />
Index (Item & x, Item & y)<br />
{<br />
if (y.type != intType)<br />
Mark ("index not integer");<br />
if (y.mode == Const)<br />
{<br />
if (y.a < 0 || y.a >= x.type->len)<br />
Mark ("bad index");<br />
x.a += y.a * x.type->base->size;<br />
}<br />
else<br />
{<br />
if (y.mode != Reg)<br />
load (y);<br />
Put (CHKI, y.r, 0, x.type->len);<br />
Put (MULI, y.r, y.r, x.type->base->size);<br />
if (x.r != 0)<br />
{<br />
Put (ADD, y.r, x.r, y.r);<br />
EXCL (regs, x.r);<br />
}<br />
x.r = y.r;<br />
}<br />
x.type = x.type->base;<br />
}<br />
void<br />
Op1 (int op, Item & x)<br />
{<br />
long t;<br />
if (op == MENOS)<br />
{<br />
if (x.type->form != Integer)<br />
Mark ("bad type");<br />
else<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
91
}<br />
{<br />
}<br />
if (x.mode == Const)<br />
x.a = -x.a;<br />
else<br />
{<br />
if (x.mode == Var)<br />
load (x);<br />
Put (SUB, x.r, 0, x.r);<br />
}<br />
}<br />
else<br />
{<br />
if (op == NAO)<br />
{<br />
if (x.mode != Cond)<br />
loadBool (x);<br />
x.c = negated (x.c);<br />
t = x.a;<br />
x.a = x.b;<br />
x.b = t;<br />
}<br />
else<br />
{<br />
if (op == E)<br />
{<br />
if (x.mode != Cond)<br />
loadBool (x);<br />
Put (BEQ + negated (x.c), x.r, 0, x.a);<br />
EXCL (regs, x.r);<br />
x.a = pc - 1;<br />
FixLink (x.b);<br />
x.b = 0;<br />
}<br />
else<br />
{<br />
if (op == OU)<br />
{<br />
if (x.mode != Cond)<br />
loadBool (x);<br />
Put (BEQ + x.c, x.r, 0, x.b);<br />
EXCL (regs, x.r);<br />
x.b = pc - 1;<br />
FixLink (x.a);<br />
x.a - 0;<br />
}<br />
}<br />
}<br />
}<br />
void<br />
Op2 (int op, Item & x, Item & y)<br />
{<br />
if (x.type->form == Integer && y.type->form == Integer)<br />
{<br />
if (x.mode == Const && y.mode == Const)<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
92
}<br />
{<br />
if (op == MAIS)<br />
x.a += y.a;<br />
else if (op == MENOS)<br />
x.a -= y.a;<br />
else if (op == MULTIPLICACAO)<br />
x.a *= y.a;<br />
else if (op == DIVISAO)<br />
x.a /= y.a;<br />
else if (op == RESTO)<br />
x.a %= y.a;<br />
else<br />
Mark ("bad type");<br />
}<br />
else<br />
{<br />
if (op == MAIS)<br />
PutOp (ADD, x, y);<br />
else if (op == MENOS)<br />
PutOp (SUB, x, y);<br />
else if (op == MULTIPLICACAO)<br />
PutOp (MUL, x, y);<br />
else if (op == DIVISAO)<br />
PutOp (DIV, x, y);<br />
else if (op == RESTO)<br />
PutOp (MOD, x, y);<br />
else<br />
Mark ("bad type");<br />
}<br />
}<br />
else<br />
{<br />
if (x.type->form == Boolean && y.type->form == Boolean)<br />
{<br />
if (y.mode != Cond)<br />
loadBool (y);<br />
if (op == OU)<br />
{<br />
x.a = y.a;<br />
x.b = merged (y.b, x.b);<br />
x.c = y.c;<br />
}<br />
else<br />
{<br />
if (op == E)<br />
{<br />
x.a = merged (y.a, x.a);<br />
x.b = y.b;<br />
x.c = y.c;<br />
}<br />
}<br />
}<br />
else<br />
Mark ("bad type");<br />
}<br />
void<br />
Relation (int op, Item & x, Item & y)<br />
{<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
93
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
if (x.type->form != Integer || y.type->form != Integer)<br />
Mark ("bad type");<br />
else<br />
{<br />
if (y.mode == Const && y.a == 0)<br />
load (x);<br />
else<br />
PutOp (CMP, x, y);<br />
x.c = op - IGUAL; // Revisar esta construção misteriosa!!!<br />
EXCL (regs, y.r);<br />
}<br />
x.mode = Cond;<br />
x.type = boolType;<br />
x.a = 0;<br />
x.b = 0;<br />
void<br />
Store (Item & x, Item & y)<br />
{<br />
long r;<br />
if ((x.type->form == Boolean || x.type->form == Integer) &&<br />
x.type->form == y.type->form)<br />
{<br />
if (y.mode == Cond)<br />
{<br />
Put (BEQ + negated (y.c), y.r, 0, y.a);<br />
EXCL (regs, y.r);<br />
y.a = pc - 1;<br />
FixLink (y.b);<br />
GetReg (y.r);<br />
Put (ADDI, y.r, 0, 1);<br />
Put (BEQ, 0, 0, 2);<br />
FixLink (y.a);<br />
Put (ADDI, y.r, 0, 0);<br />
}<br />
else<br />
{<br />
if (y.mode != Reg)<br />
load (y);<br />
}<br />
if (x.mode == Var)<br />
{<br />
if (x.lev == 0)<br />
{<br />
rel[relx] = SHORT (pc);<br />
relx++;<br />
}<br />
Put (STW, y.r, x.r, x.a);<br />
}<br />
else<br />
Mark ("illegal assignment");<br />
EXCL (regs, x.r);<br />
EXCL (regs, y.r);<br />
}<br />
else<br />
Mark ("incompatible assignment");<br />
}<br />
void<br />
Parameter (Item & x, Type & ftyp, int Class)<br />
94
{<br />
}<br />
long r;<br />
if (x.type == ftyp)<br />
{<br />
if (Class == Par)<br />
{<br />
if (x.mode == Var)<br />
{<br />
if (x.a != 0)<br />
{<br />
if (x.lev != 0)<br />
{<br />
rel[relx] = SHORT (pc);<br />
relx++;<br />
}<br />
GetReg (r);<br />
Put (ADDI, r, x.r, x.a);<br />
}<br />
else<br />
r = x.r;<br />
}<br />
else<br />
Mark ("illegal parameter mode");<br />
Put (PSH, r, SP, 4);<br />
EXCL (regs, r);<br />
}<br />
else<br />
{<br />
if (x.mode != Reg)<br />
load (x);<br />
Put (PSH, x.r, SP, 4);<br />
EXCL (regs, x.r);<br />
}<br />
}<br />
else<br />
Mark ("bad parameter type");<br />
void<br />
CJump (Item & x)<br />
{<br />
if (x.type->form == Boolean)<br />
{<br />
if (x.mode != Cond)<br />
loadBool (x);<br />
Put (BEQ + negated (x.c), x.r, 0, x.a);<br />
EXCL (regs, x.r);<br />
FixLink (x.b);<br />
x.a = pc - 1;<br />
}<br />
else<br />
{<br />
Mark ("Boolean?");<br />
x.a = pc;<br />
}<br />
}<br />
void<br />
BJump (long L)<br />
{<br />
Put (BEQ, 0, 0, L - pc);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
95
}<br />
void<br />
FJump (long &L)<br />
{<br />
Put (BEQ, 0, 0, L);<br />
L = pc - 1;<br />
}<br />
void<br />
Call (Item & x)<br />
{<br />
Put (BSR, 0, 0, x.a - pc);<br />
}<br />
void<br />
IOCall (Item & x, Item & y)<br />
{<br />
Item z;<br />
if (x.a < 4)<br />
{<br />
if (y.type->form != Integer)<br />
Mark ("Integer?");<br />
}<br />
}<br />
if (x.a == 1)<br />
{<br />
GetReg (z.r);<br />
z.mode = Reg;<br />
z.type = intType;<br />
Put (RD, z.r, 0, 0);<br />
Store (y, z);<br />
}<br />
else<br />
{<br />
if (x.a == 2)<br />
{<br />
load (y);<br />
Put (WRD, 0, 0, y.r);<br />
EXCL (regs, y.r);<br />
}<br />
else<br />
{<br />
if (x.a == 3)<br />
{<br />
load (y);<br />
Put (WRH, 0, 0, y.r);<br />
EXCL (regs, y.r);<br />
}<br />
else<br />
Put (WRL, 0, 0, 0);<br />
}<br />
}<br />
void<br />
Header (long size)<br />
{<br />
entry = pc;<br />
Put (ADDI, SP, 0, MemSize - size);<br />
Put (PSH, LNK, SP, 4);<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
96
}<br />
void<br />
Enter (long size)<br />
{<br />
Put (PSH, LNK, SP, 4);<br />
Put (PSH, FP, SP, 4);<br />
Put (ADD, FP, 0, SP);<br />
Put (SUBI, SP, SP, size);<br />
}<br />
void<br />
Return (long size)<br />
{<br />
Put (ADD, SP, 0, FP);<br />
Put (POP, FP, SP, 4);<br />
Put (POP, LNK, SP, size + 4);<br />
Put (RET, 0, 0, LNK);<br />
}<br />
void<br />
Open (void)<br />
{<br />
curlev = 0;<br />
pc = 0;<br />
relx = 0;<br />
ClearReg ();<br />
}<br />
void<br />
Close (FILE * S, long globals)<br />
{<br />
Put (POP, LNK, SP, 4);<br />
Put (RET, 0, 0, LNK);<br />
}<br />
void<br />
EnterCmd (char *name)<br />
{<br />
strcpy (name, comname[cno]);<br />
comadr[cno] = pc * 4;<br />
cno++;<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
void<br />
Load (FILE * S)<br />
{<br />
long i = 0L, k;<br />
while (i < relx)<br />
{<br />
k = rel[i++];<br />
code[k] = (code[k] / 0x10000 * 0x10000) + (code[k] + MemSize) %<br />
0x10000;<br />
}<br />
RISC.Load (code, pc);<br />
fprintf (W, " code loaded\n");<br />
RISC.Execute (entry * 4, S, stderr);<br />
}<br />
void<br />
97
Exec (FILE * S)<br />
{<br />
int i = 0;<br />
//NILO: traduzir a pesquisa<br />
//Carrega o nome e endereco das procedures<br />
// while(i 0x8000)<br />
a -= 0x10000;<br />
fprintf (W, "%4d\t%s\t%4d,%4d,%8d\n",<br />
4 * i,<br />
mnemo[cd / 0x4000000 % 0x40],<br />
cd / 0x200000 % 0x20, cd / 0x10000 % 0x20, a);<br />
i++;<br />
}<br />
fprintf (W, "reloc\n");<br />
i = 0;<br />
while (i < relx)<br />
{<br />
fprintf (W, "%5d", rel[i++] * 4);<br />
if (i % 16 == 0)<br />
fprintf (W, "\n");<br />
}<br />
fprintf (W, "\n");<br />
// Concatena a saída de W em T ...<br />
}<br />
void<br />
mainCodeGenerator (void)<br />
{<br />
boolType = new TypeDesc;<br />
boolType->form = Boolean;<br />
boolType->size = 4;<br />
intType = new TypeDesc;<br />
intType->form = Integer;<br />
intType->size = 4;<br />
litType = new TypeDesc;<br />
litType->form = Literal;<br />
litType->size = 8;<br />
strcpy (mnemo[ADD], "ADD ");<br />
strcpy (mnemo[SUB], "SUB ");<br />
strcpy (mnemo[MUL], "MUL ");<br />
strcpy (mnemo[DIV], "DIV ");<br />
strcpy (mnemo[MOD], "MOD ");<br />
strcpy (mnemo[CMP], "CMP ");<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
98
}<br />
strcpy (mnemo[OR], "OR ");<br />
strcpy (mnemo[AND], "AND ");<br />
strcpy (mnemo[BIC], "BIC ");<br />
strcpy (mnemo[XOR], "XOR ");<br />
strcpy (mnemo[LSH], "LSH ");<br />
strcpy (mnemo[ASH1], "ASH ");<br />
strcpy (mnemo[CHK], "CHK ");<br />
strcpy (mnemo[ADDI], "ADDI");<br />
strcpy (mnemo[SUBI], "SUBI");<br />
strcpy (mnemo[MULI], "MULI");<br />
strcpy (mnemo[DIVI], "DIVI");<br />
strcpy (mnemo[MODI], "CMPI");<br />
strcpy (mnemo[CMPI], "MODI");<br />
strcpy (mnemo[ORI], "ORI ");<br />
strcpy (mnemo[ANDI], "ANDI");<br />
strcpy (mnemo[BICI], "BICI");<br />
strcpy (mnemo[XORI], "XORI");<br />
strcpy (mnemo[LSHI], "LSHI");<br />
strcpy (mnemo[ASHI], "ASHI");<br />
strcpy (mnemo[CHKI], "CHKI");<br />
strcpy (mnemo[LDW], "LDW ");<br />
strcpy (mnemo[LDB], "LDB ");<br />
strcpy (mnemo[POP], "POP ");<br />
strcpy (mnemo[STW], "STW ");<br />
strcpy (mnemo[STB], "STB ");<br />
strcpy (mnemo[PSH], "PSH ");<br />
strcpy (mnemo[BEQ], "BEQ ");<br />
strcpy (mnemo[BNE], "BNE ");<br />
strcpy (mnemo[BLT], "BLT ");<br />
strcpy (mnemo[BGE], "BGE ");<br />
strcpy (mnemo[BLE], "BLE ");<br />
strcpy (mnemo[BGT], "BGT ");<br />
strcpy (mnemo[BSR], "BSR ");<br />
strcpy (mnemo[JSR], "JSR ");<br />
strcpy (mnemo[RET], "RET ");<br />
strcpy (mnemo[RD], "READ");<br />
strcpy (mnemo[WRD], "WRD ");<br />
strcpy (mnemo[WRH], "WRH ");<br />
strcpy (mnemo[WRL], "WRL ");<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
99
FUNCOES.H<br />
#ifndef IFUNCOES<br />
#define IFUNCOES<br />
#define MAX_ELEM_CJ 128<br />
#ifndef FUNCOES<br />
extern char minusculaC(char texto);<br />
extern void minusculaS(char *texto);<br />
extern long fASH (long R, long c);<br />
extern long fLSH (long R, long c);<br />
extern long SHORT (long x);<br />
extern int ODD (long x);<br />
extern bool PertenceConjunto(char *a, int elemento);<br />
extern void AdicionaConjunto(char *a, int elemento);<br />
extern void CriaConjunto(char *a);<br />
#endif<br />
#endif<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
100
FUNCOES.CPP<br />
#include <br />
#include <br />
#define FUNCOES<br />
#include "funcoes.h"<br />
long<br />
fASH (long R, long c)<br />
{<br />
long t, s;<br />
const m = (1 = 0)<br />
for (; c >= 0; c--)<br />
t = 1;<br />
t = (t & !m) + s;<br />
return (t);<br />
}<br />
long<br />
fLSH (long R, long c)<br />
{<br />
long t;<br />
t = R;<br />
if (c >= 0)<br />
for (; c >= 0; c--)<br />
t = t > 1;<br />
return (t);<br />
}<br />
int<br />
ODD (long x)<br />
{<br />
return ((1 & x));<br />
}<br />
int<br />
SHORT (long x)<br />
{<br />
return ((0xFFFF & x));<br />
}<br />
char minusculaC(char texto)<br />
{<br />
char minus[] = "áéíóúâêîôûäëïöüÿãõàèìòùñç";<br />
char maius[] = "ÁÉÍÓÚÂÊÎÔÛÄËÏÖÜYÃÕÀÈÌÒÙÑÇ";<br />
char *c;<br />
if(texto>='A' && texto
}<br />
else {<br />
c = strchr(maius, texto);<br />
if(c)<br />
texto=minus[c-maius];<br />
}<br />
return texto;<br />
void minusculaS(char *texto)<br />
{<br />
int i;<br />
char *c;<br />
for (i=0; texto[i]!=0;i++)<br />
texto[i] = minusculaC(texto[i]);<br />
}<br />
void CriaConjunto(char *a)<br />
{<br />
memset(a, MAX_ELEM_CJ, 0);<br />
}<br />
void AdicionaConjunto(char *a, int elemento)<br />
{<br />
a[elemento]=1;<br />
}<br />
bool PertenceConjunto(char *a, int elemento)<br />
{<br />
return(a[elemento]==1);<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
102
RISC.H<br />
#ifndef IRISC<br />
#define IRISC<br />
#define MemSize 4096<br />
class TRisc<br />
{<br />
public:<br />
long PC, IR, R[32], M[MemSize / 4];<br />
void Execute (long pc0, FILE * in, FILE * out);<br />
void Load (long code[], long len);<br />
void State ();<br />
};<br />
extern TRisc RISC;<br />
#endif<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
103
RISC.CPP<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
/*<br />
*<br />
* Módulo RISC - Interpretador de código Universidade do Amazonas Comport<br />
* - <strong>Compilador</strong> <strong>Portugol</strong> Aluno: <strong>Nilo</strong> Ney Coutinho <strong>Menezes</strong><br />
*<br />
* Baseado no compilador Oberon-0 de Niklaus Wirth<br />
*<br />
*/<br />
#include <br />
#include <br />
#include <br />
#include "instrucoes.h"<br />
#include "risc.h"<br />
#include "funcoes.h"<br />
void<br />
TRisc::Execute (long pc0, FILE * in, FILE * out)<br />
{<br />
long opc, a, b, c, nxt;<br />
int ii;<br />
R[31] = 0;<br />
PC = pc0 / 4;<br />
do<br />
{<br />
R[0] = 0;<br />
nxt = PC + 1;<br />
IR = M[PC];<br />
opc = (IR / 0x4000000) % 0x40;<br />
a = (IR / 0x200000) % 0x20;<br />
b = (IR / 0x10000) % 0x20;<br />
c = (IR % 0x10000);<br />
if (opc < ADDI)<br />
c = R[c % 0x20];<br />
else<br />
{<br />
if (c > 0x8000)<br />
c -= 0x10000;<br />
}<br />
switch (opc)<br />
{<br />
case ADD:<br />
case ADDI:<br />
R[a] = R[b] + c;<br />
break;<br />
case SUB:<br />
case SUBI:<br />
case CMP:<br />
case CMPI:<br />
R[a] = R[b] - c;<br />
break;<br />
case MUL:<br />
case MULI:<br />
104
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
R[a] = R[b] * c;<br />
break;<br />
case DIV:<br />
case DIVI:<br />
R[a] = R[b] / c;<br />
break;<br />
case MOD:<br />
case MODI:<br />
R[a] = R[b] % c;<br />
break;<br />
case OR:<br />
case ORI:<br />
R[a] = R[b] | c;<br />
break;<br />
case AND:<br />
case ANDI:<br />
R[a] = R[b] & c;<br />
break;<br />
case BIC:<br />
case BICI:<br />
R[a] = R[b] & !c;<br />
break;<br />
case XOR:<br />
case XORI:<br />
R[a] = R[b] ^ c;<br />
break;<br />
case LSH:<br />
case LSHI:<br />
fLSH (R[b], c);<br />
break;<br />
case ASH1:<br />
case ASHI:<br />
R[a] = fASH (R[b], c);<br />
break;<br />
case CHK:<br />
case CHKI:<br />
if (R[a] < 0 || R[a] > c)<br />
{<br />
fprintf (stderr, "Trap at %d\n", PC);<br />
return;<br />
}<br />
break;<br />
case LDW:<br />
R[a] = M[(R[b] + c) / 4];<br />
break;<br />
case LDB:<br />
R[a] = fLSH (M[(R[b] + c) / 4], (R[b] + c) / 4 * 8) % 0x100;<br />
break;<br />
case POP:<br />
R[a] = M[R[b] / 4];<br />
R[b] += c;<br />
break;<br />
case STW:<br />
M[(R[b] + c) / 4] = R[a];<br />
break;<br />
case STB:<br />
break; // Não implementado<br />
case PSH:<br />
R[b] -= c;<br />
M[(R[b] / 4)] = R[a];<br />
break;<br />
105
}<br />
case BEQ:<br />
if (R[a] == R[b])<br />
nxt = PC + c;<br />
break;<br />
case BNE:<br />
if (R[a] != R[b])<br />
nxt = PC + c;<br />
break;<br />
case BLT:<br />
if (R[a] < R[b])<br />
nxt = PC + c;<br />
break;<br />
case BGE:<br />
if (R[a] >= R[b])<br />
nxt = PC + c;<br />
break;<br />
case BLE:<br />
if (R[a] R[b])<br />
nxt = PC + c;<br />
break;<br />
case BSR:<br />
nxt = PC + c;<br />
R[31] = (PC + 1) * 4;<br />
break;<br />
case JSR:<br />
nxt = IR % 0x4000000;<br />
R[31] = (PC + 1) * 4;<br />
break;<br />
case RET:<br />
nxt = R[c % 0x20] / 4;<br />
if (nxt == 0)<br />
return;<br />
break;<br />
case RD:<br />
fscanf (in, "%d", &ii);<br />
R[a] = ii;<br />
break;<br />
case WRD:<br />
fprintf (stdout, " %d", R[c]);<br />
break;<br />
case WRH:<br />
fprintf (stdout, "%x", R[c]);<br />
break;<br />
case WRL:<br />
fprintf (stdout, "\n");<br />
break;<br />
}<br />
PC = nxt;<br />
}<br />
while (1);<br />
void<br />
TRisc::Load (long code[], long len)<br />
{<br />
int i;<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
106
}<br />
for (i = 0; i < len; i++)<br />
M[i] = code[i];<br />
void<br />
TRisc::State ()<br />
{<br />
fprintf (stderr, "PC=%d\n", PC * 4);<br />
fprintf (stderr, "SP=%d\n", R[30]);<br />
fprintf (stderr, "FP=%d\n", R[29]);<br />
fprintf (stderr, "R1=%d\n", R[1]);<br />
fprintf (stderr, "R2=%d\n", R[2]);<br />
fprintf (stderr, "R3=%d\n", R[3]);<br />
fprintf (stderr, "R4=%d\n", R[4]);<br />
}<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
107
INSTRUCOES.H<br />
// Instruções<br />
#define ADD 0<br />
#define SUB 1<br />
#define MUL 2<br />
#define DIV 3<br />
#define MOD 4<br />
#define CMP 5<br />
#define OR 8<br />
#define AND 9<br />
#define BIC 10<br />
#define XOR 11<br />
#define LSH 12<br />
#define ASH1 13<br />
#define CHK 14<br />
#define ADDI 16<br />
#define SUBI 17<br />
#define MULI 18<br />
#define DIVI 19<br />
#define MODI 20<br />
#define CMPI 21<br />
#define ORI 24<br />
#define ANDI 25<br />
#define BICI 26<br />
#define XORI 27<br />
#define LSHI 28<br />
#define ASHI 29<br />
#define CHKI 30<br />
#define LDW 32<br />
#define LDB 33<br />
#define POP 34<br />
#define STW 36<br />
#define STB 37<br />
#define PSH 38<br />
#define BEQ 40<br />
#define BNE 41<br />
#define BLT 42<br />
#define BGE 43<br />
#define BLE 44<br />
#define BGT 45<br />
#define BSR 46<br />
#define JSR 48<br />
#define RET 49<br />
#define RD 50<br />
#define WRD 51<br />
#define WRH 52<br />
#define WRL 53<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
108
PRINCIPAL.CPP<br />
#include <br />
#include <br />
#include <br />
// extern void mainScanner(void);<br />
// extern void mainCodeGenerator(void);<br />
#include "scanner.h"<br />
#include "codegenerator.h"<br />
#include "risc.h"<br />
#include "parser.h"<br />
#define VERSAO "0.92"<br />
#define DATA "2003-09-06"<br />
TRisc RISC;<br />
int<br />
main (int argc, char **argv)<br />
{<br />
FILE *FONTE;<br />
spawnl(P_WAIT, "pagina.bat", "pagina.bat","1252",NULL);<br />
}<br />
mainScanner ();<br />
mainCodeGenerator ();<br />
mainParser ();<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
if(argc==2)<br />
{<br />
FONTE = fopen(argv[1],"r");<br />
if(FONTE==NULL)<br />
{<br />
fprintf(stderr, "Erro ao abrir arquivo fonte!! [%s]\n", argv[1]);<br />
exit(1);<br />
}<br />
}<br />
else<br />
{<br />
FONTE=stdin;<br />
fprintf(stderr, "Lendo fonte da entrada padrão [stdin]\n");<br />
}<br />
Compile (FONTE);<br />
// Pausa para manter a janela aberta (tecla para terminar)<br />
fgetc(stdin);<br />
109
MAKEFILE<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
# -------------------------------------------------------------------------<br />
--<br />
!if !$d(BCB)<br />
BCB = $(MAKEDIR)\..<br />
!endif<br />
# -------------------------------------------------------------------------<br />
--<br />
# IDE SECTION<br />
# -------------------------------------------------------------------------<br />
--<br />
# The following section of the project makefile is managed by the BCB IDE.<br />
# It is recommended to use the IDE to change any of the values in this<br />
# section.<br />
# -------------------------------------------------------------------------<br />
--<br />
VERSION = BCB.06.00<br />
# -------------------------------------------------------------------------<br />
--<br />
PROJECT = portugol.exe<br />
OBJFILES = scanner.obj parser.obj risc.obj codegenerator.obj funcoes.obj<br />
principal.obj<br />
RESFILES =<br />
MAINSOURCE = portugol.bpf<br />
RESDEPEN = $(RESFILES)<br />
LIBFILES =<br />
IDLFILES =<br />
IDLGENFILES =<br />
LIBRARIES =<br />
PACKAGES = dbrtl.bpi vcldb.bpi adortl.bpi ibsmp.bpi bdertl.bpi vcldbx.bpi<br />
qrpt.bpi \<br />
teeui.bpi teedb.bpi tee.bpi dss.bpi teeqr.bpi ibxpress.bpi dsnap.bpi \<br />
vclie.bpi inetdb.bpi inet.bpi nmfast.bpi webdsnap.bpi bcbie.bpi \<br />
bcb2kaxserver.bpi<br />
SPARELIBS =<br />
DEFFILE =<br />
OTHERFILES =<br />
# -------------------------------------------------------------------------<br />
--<br />
DEBUGLIBPATH = $(BCB)\lib\debug<br />
RELEASELIBPATH = $(BCB)\lib\release<br />
USERDEFINES = _DEBUG;PRINCIPAL<br />
SYSDEFINES = NO_STRICT;_NO_VCL<br />
INCLUDEPATH = $(BCB)\include;$(BCB)\include\vcl<br />
LIBPATH = $(BCB)\lib\obj;$(BCB)\lib<br />
WARNINGS= -w-par<br />
PATHCPP = .;<br />
PATHASM = .;<br />
PATHPAS = .;<br />
PATHRC = .;<br />
PATHOBJ = .;$(LIBPATH)<br />
# -------------------------------------------------------------------------<br />
--<br />
110
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
CFLAG1 = -Od -H=c:\ARQUIV~1\borland\CBUILD~1\lib\vcl60.csm -Hc -Q -Vx -X- -<br />
A -r- \<br />
-a8 -6 -b- -k -y -v -vi- -tWC -tWM- -c<br />
IDLCFLAGS = -src_suffix cpp -D_DEBUG -DPRINCIPAL -I$(BCB)\include -<br />
I$(BCB)\include\vcl \<br />
-boa<br />
PFLAGS = -$YD -$W -$O- -$A8 -v -JPHNE -M<br />
RFLAGS =<br />
AFLAGS = /mx /w2 /zi<br />
LFLAGS = -D"" -ap -Tpe -x -Gn -v<br />
# -------------------------------------------------------------------------<br />
--<br />
ALLOBJ = c0x32.obj $(OBJFILES)<br />
ALLRES = $(RESFILES)<br />
ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cw32.lib<br />
# -------------------------------------------------------------------------<br />
--<br />
!ifdef IDEOPTIONS<br />
[Version Info]<br />
IncludeVerInfo=0<br />
AutoIncBuild=0<br />
MajorVer=1<br />
MinorVer=0<br />
Release=0<br />
Build=0<br />
Debug=0<br />
PreRelease=0<br />
Special=0<br />
Private=0<br />
DLL=0<br />
[Version Info Keys]<br />
CompanyName=<br />
FileDescription=<br />
FileVersion=1.0.0.0<br />
InternalName=<br />
LegalCopyright=<br />
LegalTrademarks=<br />
OriginalFilename=<br />
ProductName=<br />
ProductVersion=1.0.0.0<br />
Comments=<br />
[Debugging]<br />
DebugSourceDirs=$(BCB)\source\vcl<br />
!endif<br />
# -------------------------------------------------------------------------<br />
--<br />
# MAKE SECTION<br />
# -------------------------------------------------------------------------<br />
--<br />
# This section of the project file is not used by the BCB IDE. It is for<br />
# the benefit of building from the command-line using the MAKE utility.<br />
111
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
# -------------------------------------------------------------------------<br />
--<br />
.autodepend<br />
# -------------------------------------------------------------------------<br />
--<br />
!if "$(USERDEFINES)" != ""<br />
AUSERDEFINES = -d$(USERDEFINES:;= -d)<br />
!else<br />
AUSERDEFINES =<br />
!endif<br />
!if !$d(BCC32)<br />
BCC32 = bcc32<br />
!endif<br />
!if !$d(CPP32)<br />
CPP32 = cpp32<br />
!endif<br />
!if !$d(DCC32)<br />
DCC32 = dcc32<br />
!endif<br />
!if !$d(TASM32)<br />
TASM32 = tasm32<br />
!endif<br />
!if !$d(LINKER)<br />
LINKER = ilink32<br />
!endif<br />
!if !$d(BRCC32)<br />
BRCC32 = brcc32<br />
!endif<br />
# -------------------------------------------------------------------------<br />
--<br />
!if $d(PATHCPP)<br />
.PATH.CPP = $(PATHCPP)<br />
.PATH.C = $(PATHCPP)<br />
!endif<br />
!if $d(PATHPAS)<br />
.PATH.PAS = $(PATHPAS)<br />
!endif<br />
!if $d(PATHASM)<br />
.PATH.ASM = $(PATHASM)<br />
!endif<br />
!if $d(PATHRC)<br />
.PATH.RC = $(PATHRC)<br />
!endif<br />
!if $d(PATHOBJ)<br />
.PATH.OBJ = $(PATHOBJ)<br />
!endif<br />
# -------------------------------------------------------------------------<br />
--<br />
112
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
$(PROJECT): $(OTHERFILES) $(IDLGENFILES) $(OBJFILES) $(RESDEPEN) $(DEFFILE)<br />
$(BCB)\BIN\$(LINKER) @&&!<br />
$(LFLAGS) -L$(LIBPATH) +<br />
$(ALLOBJ), +<br />
$(PROJECT),, +<br />
$(ALLLIB), +<br />
$(DEFFILE), +<br />
$(ALLRES)<br />
!<br />
# -------------------------------------------------------------------------<br />
--<br />
.pas.hpp:<br />
$(BCB)\BIN\$(DCC32) $(PFLAGS) -U$(INCLUDEPATH) -<br />
D$(USERDEFINES);$(SYSDEFINES) -O$(INCLUDEPATH) --BCB {$< }<br />
.pas.obj:<br />
$(BCB)\BIN\$(DCC32) $(PFLAGS) -U$(INCLUDEPATH) -<br />
D$(USERDEFINES);$(SYSDEFINES) -O$(INCLUDEPATH) --BCB {$< }<br />
.cpp.obj:<br />
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />
D$(USERDEFINES);$(SYSDEFINES) -n$(@D) {$< }<br />
.c.obj:<br />
$(BCB)\BIN\$(BCC32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />
D$(USERDEFINES);$(SYSDEFINES) -n$(@D) {$< }<br />
.c.i:<br />
$(BCB)\BIN\$(CPP32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />
D$(USERDEFINES);$(SYSDEFINES) -n. {$< }<br />
.cpp.i:<br />
$(BCB)\BIN\$(CPP32) $(CFLAG1) $(WARNINGS) -I$(INCLUDEPATH) -<br />
D$(USERDEFINES);$(SYSDEFINES) -n. {$< }<br />
.asm.obj:<br />
$(BCB)\BIN\$(TASM32) $(AFLAGS) -i$(INCLUDEPATH:;= -i) $(AUSERDEFINES) -<br />
d$(SYSDEFINES:;= -d) $
APENDICE B <strong>–</strong> TABELA ASCII<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
114
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
APENDICE C <strong>–</strong> OPCODES DA MÁQUINA VIRTUAL<br />
Tipo da<br />
Instrução/opcode<br />
Transferência de<br />
dados<br />
LB, LBU, SB<br />
LH, LHU, SH<br />
LW, SW<br />
LF, LD, SF, SD<br />
MOVI2S, MOVS2I<br />
MOVF, MOVD<br />
MOVFP2I, MOVI2FP<br />
Aritmético/Lógico<br />
ADD, ADDI, ADDU,<br />
ADDUI<br />
SUB, SUBI, SUBU,<br />
SUBUI<br />
Significado<br />
Movimentação de dados entre os registradores e<br />
a memória ou entre um registrador inteiro, de<br />
ponto flutuante ou de propósito especial. Só há<br />
uma forma de endereçamento: deslocamento de<br />
16 bits + o valor de um registrador de uso geral.<br />
Carrega byte, carrega byte sem sinal e armazena<br />
byte<br />
Carrega meia-palavra, carrega meia-palavra sem<br />
sinal, armazena meia palavra<br />
Carrega palavra, armazena palavra (de/para)<br />
registradores inteiros<br />
Carrega número de ponto flutuante de precisão<br />
simples, carrega número de ponto flutuante de<br />
precisão dupla, armazena número de ponto<br />
flutuante de precisão simples, armazena número<br />
de ponto flutuante de precisão dupla<br />
Move de ou para um registrador de uso geral de<br />
ou para um registrador de uso especial<br />
Copia um registrador de ponto flutuante ou um<br />
para de dupla precisão para outro registrador ou<br />
par.<br />
Move 32 bits de/para um registrador de ponto<br />
flutuante de/para um registrador inteiro<br />
Operações em inteiros ou tipos lógicos em<br />
registros de uso geral. Operações aritméticas<br />
com sinalsetam o trap em caso de overflow<br />
Adiciona, adiciona com constante (16 bits); com<br />
sinal e sem.<br />
Subtraia, subtraia com constante (16 bits); com e<br />
sem sinal<br />
MULT, MULTU, DIV, Multiplique e divida, com e sem sinal<br />
115
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
DIVU paraoperadores de ponto flutuante. Todas as<br />
operações com valores de 32-bits<br />
AND, ANDI E lógico e E lógico com constante<br />
OR, ORI, XOP, XOPI<br />
LHI<br />
SLL, SRL, SRA,<br />
SLLI, SRLI, SRAI<br />
S__, S__I<br />
Controle<br />
BEQZ, BNEZ<br />
BFPT, BFPF<br />
J, JR<br />
JAL, JALR<br />
TRAP<br />
RFE<br />
Ponto Flutuante<br />
Ou, Ou com constante, Ou exclusivo e Ou<br />
exclusive com constante<br />
Carrega a metade superior de um registro com<br />
uma constante<br />
Deslocamentos: com constante (S__I) ou com<br />
variável (S__); deslocamentos a esquerda lógico,<br />
a direita lógico e a direita aritmético<br />
Marca se condição: "__" pode ser LT, GT, LE, GE,<br />
EQ, NE (menor, maior, menor ou igual, maior ou<br />
igual, igual, não igual)<br />
Saltos condicionais e desvios. Relativos ao PC<br />
(program counter) ou através de registrador<br />
Salta se o registrador é igual ou diferente a zero.<br />
Deslocamento de 16 bits a partir do PC<br />
Testa o bit de comparação do registrador de<br />
status FP e salta (16 bits a partir do PC)<br />
Salta a partir do PC com deslocamento de 26 bits<br />
ou para endereço no registrador (JR)<br />
Salta e marca retorno: salva PC+4 no R31. O<br />
endereço destino é relative a PC(JAL) ou a um<br />
registro (JALR)<br />
Transfere a execução para o sistema operacional<br />
num endereço armazenado em um vetor<br />
Retorna para o código do usuário de uma<br />
exceção. Retorna a execução para o código do<br />
usuário.<br />
Operações de ponto flutuante em dupla<br />
precisão (DP) ou precisão simples (SP)<br />
ADDD, ADDF Soma números de DP, SP<br />
SUBD, SUBF Subtrai números de DP, SP<br />
MULTD, MULTF Multiplica números de DP, SP<br />
DIVD, DIVF Divide números de DP, SP<br />
CVTF2D, CVTF2I, Instruções de converção: CVTx2y converte do tipo<br />
116
CVTD2F,<br />
CVTD2I, CVTI2F,<br />
CVTI2D<br />
__D, __F<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
x para o tipo y, onde x e y podem ser I para<br />
inteiro, D para precisão dupla e F para simples<br />
precisão. Ambos operandos devem estar em<br />
registradores FP.<br />
Compara números de DP e SP compares: "__"<br />
pode ser LT, GT, LE, GE, EQ, NE(menor, maior,<br />
menor ou igual, maior ou igual, igual, não igual);<br />
Ativa o bit de comparação no registrador de status<br />
FP.<br />
117
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
APENDICE D <strong>–</strong> EMENTAS DE CURSOS DE COMPILAÇÃO<br />
DE OUTRAS UNIVERSIDADES<br />
Instituição: UNESP<br />
URL: http://www.dcce.ibilce.unesp.br/comp/alldisc.html<br />
Disciplina: Construção de <strong>Compilador</strong>es<br />
Pré requisito: Fundamentos em Linguagens e Teoria da Computação e Autorização<br />
do Coordenador do Curso<br />
Ementa: Estudo dos componentes de um compilador, com o projeto de um<br />
compilador para uma linguagem simples, incluíndo os módulos de análise léxica,<br />
sintática e semântica, além do gerador de código e otimizador.<br />
Instituição: UFMG<br />
URL: http://www.dcc.ufmg.br/~mariza/Cursos/<strong>Compilador</strong>es/Comp2001-2/Prog2001-<br />
2/comp_txt.html<br />
Disciplina: <strong>Compilador</strong>es<br />
Pré-Requisitos: Esta disciplina é oferecida aos alunos do sexto período do<br />
Bacharelado em Ciência da Computação da UFMG. Os pré-requisitos da disciplina<br />
são: Algoritmos e Estruturas de Dados I, Algoritmos e Estruturas de Dados II e<br />
Fundamentos da Teoria da Computação.<br />
Programa do Curso: O objetivo da disciplina é ensinar técnicas básicas de<br />
construção de compiladores e conceitos relacionados com linguagens de<br />
programação. A matéria apresentada tem aplicação não somente em projeto de<br />
linguagens de programação, mas é também importante para a compreensão e<br />
implementação de interfaces que tornem mais natural a comunicação<br />
homem/máquina. Concluindo o curso, os alunos deverão ser capazes de definir a<br />
gramática de uma linguagem e programar seu compilador ou interpretador.<br />
Ementa: Gramáticas. Análise léxica. Análise sintática. Tabela de símbolos.<br />
Linguagens intermediárias. Alocação de memória em tempo de execução. Tradução<br />
dirigida por sintaxe.<br />
118
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Instituição: UFMG - Pós-graduação<br />
URL: http://www.dcc.ufmg.br/pos/html/node5.html<br />
Disciplina: Linguagens de Programação e <strong>Compilador</strong>es<br />
Ementa: <strong>Compilador</strong>es, Teoria de Linguagens, Semântica Formal, Tópicos em<br />
<strong>Compilador</strong>es, Tópicos em Linguagens de Programação.<br />
Instituição: Centro Universitário Feevale<br />
URL: http://www.feevale.tche.br/graduacao/icet/cico/ementa.htm#compiladores-B<br />
Disciplina: <strong>Compilador</strong>es.<br />
Ementa: Organização e estrutura de compiladores e interpretadores. Análise léxica.<br />
Análise sintática. Alocação e gerência de memória. Formas internas de programa<br />
fonte. Análise semântica. Geração de código. Optimização de código.<br />
Instituição: Universidade Estadual Vale do Acaraú - Sobral/CE<br />
URL: http://uvanet.br/computacao/ementa.php<br />
Curso: Bacharelado em Ciências da Computação<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: Organização de um compilador. Tabela de símbolos durante a compilação<br />
e execução. Varredura Léxica. Varredura Sintática. Geração de código objeto.<br />
Otimização e Recuperação de Erros. Linguagens para escrever compiladores.<br />
Instituição: Universidade Estadual de Ponta Grossa<br />
URL: http://www.deinfo.uepg.br/ementas.html<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: Estrutura lógica dos compiladores. Fases de análise e síntese. Obtenção de<br />
compiladores. Teoria das linguagens. Gramáticas formais. Autômatos finitos<br />
determinísticos e não determinísticos. Reconhecedores léxicos. Autômatos de pilha.<br />
Reconhecedores sintáticos. Geração e otimização de código. Projeto de um<br />
compilador.<br />
Instituição: Pontifícia Unive rsidade Católica do Rio Grande do Sul<br />
URL: http://pucrs.campus2.br/faci/info/5/<br />
Disciplina: <strong>Compilador</strong>es I<br />
119
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Objetivos: O cumprimento da disciplina busca dar ao aluno, ao final do semestre,<br />
capacidade de: Descrever, formalmente, os componentes de um compilador;<br />
Projetar linguagens de programação; Elaborar rotinas para análise lexicográfica,<br />
gerenciamento de tabelas de símbolos e análise sintática; Projetar compiladores.<br />
Ementa: Tradução e compilação, etapas da compilação. Análise léxica: tabelas de<br />
símbolos. Análise sintática: construção e geração de analisadores, precedência de<br />
operadores, LR. Tradução dirigida à sintaxe: translação, definições, gramáticas de<br />
atributos. Análise semântica estática: verificação de tipos, escopo, equivalência e<br />
compatibilidade, coerção, sobrecarga e polimorfismo.<br />
Programa: Introdução à Compilação, Introdução: Fases de um compilador, Fase de<br />
Análise, Fase de Síntese, Tabela de Símbolos, Detecção de erros, Análise Léxica,<br />
Funções de Analisador Léxico, A relação: Analisadores Léxicos X Autômatos Finitos<br />
X Expressões Regulares, Implementação de Analisadores Léxicos, Tabela de<br />
símbolos, Ferramentas para construção de Analisadores Léxicos, Análise Sintática,<br />
Funções de Analisador Sintático, A relação: Analisadores Sintáticos X Gramáticas<br />
Livres de Contexto, Analisadores Sintáticos Descendentes, Analisador Preditivo,<br />
Analisador Sintático Descendente Recursivo, Analisadores Sintáticos Ascendentes,<br />
Precedência de Operadores, Técnicas LR, Ferramentas para construção de<br />
Analisadores Sintáticos, Tradução dirigida por Sintaxe, Introdução a Tradução<br />
Dirigida por Sintaxe, Definição Dirigida pos Sintaxe, Esquemas de Tradução,<br />
Verificação Semântica, Sistemas de tipos, Sub-linguagem de tipos genérica,<br />
Verificação de tipos estática X dinâmica, Verificação de tipos simples: expressões e<br />
comandos, Equivalência de tipos, Coerção, Sobrecarga, Polimorfismo.<br />
Instituição: Universidade do Planalto Catarinense - UNIPLAC<br />
URL: http://www.uniplac.rct-sc.br/Ensino/Informatica/ementa_biblio_.htm<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: Análise Léxica e Sintática. Tabelas de Símbolos. Esquemas de Tradução.<br />
Ambientes de Tempo de Execução. Linguagens intermediárias. Geração de Código.<br />
Otimização de Código. Montadores. Ligadores.<br />
Sociedade Brasileira de Computação<br />
120
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
URL:http://www.sbc.org.br/notitia/servlet/newstorm.notitia.apresentacao.ServletDeNo<br />
ticia?codigoDaNoticia=38&dataDoJornal=atual<br />
Currículo de Referência da SBC para Cursos de Graduação em Computação e<br />
Informática<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: Análise léxica e sintática. Tabelas de símbolos. Esquemas de tradução.<br />
Ambientes de tempo de execução. Linguagens intermediárias. Geração de código.<br />
Otimização de código. Montadores, ligadores.<br />
Instituição: PUC-Minas<br />
URL: http://www.inf.pucminas.br/dcc/bh/disciplinas/cmpl.html<br />
Curso: Ciência da Computação<br />
Disciplina: <strong>Compilador</strong>es<br />
Objetivos: preparar o aluno para entender o processo de compilação no que tange<br />
aos seus processos internos nos métodos de análise léxica, sintática e semântica,<br />
com o objetivo de otimizar o projeto de sistemas e detalhamento de programas, e<br />
para iniciar o aluno no processo de construção de um compilador.<br />
Ementa: análise léxica, sintática e semântica, geração de código<br />
Instituição: Universidade Federal de Goiás<br />
URL: http://www.inf.ufg.br/~cedric/comp.html<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: O processo de compilação. Análise léxica. O analisador léxico como um<br />
autômato finito. Análise sintática Ascendente e descendente. Tabelas de símbolos:<br />
estruturas de blocos. Análise de contexto e geração de código. Recuperação de<br />
erros. Implementação de um compilador para uma linguagem de alto nível.<br />
Instituição: Universidade Federal de Mato Grosso do Sul<br />
URL: http://www.ufms.br/ensino/grad/ccet/ccomp/ementa.htm<br />
Curso: Ciência da Computação<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: Introdução à compilação. Análise léxica. Análise sintática. Tradução dirigida<br />
por sintaxe. Checagem de tipos. Ambiente de execução. Geração de código<br />
121
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
intermediário. Geração de código. Otimização de código. A construção de um<br />
compilador.<br />
Instituição: Universidade Tiradentes - Sergipe<br />
URL: http://www.unit.br/graduacao/sistemas_de_informacao/ementasgrade2000.htm<br />
Disciplina: Linguagens Formais e <strong>Compilador</strong>es<br />
Ementa: Gramáticas e Autômatos. Gramáticas Livres de Contexto e Autômatos a<br />
Pilha. Gramáticas Irrestritas e Sensíveis ao contexto. Introdução à Arquitetura de<br />
<strong>Compilador</strong>es. Análise Léxica, Sintática e Semântica. Geração de Código<br />
Intermediário. Otimização e Geração de Código.<br />
Instituição: Universidade Federal de Uberlândia<br />
URL: http://www.feelt.ufu.br/graduacao/ementas/ELT81.htm<br />
Disciplina: Construção de <strong>Compilador</strong>es 1<br />
Objetivo: Apresentar noções da teoria de Linguagens Formais e Automáticas.<br />
Capacitar o aluno a construir parte de um compilador de interpretador para<br />
linguagem de alto nível. Ensinar as técnicas de análise léxica e sintática.<br />
Disciplina: Construção de <strong>Compilador</strong>es 2<br />
Ementa: Análise de contexto. Geração de código intermediário. Geração de código.<br />
Otimização de códigos. Recuperação de erros.<br />
Instituição: UFRJ<br />
URL: http://www.dcc.ufrj.br/informatica/curriculo/obrigatorias.html<br />
Disciplina: <strong>Compilador</strong>es I<br />
Ementa: Visão Geral. Tabelas de símbolos. Análise Léxica. Especificação Sintática<br />
de Linguagens de Programação. Análise Sintática Top-Down e Bottom-Up. Formas<br />
intermediárias. Conceitos Básicos de tradução dirigida pela sintaxe. Conceitos<br />
Básicos de Otimização. Recuperação de erros. Conceitos Básicos de Alocação de<br />
Registradores.<br />
Disciplina: <strong>Compilador</strong>es II<br />
Ementa: Revisão de Análise Léxica e Sintática. Especificação Semântica através de<br />
Gramáticas de Atributos. Avaliação de Atributos. Otimização e Geração de Código.<br />
122
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
Instituição: USP<br />
URL: http://www.ime.usp.br/grad/catalogo/2000/mac/node40.html<br />
Disciplina: Projeto de <strong>Compilador</strong>es<br />
Objetivos: Construção de um compilador e o ensino associado à geração de código<br />
e otimização.<br />
Instituição: Universidade Federal de Lavras - UFLA / MG<br />
URL: http://www.prg.ufla.br/cursos/cienc_comp/ementas_cc.htm<br />
Disciplina: <strong>Compilador</strong>es<br />
Ementa: Gramáticas e Linguagens Formais. Estrutura de um compilador. Análise<br />
léxica. Análise sintática. Análise semântica. Gerador de código intermediário.<br />
Otimização de código.<br />
Conteúdo: O processo de compilação. Implementação de analisadores sintáticos.<br />
recuperação de erros sintáticos. Tabela de símbolos; estrutura de blocos. A análise<br />
de contexto e geração de código objeto. Expressões aritméticas e booleanas.<br />
Comandos repetitivos e de seleção. Variáveis indexadas. Procedimentos e<br />
recursividade. Otimização e alocação de registradores.<br />
123
-, 27<br />
( ), 27<br />
*, 27<br />
?, 27<br />
[ ], 27<br />
{ }, 27<br />
|, 27<br />
+, 27<br />
a<br />
(<br />
*<br />
?<br />
[<br />
{<br />
|<br />
+<br />
A<br />
alfabeto, 19<br />
analisador léxico, 26<br />
analisador sintático, 28<br />
autômato finito<br />
ÍNDICE REMISSIVO<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
determinístico, 21<br />
fita, 21<br />
não-determinísticos, 23<br />
programa, 21<br />
unidade de controle, 21<br />
Backus-Naur-Form. Consulte BNF<br />
BNF, 28<br />
compilador, 24<br />
comprimento, 20<br />
B<br />
C<br />
E<br />
Expressões regulares, 26<br />
gramática, 28<br />
G<br />
L<br />
Lexemas, 26<br />
linguagem, 19<br />
linguagem de origem, 24<br />
padrão, 26<br />
palavra, 20<br />
palavra vazia, 20<br />
P<br />
124
símbolos, 19<br />
inicial, 19<br />
não-terminais, 19<br />
terminais, 19<br />
S<br />
Tokens, 26<br />
vocabulário, 19<br />
ComPort <strong>–</strong> <strong>Compilador</strong> <strong>Portugol</strong><br />
T<br />
V<br />
125