O que exatamente é uma linguagem de programação? O que nos permite escrever em tal idioma?

26

Tudo bem, eu sou novo em programação e admito que essa é uma pergunta bastante abstrata.

A linguagem natural que falamos todos os dias existe porque as pessoas podem se entender. Como os computadores podem entender meu código escrito em um determinado idioma?

Digamos que o Sr. A crie um novo idioma. Como isso é aceito pelas máquinas? O criador deve se comunicar com a máquina usando o idioma da máquina para criar um novo idioma? O que garante que podemos escrever em um idioma enquanto somos entendidos corretamente pela máquina?

Erica Xu
fonte
1
O que nos permite escrever em tal idioma? - "Cérebros: a nova maravilha!" Spike Milligan.
Stephen C
6
Um pouco amplo, mas uma boa pergunta, no entanto. Muitas pessoas simplesmente usam idiomas sem se perguntarem como eles funcionam. Que bom que você está curioso.
riwalk
4
Esta é uma pergunta de referência geral , fácil e trivialmente respondida pela Wikipedia .
Aaronaught

Respostas:

39

Você pode resumir praticamente toda a resposta ao seu conjunto de perguntas com a palavra "compilador" . Um compilador é um programa especial cuja função é tomar o código-fonte como entrada, aplicar regras de linguagem determinadas pelo designer de idiomas para descobrir o que o código significa e produzir código com o mesmo significado em outro idioma como saída. Geralmente, é um código de máquina ou alguma forma de bytecode (o "código de máquina" para máquinas virtuais), embora existam compiladores especializados que convertem o código em outros idiomas de alto nível. Eles estão além do escopo desta questão, no entanto.

Nem todos os idiomas têm um compilador. Alguns deles têm intérprete , que faz as mesmas coisas que um compilador, exceto que, em vez de produzir código de máquina após determinar o que o programa significa, ele simplesmente executa o programa imediatamente. Mas os princípios básicos de analisar (ler) o código e determinar o que ele significa são os mesmos.

Responder de maneira mais aprofundada do que isso entraria na teoria dos compiladores, que é um assunto muito amplo. Se você estiver interessado no tópico, comece lendo o artigo da Wikipedia para "compilador" e verifique os links dele. Se você tiver perguntas específicas, não hesite em perguntar aqui.

Mason Wheeler
fonte
11
+1 - Eu também acrescentaria que, ao escrever um novo idioma, você deve escrever o compilador ou intérprete em outro idioma. Versões posteriores do compilador ou intérprete podem ser escritas em versões anteriores do idioma e compiladas com o compilador mais antigo. O primeiro montador foi escrito em código de máquina. O primeiro compilador C foi escrito em assembly (provavelmente) etc.
Scott Whitlock
1
Eu mudaria a definição de compilador. Nem todos emitem código de máquina. Especialmente hoje em dia, com tantos compiladores emitindo "código intermediário", como o MSIL. Existem até compiladores que emitem JavaScript!
Neil N
3
Eu hesitaria em afirmar que os compiladores produzem código de máquina por definição, mesmo quando explicam para um iniciante. É como dizer que funções retornam números reais, uma simplificação sem sentido. Toda a construção do compilador é mantida ao produzir código que não é para um computador realmente construído a partir de silício, mas apenas definido de forma abstrata (seja uma VM ou uma linguagem de alto nível; há uma razão para dizer que o padrão C define uma máquina abstrata e existe é um compilador do IR LLVM de nível muito baixo para obter o JavaScript). Os iniciantes precisam entender isso, quanto mais cedo melhor.
2
A simplificação usada pela maioria dos livros do compilador é que um compilador aplica regras de idioma para converter de um idioma de origem para um idioma de destino como saída. (Não é incomum compilar com C, por exemplo, especialmente para um curso introdutório).
JasonTrue
4
@ delnan, ainda mais - toda linguagem é um código de máquina , para sua própria máquina abstrata. Não importa quão alto seja o idioma.
SK-logic,
11

Como você apontou, os humanos se comunicam através de um idioma "natural", como inglês, francês, alemão, entre si. Eles são chamados naturais porque nós os adquirimos naturalmente, em vez de inventá-los intencionalmente (o esperanto é uma exceção).

Uma linguagem formal é aquela inventada para algum propósito ou outro. Uma linguagem de programação como C, por exemplo, é uma linguagem formal inventada com a finalidade de programar computadores.

Todos os idiomas podem ser descritos usando uma gramática. Uma hierarquia de gramáticas foi descrita por Noam Chomsky em 1956. Consiste nos seguintes níveis:

Gramáticas tipo 0 (gramáticas irrestritas). Eles são os mais gerais e são equivalentes a uma Máquina de Turing. Como tal, o problema de decidir se uma determinada sequência faz parte de uma gramática irrestrita é indecidível.

Gramáticas tipo 1 (gramáticas sensíveis ao contexto). Quase todos os idiomas naturais, como o inglês, são sensíveis ao contexto. Um exemplo de sensibilidade ao contexto em inglês são as duas frases: "O tempo voa como uma flecha". e "A fruta voa como uma banana". Em geral, é difícil para os computadores entenderem linguagens sensíveis ao contexto.

Gramáticas tipo 2 (sem contexto). Linguagens sem contexto são a base teórica para a sintaxe da maioria das linguagens de programação.

Gramáticas tipo 3 (gramáticas regulares). A família de idiomas regulares pode ser obtida por expressões regulares. Linguagens regulares são comumente usadas para definir padrões de pesquisa e a estrutura lexical das linguagens de programação.

As gramáticas do tipo 2 (sem contexto) e do tipo 3 (regulares) geralmente são feitas por computadores, porque os analisadores podem ser implementados com eficiência.

BNF (Backus Normal Form ou Backus – Naur Form) é uma técnica de notação para gramáticas sem contexto, frequentemente usada para descrever a sintaxe das linguagens usadas na computação.

Por exemplo, um identificador pode ser descrito como:

<identifier> ::= <letter> { <letter> | <digit> }

o que significa que deve começar com uma letra e pode conter letras ou dígitos adicionais.

Anteriormente, uma letra é definida como 'a' | 'b' 'c' etc., e dígito é definido como '0' a '9' usando o mesmo tipo de notação.

A instrução "for" da CA pode ser definida como:

 <for_statement> ::=
    'for' '(' <expression> ';' <expression> ';' <expression> ')' <statement> 

Analisadores e analisadores lexicais (os primeiros estágios de um compilador ou intérprete) são então construídos para aceitar a gramática específica descrita pelo BNF para um idioma específico. Os analisadores lexicais são normalmente usados ​​para separar os vários tokens de um idioma (como uma palavra-chave, identificador ou número), e o analisador é usado para descobrir como os tokens funcionam juntos, como a construção de uma declaração "for" .

tcrosley
fonte
+1 excelente redação. Mas não estou surpreso que isso não tenha sido aceito como resposta. Isso é o que eu pensei que o OP estava perguntando, mas com base na resposta que eles escolheram, parece que eles queriam algo muito mais alto.
Matthew Rodatus
5

Primeiro, vamos definir "linguagem" em termos do que é. A linguagem requer primeiro um vocabulário (uma lista de palavras que definem conceitos que são os objetos da comunicação) e, em seguida, uma sintaxe (uma "cartilha" ou conjunto de regras que definem a estrutura da comunicação).

Nesse nível mais básico, o C # não é tão diferente do inglês. O que faz do C # uma "linguagem de programação" é sua intenção e, portanto, seu design; Ele foi projetado para ser digerido em comandos individuais de baixo nível. Como tal, o vocabulário predefinido é limitado, a sintaxe é aplicada com muita rigidez e o idioma inteiro é projetado para ser consumido de uma maneira predefinida muito conhecida pelo seu "público" (o computador; mais precisamente o compilador, que digerirá o código fonte em um "idioma intermediário" de comandos simples que podem ser posteriormente traduzidos em código de máquina pelo "tempo de execução"). Você não escreve prosa ou poesia em C #; você diz ao computador para fazer um trabalho da maneira mais inequívoca possível.

Para computadores, sim, é necessária uma ferramenta, geralmente chamada de compilador, para pegar o que você escreve em código e convertê-lo nas instruções que o computador pode usar. A ciência da computação, como a maioria das tecnologias, é um processo inerentemente iterativo e "em camadas". Quando os computadores foram inventados, eles foram programados inserindo manualmente as instruções binárias. Essas instruções foram padronizadas para cada processador em "códigos de máquina" hexadecimais; a diferença está apenas na forma como os dígitos binários são agrupados para exibição em humanos. Em seguida, no código assembler, a lista de comandos e alguns identificadores básicos, como nomes de registradores, foram substituídos por seus códigos hexadecimais ao escrever programas; O ASM ainda pode ser convertido 1: 1 em código de máquina nativo. O salto quântico foi para a programação "imperativa" de 3ª geração, que basicamente pega conceitos abstratos mais compreensíveis ao ser humano, como variáveis ​​e loops lógicos, e os digere nas instruções nativas, usando padrões baseados em palavras-chave e sintaxe. Idiomas antigos como COBOL, FORTRAN, Pascal e C ainda podem ser "traduzidos" por um ser humano para um idioma de máquina específico (geralmente 8086 ASM). Então veio a revolução da programação orientada a objetos, que é basicamente regras de sintaxe adicionais que definem o código como sendo encapsulado conceitualmente em "objetos" que possuem alguma combinação de estado e lógica. por um ser humano em uma linguagem de máquina específica (geralmente 8086 ASM). Então veio a revolução da programação orientada a objetos, que é basicamente regras de sintaxe adicionais que definem o código como sendo encapsulado conceitualmente em "objetos" que possuem alguma combinação de estado e lógica. por um ser humano em uma linguagem de máquina específica (geralmente 8086 ASM). Então veio a revolução da programação orientada a objetos, que é basicamente regras de sintaxe adicionais que definem o código como sendo encapsulado conceitualmente em "objetos" que possuem alguma combinação de estado e lógica.

