quinta-feira, 21 de agosto de 2008

manuscrito ACM. bytecode.

Aqui está o manuscrito ACM do bytecode.
Abordando o que foi explicado nesse blog e nas apresentações em sala, o manuscrito vai documentar tudo que nós pesquisamos e aprendemos com esse traballho. ele pode ser visto aqui mesmo no blog, como também pode ser feito o download, via SlideShare.


sábado, 9 de agosto de 2008

Estudo de Caso

O presente estudo de caso abordará a utilização de um dos tipos de tradutores – compilador – pela tecnologia Framework.Net e um exemplo de aplicação prática desse modelo através da ferramenta Asp.Net.
O Framework.Net é uma tecnologia utilizada para se construir e executar aplicações .Net (ponto Net) e possui a seguinte estrutura:

Figura1: Estrutura do Framework.Net (esta figura encontra-se na apresentação)

A partir da figura, pode-se observar que esta tecnologia faz uso de duas camadas de compiladores para implementar o mecanismo de tradução, o que revela a existência de um duplo processo de geração de código: o primeiro, composto pela camada de compiladores específicos (Compiler) de cada linguagem de programação, visto que, cada compilador só consegue traduzir um conjunto específico de regras de sintaxe, é responsável por receber o código fonte escrito em uma dada linguagem de programação e convertê-lo para um código intermediário que, no caso em questão, será padronizado; o segundo, composto por um compilador chamado JIT (Just in Time Compiler), tem por finalidade traduzir o código intermediário vindo da camada de compiladores específicos em código objeto, representado pela camada Native Code, que estará pronto para ser executado pelo sistema operacional (Operating System Services).
Um bom exemplo de utilização desse modelo é encontrado no Asp.Net. Asp.Net é um ambiente de desenvolvimento para aplicações .Net. Este ambiente possui uma característica muito importante, o suporte a diversas linguagens de programação, ou seja, um programador poderá escolher a linguagem de programação em que o mesmo usará para codificar um site. Isso é possível devido à utilização do Framework.Net por parte do Asp.Net, pois a capacidade de suportar diversas linguagens e conseguir executar um site após ser construído está relacionada ao duplo processo de geração de código existente no Framework.Net, que já foi exposto anteriormente.

Perspectivas sobre o futuro dos tradutores...

O caminho a ser seguido no campo dos tradutores de linguagens de programação dependerá tanto do que já é necessário para os desenvolvedores de aplicativos (software básico que possibilita a construção de outros programas) como também do que ainda está por vir.
No entanto, pelo contexto atual, verifica-se a utilização em expansão de um tipo de tradutor, a máquina virtual, para suprir um ponto negativo do processo de geração de código encontrado nos compiladores, que é a dependência do código objeto em relação ao sistema operacional. Um bom exemplo desse ponto é a máquina virtual Java.
O interpretador continuará sendo usado pela internet, que é um grande exemplo de utilização desse tradutor, e poderá se desenvolver ainda mais.
Além disso, está ocorrendo uma maior utilização dos compiladores, principalmente no que se refere ao duplo processo de geração de código, ou seja, uso de vários compiladores para a obtenção do código objeto, fato encontrado no Framework.Net que possui diversos compiladores (apenas um é usado para a escrita de um programa) para se produzir o código intermediário e um compilador geral responsável pela geração do código objeto final.
Diante do que foi exposto, percebe-se que os tipos de tradutores atuais (compiladores, interpretadores e máquina virtual) continuarão sendo utilizados, o que poderá ocorrer é o que já foi mencionado: a expansão, diminuição de alguns e até a criação de novas formas de tradução.

Diferenças entre compiladores e interpretadores (vantagens e desvantagens)

Compiladores são tipos de tradutores que possuem uma forma específica de conversão, visto que, atuam na transformação de uma linguagem de alto nível para uma linguagem de baixo nível – linguagem de máquina. Assim como o compilador, um interpretador analisa sintática e semanticamente um programa escrito em uma determinada linguagem de programação, no entanto, segundo [1], algumas diferenças são observadas, principalmente no que se refere à forma de se executar o programa em questão: o compilador executa o programa somente após ter traduzido o mesmo por inteiro; já o interpretador, lê, traduz e executa cada linha de código sequencialmente, ou seja, passo a passo; no compilador, há geração de um código de máquina ao final do processo de tradução; já no interpretador, não existe a criação de código executável;

Vantagens e Desvantagens

Compiladores
- Vantagens:
1) A execução do programa é mais rápida.
2) Estruturas de dados mais completas;
3) Permitem a otimização de código fonte.
- Desvantagens:
1) Várias etapas de tradução;
2) Processo de correção de erro e de depuração é mais demorado;
3) Programação final é maior, o que gera a necessidade de mais memória;

