7
Linguagem de programação Uma linguagem de programação é um método padronizado para comunicar instruções para um computador. 1 É um conjunto de regras sintácticas e semânticas usadas para definir um programa de computador. 2 Nota 1 Permite que um programador especifique precisamente sobre quais dados um computador vai actuar, como estes dados serão armazenados ou transmitidos e quais acções devem ser tomadas sob várias circunstâncias. Linguagens de programação podem ser usadas para expressar algoritmos com precisão. O conjunto de palavras (lexemas classificados em tokens), compostos de acordo com essas regras, constituem o código fonte de um software. 3 Esse código fonte é depois traduzido para código de máquina, que é executado pelo processador. 3 Existem dois tipos de linguagens de programação: as de baixo nível e as de alto nível. Os computadores interpretam tudo como números em base binária, ou seja, só entendem zero e um. As linguagens de baixo nível são interpretadas directamente pelo computador, tendo um resultado rápido, porém é muito difícil e incômodo se trabalhar com elas. Exemplos de linguagens de baixo nível são a linguagem binária e a linguagem Assembly. Exemplo de código em Assembly: MOV r0, #0C ;load base address of string into r0 LOAD: MOV r1,(r0) ;load contents into r1 CALL PRINT ; call a print routine to print the character in r1 INC r0 ;point to next character JMP LOAD ;load next character Quando programamos em uma linguagem de programação de alto nível primeiramente criamos um arquivo de texto comum contendo a lógica do programa, ou seja, é onde falamos ao computador como deve ser feito o que queremos. Este arquivo de texto é chamado de código-fonte, cada palavra de ordem

Linguagem de programação

Embed Size (px)

Citation preview

Page 1: Linguagem de programação

Linguagem de programação

Uma linguagem de programação é um método padronizado para comunicar instruções para um computador.1 É um conjunto de regras sintácticas e semânticas usadas para definir um programa de computador.2 Nota

1 Permite que um programador especifique precisamente sobre quais dados um computador vai actuar, como estes dados serão armazenados ou transmitidos e quais acções devem ser tomadas sob várias circunstâncias. Linguagens de programação podem ser usadas para expressar algoritmos com precisão.

O conjunto de palavras (lexemas classificados em tokens), compostos de acordo com essas regras, constituem o código fonte de um software.3 Esse código fonte é depois traduzido para código de máquina, que é executado pelo processador.3

Existem dois tipos de linguagens de programação: as de baixo nível e as de alto nível. Os computadores interpretam tudo como números em base binária, ou seja, só entendem zero e um. As linguagens de baixo nível são interpretadas directamente pelo computador, tendo um resultado rápido, porém é muito difícil e incômodo se trabalhar com elas. Exemplos de linguagens de baixo nível são a linguagem binária e a linguagem Assembly.

Exemplo de código em Assembly:

MOV r0, #0C ;load base address of string into r0LOAD: MOV r1,(r0) ;load contents into r1CALL PRINT ; call a print routine to print the character in r1INC r0 ;point to next characterJMP LOAD ;load next character

Quando programamos em uma linguagem de programação de alto nível primeiramente criamos um arquivo de texto comum contendo a lógica do programa, ou seja, é onde falamos ao computador como deve ser feito o que queremos. Este arquivo de texto é chamado de código-fonte, cada palavra de ordem dentro do código-fonte é chamada de instrução. Após criarmos o código-fonte devemos traduzir este arquivo para linguagem binária usando o compilador correspondente com a linguagem na qual estamos programando. O compilador irá gerar um segundo arquivo que chamamos de

Page 2: Linguagem de programação

executável ou programa, este arquivo gerado é interpretado directamente pelo computador.

COMPILADORES

Um compilador é um programa de sistema que traduz um programa descrito em uma linguagem de alto nível para um programa equivalente em código de máquina para um processador. Em geral, um compilador não produz directamente o código de máquina mas sim um programa em linguagem simbólica (assembly) semanticamente equivalente ao programa em linguagem de alto nível. O programa em linguagem simbólica é então traduzido para o programa em linguagem de máquina através de montadores.