Atualmente, estamos inseridos na "quarta geração" de idiomas, escritos para definir a comunicação com outros programas, em vez de diretamente para a máquina. Amplamente definido, isso inclui linguagens de "marcação", como XML / HTML, linguagens de "script", como JavaScript e SQL, e a maioria das linguagens de "sandbox", como Java e o .NET Framework (que são compiladas em um IL que é posteriormente interpretado por um tempo de execução que abstrai os detalhes específicos da máquina e da plataforma). Você também pode dizer que abrange o domínio das linguagens de programação funcionais, que dependem HEAVILY de um tempo de execução para fornecer abstração não apenas de detalhes específicos da máquina, mas de detalhes específicos da operação. Esses idiomas de quarta geração são mais ou menos inviáveis ​​para um ser humano traduzir em instruções de máquina nativas, e o ponto é que não seria um empreendimento que valesse a pena; a força dessas linguagens é o processo em camadas em que elas são usadas para, eventualmente, dizer ao computador o que fazer nos níveis mais baixos.

KeithS
fonte
Obrigado. Eu tenho um vislumbre da história do desenvolvimento da linguagem de programação.
Erica Xu
2
@ KeithS: Você pode reformatar o último parágrafo para torná-lo um pouco mais legível.
Ivan Vučica 25/10
4

É uma boa pergunta. Uma resposta adequada forma uma boa metade do que é chamado de "Ciência da Computação".

Para começar, eu recomendaria percorrer a semântica denotacional e operacional e depois ler este livro . Isso lhe dará uma compreensão mais ou menos sólida do que é a linguagem de programação e como ela pode ser formalmente definida.

Se o exposto acima é um pouco acadêmico, você pode começar com Petzold, "Código" , e depois voltar para a semântica.

SK-logic
fonte
1
Você realmente espera que um novato de 18 anos leia alguma teoria pesada apenas para responder a essa pergunta?
Job
2
@Job, de acordo com a pergunta anterior, ele está recebendo doses de Scheme (e, presumivelmente, SICP) na universidade. Deve ficar bem com um pouco de semântica então. De qualquer forma, não há resposta adequada para essa pergunta sem a teoria pesada.
SK-logic,
+1 por mencionar "Código". Esse livro deve ser uma leitura obrigatória para todos os estudantes de nível básico.
Daniel Pryden 24/10/11
4

Se você escrever um programa em uma linguagem de programação, um programa diferente converterá os símbolos no seu programa em símbolos que o computador entende. Às vezes, isso leva várias etapas. Por exemplo em C:

  1. O usuário escreve um programa em linguagem de alto nível (C), que não é entendida pela CPU, mas é entendida diretamente pelo programador (esperamos!).

  2. O compilador converte C na linguagem Assmebly, que não é diretamente entendida pela CPU, mas é fácil de converter em outra coisa.

  3. O Assempler converte o Assembly em sequência de códigos binários que são diretamente entendidos pela CPU. Alguns compiladores pulam a etapa acima (etapa 2) e produzem o binário compilado diretamente do código-fonte.

Para garantir que o computador entenda seu programa, o compilador ou intérprete fornecerá um erro e, geralmente, será interrompido se encontrar algo que não é compilável, como um erro de sintaxe. Se seu programa não puder ser compilado, ele nunca poderá chegar ao estágio em que seu programa tentará executá-lo e falhará porque não o "entendeu".

Para criar um novo idioma, você primeiro projeta seu idioma de alto nível e, em seguida, precisa encontrar uma maneira de mapear os símbolos do seu novo idioma para os comandos da linguagem assembly que sua CPU entende.

FrustratedWithFormsDesigner
fonte
2
Na verdade não; compiladores modernos não executam a etapa 2 e apenas produzem código binário diretamente. Mas montagem e código binário são quase equivalentes de qualquer maneira; você pode desmontar (converter o código binário em montagem) com uma fidelidade muito alta.
MSalters 25/10/11