Interpretadores
- Vantagens:
1) Depuração é mais simples;
2) Consomem menos memória;
3) Resultado imediato do programa ou rotina desenvolvida.
- Desvantagem:
1) A execução do programa é mais lenta.
2) Estrutura de dados demasiadamente simples;
3) Necessário fornecer o programa fonte ao utilizador;


Referência

[1] Como Funcionam os Compiladores e Interpretadores. Disponível em:
http://www.mat.ua.pt/lap/Teoricas/CompvsInterp.ppt. Acessado em: 20 mai 2008.

sábado, 2 de agosto de 2008

Apresentação Final - Compiladores vs Interpretadores

Aqui está a versão final da nossa apresentação, que foi vista na aula do dia 31/07/2008. Agora dá pra ver quantas vezes quiser, e o melhor de tudo, sem aquele VERDE. :P

segunda-feira, 21 de julho de 2008

Alguns Compiladores...

Nós já falamos muita coisa sobre compiladores e tradutores de linguagens de programação ao longo desses primeiros meses de blog. Mas poucos exemplos de compiladores foram dados.
Agora, eu vou colocar aqui no bytecode uma lista com alguns deles. Como as linguagens mais usadas atualmente são C e C++, vamos colocar alguns dos compiladores mais usados para traduzir essas linguagens.


Compilador Autor Windows UNIX Outros SOs Tipo de Licensa
AMPC Axiomatic Solutions Sdn Bhd Sim Sim Sim Proprietário
C++ Builder CodeGear (Borland) Sim Não DOS Proprietário
C++ Compiler CodeGear (Borland) Sim Não Não Freeware
Comeau C/C++ Comeau Computing Sim Sim Sim Proprietário
CoSy compiler development system ACE Associated Compiler Experts Sim Sim Não Proprietário
Digital Mars Digital Mars Sim Não DOS Proprietário
EDGE ARM C/C++ Mentor Graphics Sim Sim Sim Proprietário
MinGW MinGW Sim Sim Sim Open source
GCC GNU Sim Sim Sim Open source
HP aC++ Hewlett-Packard Não Sim Não Proprietário
Intel C++ Compiler Intel Sim Sim Sim Proprietário
LabWindows/CVI National Instruments Sim Sim Sim Proprietário
Local C compiler Chris Fraser eDaviHanson Sim Sim Sim Open source
Microtec Mentor Graphics
Sim Sim Sim Proprietário
MULTI Green Hills Software Sim Sim Sim Proprietário
Nwcc Nils Weller Sim Sim Sim Open source
Open Watcom Sybase Sim Não Sim Open source


Esses são alguns compiladores mais usados para traduzir C e C++. Claro que há muitos outros compiladores, inclusive para outra linguagens, mas esses são os principais.


tabela retirada e adapata da Wikipédia. Para conferir a lista completa clique aqui.

quarta-feira, 11 de junho de 2008

E Máquina Virtual?

Máquina Virtual, como foi dito na nossa última apresentação, é um tipo de tradutor auxiliar que fica entre o Compilador e o Interpretador.
No caso, o programador escreve o códiogo fonte, numa linguagem de alto nível, e executa um programa (compilador) que irá traduzir o texto para um código binário, de baixo nível. A diferença, nesse caso, está no fato de que esse código binário gerado ainda não é um código que pode ser entendido pela máquina, ele é um código intermediário, e para que o computador possa executá-lo é necessário uma
Máquina Virtual. É a Máquina Virtual que vai traduzir esse código intermediário para um código que o computador consegue entender.
Pra quem está começando agora na área de programação,a utilização de Máquinas Virtuais pode parecer estranho, mas essa técnica trouxe grandes avanços e é cada vez mais comum a sua utilização. A principal vantagem é que com a utilização da Máquina Virtual fica muito fácil executar um mesmo aplicativo em sistemas diferentes. Um código binário criado pelo método tradicional da compilação só pode ser executado no Sistema Operacional onde foi criado. Já um código gerado por uma Máquina Virtual pode ser executado em diversos Sistemas Operacionais diferentes. Java é um bom exemplo: mesmo que um programa em Java seja criado no Windows, ele pode ser rodado também no Linux, Solaris, MacOSX, FreeBSD, sem fazer nenhuma alteração no seu programa. Por outro lado, como já dá pra imaginar, esta outra camada de tradução da Máquina Virtual acaba tornando a execução do programa mais lenta, se comparada com o método tradicional de compilação.

quinta-feira, 5 de junho de 2008

Trabalho: Primeira Parte

Tradutores: Compiladores e Interpretadores

Introdução: Tradutores