O compilador é um dos dois tipos mais gerais de tradutores, juntamente com o interpretador.

Para apresentar um exemplo das actividades que um compilador deve desempenhar, considere o seguinte trecho de um programa em C:

Para o compilador, este segmento nada mais é do que uma sequência de caracteres em um arquivo texto. O primeiro passo da análise é reconhecer que agrupamentos de caracteres têm significado para o programa -- por exemplo, saber que int é uma palavra-chave da linguagem e que a e b serão elementos individuais neste programa. Posteriormente, o compilador deve reconhecer que a sequência int a corresponde a uma declaração de uma variável inteira cujo identificador recebeu o nome a.

As regras de formação de elementos e frases válidas de uma linguagem são expressos na gramática da linguagem. O processo de reconhecer os comandos de uma gramática é conhecido como reconhecimento de sentenças. Gramáticas e reconhecimento de sentenças serão estudados na Seção 3.1.

Page 3: Linguagem de programação

A aplicação do conceito de reconhecimento de sentenças para agrupar as sequências de caracteres em ``palavras'' é a análise léxica. Os elementos reconhecidos nessa primeira etapa da compilação são denominados itens léxicos ou tokens. Para o exemplo acima, a seguinte lista de tokens seria reconhecida pelo compilador:

Para desempenhar a análise léxica, o compilador deve ter conhecimento de quais são os tokens válidos da linguagem, assim como suas palavras-chaves e regras para formação de identificadores. Por exemplo, a declaração

int 1var;

deve resultar em erro nessa etapa da análise, pois 1var não é uma constante ou identificador válido. Se um programa contendo esta declaração fosse compilado usando o compilador gcc, por exemplo, a esta linha seria associado o erro ``nondigits in number and not hexadecimal'', mostrando que o compilador esperava que 1var fosse um número, já que inicia com um algarismo. A análise léxica será estudada na Seção 3.2.

O segundo passo da análise desempenhado pelo compilador é a análise sintática, onde a estrutura do programa é analisada a partir do agrupamento de tokens. Nesta etapa, que será estudada na Seção 3.4, o compilador deverá reconhecer que a seqüência de tokens obtida do segmento de código apresentado no início da seção corresponde a quatro comandos, sendo o primeiro deles um comando de declaração de variáveis e os três restantes de atribuição. Adicionalmente, deverá reconhecer que o último dos comandos de atribuição contém subexpressões que deverão ser avaliadas para completar a atribuição na execução do programa.

Para que este passo possa ser realizado pelo compilador, ele deve ter conhecimento de como são formados os comandos válidos da linguagem. Por exemplo, um comando de declaração de variáveis como

int int x;

Page 4: Linguagem de programação