Tradutores são programas que têm por finalidade principal realizar a tradução de uma linguagem de programação em outra: a primeira é a linguagem fonte e a segunda é a linguagem objeto, sendo que o resultado do processo de conversão (linguagem objeto) deve ser equivalente, ou seja, apresentar o mesmo propósito do conteúdo da linguagem inicial (linguagem fonte). Dessa forma, verifica-se que o objetivo geral dos tradutores é fazer a comunicação entre o Software – programa escrito em uma linguagem de programação – e o Hardware – equipamento responsável pela execução física das instruções lógicas. Entre os tradutores, os mais conhecidos são os seguintes: Compiladores, Interpretadores, Montadores (“Assemblers”) e Máquina Virtual.

Esquematicamente, tem-se:
A figura já foi colocada por Kelly!

Figura 1 (Esquema geral de funcionamento de um Tradutor)

Definição

Compiladores

Compiladores são tipos de tradutores que possuem uma forma específica de conversão, pois atuam na transformação de uma linguagem de alto nível (próxima do entendimento humano) para uma linguagem de baixo nível – linguagem de máquina (reconhecida pelo hardware do computador).

Os compiladores podem ser assim esquematizados:

A figura já foi colocada por Kelly!

Figura 2 (Esquema específico de um Compilador)

Além de realizar o processo de conversão, os compiladores também são responsáveis, na maioria das vezes, pela execução de outras tarefas que mantém relação com a principal, tais como: detecção de erros e a permissão para a inclusão de comentários. A detecção de erros é implantada através de mecanismos que além de identificar, recupera e elabora relatório de todas as incorreções encontradas no programa, eliminando com isso a necessidade de o mesmo ser submetido ao compilador toda vez que um novo erro ocorrer. A permissão de inclusão de comentários à linguagem fonte, seja por meio da estrutura da sintaxe desta ou recursos do próprio compilador, é uma ferramenta que contribui para uma melhor documentação do programa.

Estrutura dos Compiladores

Os compiladores no que diz respeito a sua estrutura estão divididos em três grandes partes ou módulos funcionais descritos da seguinte forma: Análise Léxica, Análise Sintática e Análise Semântica.

Análise Léxica

É o módulo do compilador que faz a comunicação entre a linguagem fonte e a Análise Sintática. Para isso, tem como tarefa principal a fragmentação do conteúdo fonte, a identificação e a classificação das partes componentes do mesmo (átomos ou tokens). A Análise Léxica utiliza-se de um conjunto de operações, ou melhor, funções para atingir o propósito pelo qual foi elaborada. A seguir são descritas as principais funções da Análise Léxica: Extração e Classificação de Átomos, Eliminação de Delimitadores e Comentários, Conversão Numérica, Tratamento de Identificadores, Tratamento de Palavras Reservadas, Recuperação de Erros e as Funções Auxiliares (Geração de Tabelas de Referências Cruzadas, Definição e Expansão de Macros, Interação com o Sistema Operacional, Controle de Compilação Condicional e Geração e Controle de Listagem).

Extração e Classificação de Átomos

É responsável por mapear o texto fonte em outro formato de texto que será constituído pelos átomos extraídos e classificados a partir daquele. Entre os átomos dessa etapa, encontram-se os seguintes: identificadores, números inteiros sem sinal, números reais, palavras reservadas, cadeias de caracteres (“strings”), operadores, sinais de pontuação, comentários, símbolos compostos e caracteres especiais.

Eliminação de Delimitadores e Comentários

Operação que remove os delimitadores, ou seja, os espaços em branco ou símbolos especiais e os comentários, visto que, não são necessários para a geração de código, embora sejam muito úteis na legibilidade do texto fonte.

Conversão Numérica

Esta função tem como finalidade pegar as cadeias de caracteres que representam números e os números que estão em diversas notações e convertê-los para uma forma em que possam ser manipulados pelas outras operações do compilador.

Tratamento de Identificadores

É a operação que cria uma tabela de identificadores na qual são armazenados, de forma padronizada, os identificadores (em geral, com tamanhos variáveis) e associa os mesmos a índices únicos para que possam ser referenciados de maneira mais simples.

Tratamento de Palavras Reservadas

As palavras reservadas são inicialmente tratadas como identificadores pela maioria dos analisadores léxicos. Em seguida, tais identificadores são comparados ao conjunto de palavras reservadas da linguagem em que o compilador fará a conversão, se os mesmos estiverem neste conjunto, recebem a classificação de palavras reservadas e vão para uma tabela que, em geral, é a mesma em que estão os identificadores.

Recuperação de Erros

Caracteres não identificados e cadeias de caracteres que não obedecem à classificação dada as classes de átomos reconhecidas pelo analisador léxico são identificados como erros léxicos.

Funções Auxiliares

Geração de Tabelas de Referências Cruzadas

Função que armazena em uma tabela os átomos encontrados e a localização destes no texto fonte.

Definição e Expansão de Macros

É a substituição das abreviaturas, que algumas linguagens possibilitam como recurso, pelo texto expandido e livre de definições e chamadas de macro.

Interação com o Sistema Operacional

É a interação entre o analisador léxico e o Sistema Operacional no que se refere ao acesso de arquivos necessários para a análise.

Controle de Compilação Condicional

É o mecanismo que possibilita, através de alguns parâmetros de compilação, a compilação de partes do texto fonte, omitindo-se as demais partes.

Geração e Controle de Listagem

Função que permite ao programador ativar e desativar opções de listagem, de coleta de símbolos em tabelas de referências cruzadas, de geração e impressão de tais tabelas, de impressão de tabelas e símbolos do programa compilador, de tabulação e formatação das saídas impressas do programa fonte.

Análise Sintática

A Análise Sintática tem como objetivo fazer a análise do texto fonte oriundo da Análise Léxica e que está em forma de átomos. Esta etapa atua de forma interativa, pois se comunica com o Analisador Léxico, os processos de geração de código e a Análise Semântica.
Para cumprir sua tarefa, a Análise Sintática possui algumas funções, como as descritas a seguir: Falta fazer o resumo!

Análise Semântica

A última parte ou módulo funcional de um compilador refere-se ao ato final de converter o programa fonte em programa objeto. No entanto, para que o código objeto esteja pronto se faz necessária à participação das ações semânticas. Assim como os outros módulos do compilador (Análise Léxica e Análise Sintática), a Análise Semântica também se subdivide em funções internas e integradas que ao serem realizadas contribuem para resolver as tarefas dessa fase. As principais são: Falta fazer o resumo!

Referência Bibliográfica
NETO, João José. Introdução à compilação. Rio de Janeiro: Livros Técnicos e Científicos, 1987.

terça-feira, 3 de junho de 2008

Apresentação bytecode. - Compiladores vs Interpretadores

E aqui estão os nossos slides que foram usados na apresentação provisória da última quinta-feira, dia 29 de Maio, pra quem quiser olhar com mais calma. Nós estamos pensando em adicionar mais coisas pra apresentação final. Aguardem! :)

domingo, 1 de junho de 2008

Mostrando o pensamento lógico de um compilador

Através do uso de metalinguagens é possível obter-se, de modo suficientemente rigoroso uma boa definição da linguagem de programação cujo compilador se deseja construir. Seja qual for a técnica empregada para tal finalidade, o resultado é sempre um programa a ser executado no computador.

Sendo um programa, o tradutor(compilador) deverá ser expresso em alguma linguagem de programçaõ disponível, para que seja possível implamtá-lo em alguma máquina existente e portanto algum compilador pode ser suposto existente para permitir a primeira tradução de um compilador para a linguagem que esta sendo desenvolvida. Este deverá, portanto, ser escrito na linguagem de programação que o compilador disponível seja capaz de traduzir.

Tem-se duas questões a solucionar: para qual máquina o compilador final deverá gerar código, e em que linguagem tal compilador deverá ser redigido.

Seja L a linguagem a ser compilada para a máquina M, ou seja, deseja-se construir um compilador da linguagem L que gere um código-objeto que seja executável na máquina M.