deve resultar em erro nesta etapa -- o compilador gcc indicaria o erro com uma mensagem ``two or more data types in declaration of `x' ''.

Após realizada a análise, na fase de síntese o compilador deverá gerar o código em linguagem simbólica equivalente ao código analisado. Por exemplo, para um compilador C gerando código para a linguagem simbólica do processador 68000 os seguintes mapeamentos poderiam estar preparados:

onde L e R seriam substituídos pelo compilador pelas variáveis usadas internamente na síntese do programa.

Na verdade, compiladores não trabalham diretamente com o código de um processador específico. Normalmente o código gerado nessa fase é expresso em alguma linguagem intermediária, próxima do assembly mas independente de processador, que depois pode ser mapeada para diversos processadores distintos.

Este é um código correto sob o ponto de vista de que as tarefas executadas correspondem semanticamente ao programa C original. Entretanto, uma simples observação demonstra que o código gerado poderia ser muito mais sucinto através da eliminação de alguns comandos desnecessários

A melhoria do código gerado pelo compilador é a fase final da compilação, que é a otimização de código.

Em programas mais complexos, há muitas outras situações onde o código gerado automaticamente pelo compilador pode ser melhorado. O objetivo da fase de otimização é detectar tais situações automaticamente e aplicar estratégias heurísticas para permitir a melhoria desse código.

DEPURADOR

Page 5: Linguagem de programação

Um depurador (em inglês: debugger) é um programa de computador usado para testar outros programas e fazer sua depuração, que consiste em encontrar os defeitosdo programa.

O código a ser examinado pode estar sendo executado sob uma máquina virtual, uma técnica que permite total flexibilidade de acesso aos estados da máquina virtual, que também é software. Mas os processadores modernos têm muitos recursos, que também facilitam o acesso a instruções do programa. Por exemplo, desde há muito tempo é possível interromper a execução de instruções do programa depurado em qualquer ponto e examinar o conteúdo de suas variáveis.

Quando o programa aborta, o depurador mostra a posição no código fonte original, se for um depurador de código fonte, ou um depurador simbólico. Caso seja um depurador de linguagem de máquina, ele mostra a linha onde ocorreu o problema através de desmontagem. Um programa é abortado quando ele usa uma instrução não disponível (inválida) na CPU, quando tenta acessar memória inexistente ou não disponível para ele, bloqueada pelo mecanismo de proteção. Ou seja: quando tenta acessar, devido a defeito ou não, recursos indisponíveis para ele. Em geral, o sistema operacional é que faz com que o programa aborte.

Em geral, os depuradores também oferecem funcionalidades mais sofisticadas, como: a execução passo-a-passo de um programa; a suspensão do programa para examinar seu estado atual, em pontos predefinidos, chamados pontos de parada; o acompanhamento do valor de variáveis, que podem ser usadas inclusive para gerar uma suspensão, ou ativar um ponto de parada.

Apesar da importância do uso de depuradores, é bom lembrar que um programa pode se comportar de forma diferente quando executando sob um depurador. O bom humor leva este problema a ser chamado deHeisenbug na literatura especializada, em alusão à incerteza de Heisenberg. Por exemplo, um depurador alterará a velocidade de processamento do programa, o que tanto fará surgir novos problemas

Page 6: Linguagem de programação

desincronização, quanto poderá mascarar aqueles já existentes. Por esta razão, mesmo os melhores depuradores existentes podem não ser eficazes na solução dos problemas de sincronização muitas vezes presentes em sistemas multitarefa ou distribuídos.

É interessante notar que as mesmas funcionalidades que tornam um depurador útil para o desenvolvedor que precisa eliminar defeitos, podem ser usadas por quem queira quebrar proteção contra cópia, ou fazer um crack de software com alguma limitação de uso.

Muitos programadores—em particular aqueles habituados ao desenvolvimento em ambientes de desenvolvimento integrado, não gostam ou têm dificuldade de trabalhar com depuradores com recursos limitados de interacção, como é o caso de depuradores que oferecem apenas uma interface de linha de comando. Em vez disso, preferem usar front-ends que acrescentem funções de visualização e interacção mais sofisticadas e flexíveis, principalmente através de interface gráfica com o usuário.

Cada linguagem de programação foi criada com algum objetivo, como por exemplo, facilidade de escrita, facilidade de manutenção, melhora da performance do dispositivo, etc.

Quando falamos em níveis, podemos dizer que uma linguagem de alto nível está muito mais próxima do programador do que do dispositivo, ou seja, é uma linguagem muito mais intuitiva. Existem linguagens onde é feito um diagrama e esse diagrama que nada mais é do que um desenho é convertido para uma linguagem de programação pré-seleccionada. Essa é uma linguagem bem mais amigável ao programador devido à sua facilidade de entendimento. Um exemplo de linguagem de alto nível é a linguagem SDL (Specification Design Language).

Page 7: Linguagem de programação