Com estas hipóteses, descreve-se a seguir a técnica de obtenção de compiladores ditos 'auto-compiláveis' através do método de 'bootstrapping'. Sendo que um compilador é chamado 'auto-compilável' quando a linguagem em que for desenvolvido (L') é a própria linguagem L que o compilador deve ser capaz de traduzir.

O método de 'bootstrapping' permite obter a partir de praticamente nenhuma infraestrutura uma primeira versão de um compilador auto-compilável a ser utilizado posteriormente para melhorar e aperfeiçoar, em versão subsequente, o compilador original. A técnica mencionada pode ser detalhada como segue:

  1. Escreve-se na linguagem L' um compilador capaz de traduzir a linguagem L para linguagem de máquina M' (nesta primeira versão, pode-se implementar apenas os recursos de L que sejam indispensáveis a construção deste primeiro compilador). Obtém-se assim na máquina M' um compilador auto-resistente para a linguagem L, que gera código para a própria máquina M'. Caso as linguagens L e M sejam a mesma, então o compilador obtido no passo 1 estaria disponível a priori, sendo assim desnecessário refazê-lo.
  2. De posse do compilador da linguagem L para a máquina M', reescreve-se o mesmo na própria linguagem M, eliminando-se deste modo linguagens L' diferentes, e de modo que o código-objeto que o novo compilador deve produzir se apresente na linguagem da máquina M. Utilizando-se o compilador L disponível, compila-se o novo programa obtido, obtendo-se desta maneira, para ser executado na máquina M', um compilador cruzado para a linguagem L, auto-compilável e que gera código para a máquina M. Se o compilador cruzado é o objewtivo final do desenvolvimento, eventuais aperfeiçoamentos do compilador podem ser efetuados, repetindo-se este passo até que se obtenha a versão definitiva do mesmo.
  3. Desejamos um compilador auto-residente, e considerando-se que o compilador obtido no passo 2 foi escrito na própria linguagem que é capaz de traduzir, ou seja, que é auto-compilável, pode-se utilizá-lo na máquina M', para compilar seu próprio texto-fonte. O programa-objeto assim obtido será executável na máquina M', e será um programa equivalente ao compilador que o produziu. Em outras palavras, o programa obtido será de linguagem L, capaz de traduzi-lo para a linguagem da máquina M, e que pode ser executado diretamente na máquina M, ou seja, produziu-se em M' um compilador auto-residente e auto-compilável da linguagem L para a máquina M.
  4. Transporta-se o compilador obtido para a máquina M, onde se pode, se assim for conviniente prosseguir o desenvolvimento do compilador e da linguagem, aperfeiçoando-se o programa obtido até que apresente todas as características desejadas.

Se a máquina M não comporta tal desenvolvimento, pode-se alterar o programa obtido, retornando-se ao terceiro passo tantas vezes forem necessárias , até que se obtenha o compilador desejado que é então transportado definitivamente para a máquina M. A figura abaixo mostra uma notação 'bootstrapping':

Um texto, denominado texto-fonte, é submetido ao programa representado no polígono, pela extremidade esquerda da figura.

No braço esquerdo do polígono esta indicada a linguagem em que X está escrito( linguagem fonte). O programa compilador, escrito na linguagem de desenvolvimento endicada na extremidade inferior do polígono, traduz o texto-fonte para a linguagem-objeto, indicada na extremidade direita do polígono, gerando um texto Y equivalente, denotado na linguagem-objeto.

Agora vejamos o processo de 'bootstrapping' que foi descrito anteriormente através da figura abaixo:


Assim depois do processamento chegamos no código objeto através do pensamento lógico que o compilador utiliza.

Diferenças de nomenclatura

Um tradutor efetua a conversão entre duas linguagens, sendo o primeiro texto chamado de 'código fonte' e o transformado em 'código objeto' . O tradutor pode converter por exemplo a linguagem do algoritmo 'pascal' em linguagem binária, java, fortran entre outros. Veja a figura abaixo:

De maneira geral, os tradutores efetuam portanto a conversão de textos redigidos em uma linguagem para formas equivalentes redigidas em outra linguagem. Se a primeira linguagem for uma linguagem de alto nível, o tradutor receberá o nome de compilador. Veja a figura:

Do ponto de vista da linguagem-objeto, esta também pode ser ou não uma linguagem de alto nível. É possível, por exemplo, que o texto-fonte esteja redigido em 'FORTRAN', e que um tradutor aceite tal texto e o converta para alguma linguagem de baixo nível (linguagem de montagem, ou linguagem de máquina) ou então para alguma outra linguagem de alto nível, tal como 'PASCAL' ou 'BASIC'. Um tradutor que efetue conversões entre duas linguagens de alto nível é denominado 'filtro', se a linguagem objeto for muito semelhante à linguagem fonte. Veja a figura a seguir:


Muitas vezes, programas que efetuam traduções entre dois dialetos de mesma linguagem, ou que permitem converter para uma forma padronizada um texto que inclua extensões de uma linguagem disponível, são denominados 'pré-processadores'. Basicamente, a função dos pr-e-processadores, neste caso, consiste na eliminação de construções de nível mais alto que o da linguagem-base, e na correspondente inserção de textos equivalentes, compostos exclusivamente de construções da linguagem-base. Veja a figura abaixo:



Outro exemplo de aplicação de pré-processadores é no processamento da definição e utilização de macros em linguagem de alto nível. Em muitos casos, os compiladores destas linguagens não oferecem ao usuário tais recursos, sendo as macros manipuladas externamente, por um pré-processador encarregado de manipular e eliminar tais construções do texto-fonte, para que possa ser traduzido pelo compilador.

domingo, 18 de maio de 2008

Pessoal, aguarde mais um pouco!

Ainda estou na metade do meu resumo para o trabalho. Logo, ainda vou precisar de mais alguns dias para postá-lo. Provavelmente, vou conseguir quinta-feira.

Valeu, e até a próxima...

segunda-feira, 12 de maio de 2008

Estrutura de um tradutor: Síntese

Agora que nós já explicamos a etapa da Análise, na qual o compilador lê as sequências de caracteres e identifica cada unidade léxica (os tokens) e verifica se fazem sentido, vamos falar sobra a Síntese que é onde o compilador finalmente gera o código objeto, numa linguagem de baixo nível.
Assim, como a Análise, a Síntese também está subdividida em fases, são elas: a Geração de Código Intermediário, Otimização de Código e, enfim, a Geração de Código Obejto. Vamos descrevê-las individualmente.

Geração de Código Intermediário: Essa fase utiliza a representação interna produzida pelo Analisador Sintático e gera como saída um código, que pode ser o código objeto final, mas geralmente contitui-se de um código intermediário. Essa fase é bem útil, pois possibilita a otimização de código intermediário, de modo a obter-se o código objeto final mais eficiente. Além de resolver, gradualmente, as dificuldades da passagem de código fonte para o objeto (alto nível para baixo nível), já que o código fonte representa inúmeras instruções elementares numa linguagem de baixo nível.

Otimizção de Código: Essa fase objetiva a otimização do código intermediário em termos de velocidade de execução e espaço de memória.

Geração de Código Objeto: É a fase mais difícil, pos requer uma seleção cuidadosa das intruções e dos registradores da máquina alvo a fim de produzir um código objeto eficiente. Existem tradutores que possuem mais uma fase para realizar a otimização do código objeto.

Adaptado do Livro "Implementação de Linguagens de Programação: Compiladores de Ana Maria de Alencar Price e Simão Sirineo Toscani"

sábado, 10 de maio de 2008

Estrutura de um tradutor: Análise

Em geral, os tradutores de linguagens de programação são programas bastantes complexos. Independentemente da linguagem a ser traduzida ou do programa objeto a ser gerado, os tradutores, de um modo geral compõe-se de funções padronizadas, que compreendem a analise de um programa fonte e a posterior sintese para a derivação do código objeto.

O processo de tradução é estruturado em fases, no qual cada subfase se comunica com a seguinte através de uma linguagem intermediária adequada. Suas fases são: Analise e Síntese.

A fase referente a Análise é subdividida em Análise Léxica, Análise Sintática e Análise Semântica.

O objetivo principal da Análise Léxica é identificar sequências de caracteres que constituem unidades léxicas (“tokens”). O analisador léxico lê, caractere a caractere, o texto fonte, verificando se os caracteres lidos pertecem ao alfabeto da linguagem, identificando tokens, e desprezando comentários e brancos desnecessários. Além de reconhecer os simbolos léxicos, o analisador também realiza outras funções, como armazenar alguns desses símbolos em tabelas internas e indicar a ocorrencia de erros léxicos.

A sequencia de tokens produzida pelo analisador léxico é utilizada como entrada pelo módulo seguinte do compilador, o analisador sintático. É interessante observar que o mesmo programa fonte é visto pelos analisadores léxico e sintatico como sentenças diferentes. Para o analisador léxico o programa fonte é uma sequencia de palavras de uma linguagem regular. Para o analisador sintatico, essa sequencia de tokens constitui uma sentença de linguagem livre de contexto (permite expressar construções mais sofisticadas).

Os simbolos léxicos (tokens) constituem uma linguagem regular, que são as mais simples. No contexto de tradução de linguagem de programação, as linguagens são usualmente apresentadas através de gramaticas ou algoritmos (automatos) que as reconhecem.

A fase da Análise Sintática tem por função verificar se a estrutura gramatical do programa está correta (isto é, se essa estrutura foi formada usando as regras gramaticais da linguagem). A Analise Semântica irá verificar se as estruturas do programa irão fazer sentido durante a execução.

O Analisador Sintático identifica seqüências de símbolos que constituem estruturas sintáticas (cadeia de tokens) do programa fonte. Outra função dos reconhecedores sintáticos é a detecção de erros de sintaxe indentificando clara e objetivamente a posição e o tipo de erro ocorrido. Mesmo que erros tenham sido encontrados, o Analisador Sintatico deve tentar recuperá-los prosseguindo a análise do texto restante.

Muitas vezes, o Analisador Sintático opera conjuntamente com o Analisador Semântico, cuja principal atividade é determinar se as estruturas sintaticas analisadas fazem sentido, ou seja, verificar se um identificador declarado como váriavel é usado como tal; Se existe compatibilidade entre os operandos e operadores em expressões; etc.


Adaptado do livro: Implementação de Linguagens de Programação: Compiladores, de Ana Maria de Alencar Price e Simão Sirineo Toscani

quinta-feira, 8 de maio de 2008

O modelo de compilação de análise e síntese I

Depois das várias explicações já dadas, está na hora de um maior aprofundamento de como ocorre o processo de compilação. Nela existem duas partes: a análise e a síntese. Porém para o seu melhor entendimento, teremos que aprender mais alguns conceitos. São eles os algoritmos e as estruturas de dados.
Algoritmos: Para resolver um problema no computador é necessário que seja primeiramente encontrada uma maneira de descrever este problema de uma forma clara e precisa. É preciso que encontremos uma seqüência de passos que permitam que o problema possa ser resolvido de maneira automática e repetitiva. Esta seqüência de passos é chamada de algoritmo.
Sendo assim, algoritmo é um conjunto de instruções finita, não ambigua e com todos os passos definitos responsável por solucionar um problema.

Ele pode ser escrito em pseudo linguagem ou por meio de fluxogramas. Por pseudo linguagem, os algoritmos são representados em uma linguagem que esteja o mais próximo possível de uma linguagem de programação de computadores de alto nível, mas evitando definir regras de construção gramatical muito rígidas. A idéia é usar as vantagens do emprego da linguagem natural, mas restringindo o escopo, o objetivo da linguagem. Normalmente estas linguagens são versões ultra reduzidas de linguagens de alto nível do tipo Pascal ou C. Por fluxogramas várias formas geométricas são utilizadas para descrever cada uma das possíveis ações durante a execução do algoritmos.
Exemplo:

Estrutura de dados: é o nome dado a organização de dados e algoritmos de forma coerente e racional de modo a otimizar, melhorar o seu uso. De acordo com o modo como um conjunto de dados são organizados e como as operações que são efetuadas sobre estes dados pode-se solucionar de forma simples problemas extremamente complexos. Existem diversos modelos de estruturas de dados, e novos modelos são criados constantemente, pois acompanham também a evolução dos algoritmos e das linguagens de programação, porém iremos nos prender a uma estrutura clássica que será citada com frequência daqui em diante.
Essa estrutura é chamada de árvore e ela se caracteriza pela relação de hierarquia entre os elementos que a compõem. O exemplo abaixo é uma representação simples de uma árvore binária, caracterizada pelo elemento distinto (bola de cor vermelha) e sua bifurcações chamadas sub-árvore direita e sub-árvore esquerda (bola de cor azul).

segunda-feira, 5 de maio de 2008

Imagens esquemáticas de compiladores e interpretadores.

Tá, nós já demos várias definições de compiladores e interpretadores e explicamos algumas diferenças entre eles aqui no blog. Mas vamos continuar a explicar, para que todo mundo entenda melhor.

Os Compiladores são tradutores que mapeiam programas escritos em linguagem de alto nível para programas equivalentes em linguagem de máquina. A execução de um programa escrito em linguagem de alto níve
l é, basicamente, um processo de dois passos: primeiro ocorre a conversão do programa fonte para o programa objeto equivalente, esse intervale de tem é chamado de tempo de compilação; Depois, o programa objeto é executado no intervalo de tempo chamado de tempo de execução.

Já os interpretadores, são processadores que aceitam como entrada o código intermediário de um programa anteriormente traduzido e produzem o "efeito de execução" do algoritmo original, sem porém mapeá-lo para a linguagem de máquina. Ou seja, a interpretação ocorre no tempo de execução, não sendo gerado um programa objeto.


Há alguns interpretadores que não utilizam um código intermediário, trabalhando diretamente sobre o programa fonte cada vez que esse deve ser executado. Mas esse enfoque consome muito tempo. Uma estratégia mais eficiente é a aplicação de técnicas de compilação para traduzir o programa fonte para uma forma intermediária que é, então, interpretada.


Adaptado do livro "Implementação de Linguagens de Programação: Compiladores", de Ana Maria de Alencar Price e Simão Sirineo Toscani.

sexta-feira, 2 de maio de 2008

Atualização do compilador Free Pascal, com várias melhorias!!!

Recentemente o compilador Free Pascal (FPC, "Free Pascal Compiler") chegou à sua versão 2.2.0 . Ele é um compilador open source para a linguagem Pascal, iniciado em 1993, hoje um dos grandes e mais sofisticados compiladores. Multiplataforma, visa a escrita do código uma única vez para compilação para várias plataformas, como Windows, Linux e Mac (claro, desde que recursos específicos de alguma plataforma não sejam utilizados). Cada vez mais programadores se utilizam do FPC, inclusive com o apoio do Lazarus, uma interface para o compilador, com facilidades para geração de aplicações gráficas.Na versão 2.2.0 várias melhorias foram conquistadas, destacando:

*Suporte às arquiteturas PowerPC/64 e ARM;

*Suporte às plataformas Windows x64, Windows CE, Mac OS X/Intel, Game Boy Advance e Nintendo DS;

*Linkador mais rápido para o ambiente Windows (uma das maiores queixas do FPC pelos programadores Windows era a lentíssima velocidade de compilação, realmente melhorada agora);

*Suporte para preenchimento automático de vários valores para variáveis durante os testes (debug), para facilitar a identificação de valores não inicializados;

*Suporte para delegação de interface (experimental, ainda) e um gerenciador de pacotes;

*Várias outras melhorias, como melhor suporte a variáveis, suporte a arquivos com múltiplos recursos (resources), widestrings compatíveis com objetos COM/OLE no Windows, etc.

adaptado do site Guia do Hardware.

quinta-feira, 1 de maio de 2008

O que são Compiladores e Interpretadores e qual a diferença básica entre eles

Pessoal, em primeiro lugar, devemos observar que os compiladores e interpretadores são programas que têm por objetivo traduzir um outro programa (escrito em linguagem de alto nível - código fonte - para linguagem de baixo nível - linguagem de máquina, gerando, assim, o código objeto), no entanto uma diferença básica deve ser notada: eles diferem na forma de traduzir um programa, pois os interpretadores traduzem e executam cada linha de código sequencialmente enquanto que os compiladores traduzem todas as linhas de código para, enfim, poder executar um programa.

valeu, até a próxima...

terça-feira, 29 de abril de 2008

Breve introdução sobre interpretadores.

O interpretador é um software que contém uma linguagem de programação embutida que tem por objetivo interpretar o programa que uma pessoa faz sem precisar compilá-lo, ou seja, diferentemente do compilador o interpretador não precisa gerar um programa executável. Logo, ele não gera código objeto e sim, a partir de um programa fonte, escrito em linguagem de alto nível, o interpretador, no momento de execução do programa, traduz cada instrução e a executa em seguida. Mas a principal desvantagem do interpretador em relação ao compilador é que o programa executado no interpretador é muito mais lento.

sábado, 26 de abril de 2008

Breve introdução sobre compiladores.

Um compilador é um programa que, a partir de um código escrito em uma linguagem de computador, chamada de código fonte, cria um programa semanticamente equivalente porém escrito em uma outra linguagem, o código objeto. Ou seja, serve para traduzir uma linguagem de computador para outra.


Um compilador é um dos dois tipos mais gerais de tradutores, sendo um interpretador, o segundo tipo.


A razão mais comum para querer traduzir o código fonte é para criar um programa executável. Normalmente, ele é escrito em uma linguagem de programação de alto nível, com grande capacidade de abstração, e o código objeto é escrito em uma linguagem de baixo nível, como uma sequência de instruções a ser executada pelo processador. Antigamente, ele era muito utilizado para traduzir um programa de uma linguagem textual facilmente entendida por um ser humano para uma linguagem de máquina, específica para um processador e/ou sistema operacional. Atualmente, porém, são comuns compiladores que geram código para uma máquina virtual que é, depois, interpretada por um interpretador .



AdAdaptado da Wikipédia.


sexta-feira, 25 de abril de 2008

Assine o nosso RSS Feed!

Acabei de criar um link pra quem quiser assinar o nosso RSS feed e ficar ligado nos nossos últimos posts. É uma boa idéia se você quiser saber das últimas notícias relacionadas a TI e a Softwares, e se você quiser entender melhor os Compiladores e os Interpretadores. :)
Para assinar é muito fácil. Basta clicar no link que está no final da barra de navegação à esquerda e assinar usando o reader que você preferir. Ou, se você achar melhor, pode ir direto no link do feed (http://feeds.feedburner.com/bytecode171) e inscrevê-lo direto no seu navegador, como na barra de favoritos do Firefox por exemplo.

quinta-feira, 24 de abril de 2008

Conceitos básicos para o entendimento de compiladores e interpretadores.

Para que haja um melhor entendimento sobre compiladores e interpretadores é necessário primeiro que tenhamos o conhecimento de alguns conceitos básicos. São eles:

- Linguagem de programação: É um conjunto finito de símbolos com os quais se escrevem programas de computador. Há várias classificações dadas as linguagens de programação, porém citaremos três tipos delas, pois são as mais utilizadas:


1. Linguagem de alto nível: É a linguagem que mais se aproxima do ser humano. Exemplos: Pascal, C , COBOL, SQL.


2. Linguagem de nível intermédiário: Fica em um nível intérmediário entre a linguagem de alto nível e a linguagem de baixo nível. Exemplo: Assembly do Pentium.


3. Linguagem de baixo nível: É o código que o computador executa diretamente, é conhecida como linguagem binária (composta por 0’s e 1’s).

- Código fonte:
É um conjunto de palavras escritas de forma ordenada composto pelas instruções de uma das linguagens de programação. Como exemplo, temos abaixo um código fonte de um programa em linguagem de programação C.

Normalmente, o código fonte é escrito em uma linguagem de programação de alto nível, com grande capacidade de abstração, e o código objeto é escrito em uma linguagem de baixo nível, como uma sequência de instruções a ser executada pelo processador, porém tais informações só são processadas quando o código fonte è compilado em código objeto. Daí a necessidade de um tradutor , responsável por traduzir um tipo de linguagem, código, para outro. Existem dois tipos, mais comuns, de tradutores: os compiladores e os interpretadores, os quais explicaremos de forma detalhada mais adiante.

Bytecode

Olá a todos, em breve postaremos sobre o nosso assunto que está relacionado a Softwares e sobre outros temas que abordem computação de uma maneira mais ampla e fácil. Peço que esperem pacientemente e aguardem as novidades.