Qu'est-ce qu'un langage de programmation exactement? Qu'est-ce qui nous permet d'écrire dans une telle langue?

26

D'accord, je suis nouveau dans la programmation et j'admets que c'est une question assez abstraite.

Le langage naturel que nous parlons tous les jours existe parce que les gens peuvent se comprendre. Comment les ordinateurs peuvent-ils comprendre mon code écrit dans une certaine langue?

Disons que M. A crée un nouveau langage. Comment cela est-il accepté par les machines? Le créateur doit-il communiquer avec la machine en utilisant le langage machine pour créer un nouveau langage? Qu'est-ce qui garantit que nous pouvons écrire dans une langue tout en étant bien compris par la machine?

Erica Xu
la source
1
Qu'est-ce qui nous permet d'écrire dans une telle langue? - "Brains: le nouveau remplisseur de tête de merveille!" - Spike Milligan.
Stephen C
6
Un peu large, mais une bonne question quand même. Trop de gens utilisent simplement des langues sans jamais se demander comment elles fonctionnent. Heureux que vous soyez curieux.
riwalk
4
Il s'agit d'une question de référence générale , facilement et trivialement répondue par Wikipedia .
Aaronaught

Réponses:

39

Vous pouvez résumer à peu près toute la réponse à votre ensemble de questions avec le mot «compilateur» . Un compilateur est un programme spécial dont la fonction est de prendre le code source en entrée, d'appliquer des règles de langage déterminées par le concepteur de langage afin de comprendre ce que signifie le code et de produire du code ayant la même signification dans une autre langue en sortie. Il s'agit généralement de code machine ou d'une certaine forme de bytecode (le "code machine" pour les machines virtuelles), bien qu'il existe des compilateurs spécialisés qui traduisent le code dans d'autres langages de haut niveau. Ils dépassent cependant le cadre de cette question.

Toutes les langues n'ont pas de compilateur. Certains d'entre eux ont un interprète à la place, qui fait tout de même un compilateur, sauf qu'au lieu de produire du code machine après avoir déterminé ce que signifie le programme, il exécute simplement le programme immédiatement. Mais les principes de base de l'analyse (lecture) du code et de la détermination de sa signification sont les mêmes.

Répondre plus en profondeur que cela entrerait dans la théorie du compilateur, qui est un sujet très large. Si le sujet vous intéresse, vous devriez commencer par lire l'article Wikipedia pour "compilateur" et en vérifier les liens, et si vous avez des questions spécifiques, n'hésitez pas à les poser ici.

Mason Wheeler
la source
11
+1 - J'ajouterais également que lorsque vous écrivez une nouvelle langue, vous devez écrire le compilateur ou l'interpréteur dans une autre langue. Les versions ultérieures du compilateur ou de l'interpréteur peuvent ensuite être écrites dans des versions antérieures du langage et compilées avec l'ancien compilateur. Le tout premier assembleur a été écrit en code machine. Le premier compilateur C a été écrit en assembleur (le plus probable) etc.
Scott Whitlock
1
Je changerais la définition du compilateur. Ils n'émettent pas tous du code machine. Surtout de nos jours avec autant de compilateurs émettant du "code intermédiaire", comme MSIL. Il existe même des compilateurs qui émettent du JavaScript!
Neil N
3
J'hésiterais à dire que les compilateurs produisent du code machine par définition, même lorsqu'ils expliquent à un débutant. C'est comme dire que les fonctions renvoient des nombres réels, une simplification excessive inutile. Tout de construction du compilateur détient lorsque le code de production qui ne sont pas pour un ordinateur en fait construit à partir de silicium , mais seulement défini abstraitement (que ce soit une machine virtuelle ou d' un langage de haut niveau, il y a une raison pour laquelle il est dit la norme C définit une machine abstraite , et est un compilateur de l'IR LLVM de très bas niveau à friggin 'JavaScript). Les débutants doivent obtenir cela, le plus tôt sera le mieux.
2
La simplification que la plupart des livres de compilation utilisent est qu'un compilateur applique des règles de langue pour convertir une langue source en une langue cible en sortie. (Il n'est pas rare de compiler en C, par exemple, surtout pour un cours d'introduction).
JasonTrue
4
@delnan, encore plus - chaque langue est un code machine , pour sa propre machine abstraite. Peu importe le niveau élevé de la langue.
SK-logic
11

Comme vous l'avez souligné, les humains communiquent entre eux par le biais d'un langage "naturel" tel que l'anglais, le français, l'allemand. Ils sont appelés naturels parce que nous les acquérons naturellement plutôt que de les inventer intentionnellement (l'espéranto étant une exception).

Un langage formel est un langage inventé dans un but ou un autre. Un langage de programmation tel que C, par exemple, est un langage formel inventé dans le but de programmer des ordinateurs.

Toutes les langues peuvent être décrites à l'aide d'une grammaire. Une hiérarchie des grammaires a été décrite par Noam Chomsky en 1956. Elle se compose des niveaux suivants:

Grammaires de type 0 (grammaires illimitées). Ils sont les plus généraux et équivalent à une machine de Turing. En tant que tel, le problème de décider si une chaîne donnée fait partie d'une grammaire illimitée est indécidable.

Grammaires de type 1 (grammaires contextuelles). Presque toutes les langues naturelles comme l'anglais sont sensibles au contexte. Un exemple de sensibilité au contexte en anglais sont les deux phrases: «Le temps passe comme une flèche». et "Les fruits volent comme une banane". En général, il est difficile pour les ordinateurs de comprendre les langages contextuels.

Grammaires de type 2 (hors contexte). Les langages sans contexte sont la base théorique de la syntaxe de la plupart des langages de programmation.

Grammaires de type 3 (grammaires normales). La famille des langues régulières peut être obtenue par des expressions régulières. Les langages réguliers sont couramment utilisés pour définir les modèles de recherche et la structure lexicale des langages de programmation.

Les grammaires de type 2 (sans contexte) et de type 3 (standard) sont le plus souvent utilisées par les ordinateurs, car les analyseurs peuvent être implémentés efficacement.

BNF (Backus Normal Form ou Backus – Naur Form) est une technique de notation pour les grammaires hors contexte, souvent utilisée pour décrire la syntaxe des langages utilisés en informatique.

Par exemple, un identifiant peut être décrit comme:

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

ce qui signifie qu'il doit commencer par une lettre et peut contenir des lettres ou des chiffres supplémentaires.

Plus tôt, une lettre est définie comme un «a» | «b» | 'c' etc., et digit est défini comme '0' à '9' en utilisant le même type de notation.

L'instruction AC "for" peut être définie comme suit:

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

Les analyseurs et analyseurs lexicaux (les premières étapes d'un compilateur ou d'un interprète) sont ensuite construits pour accepter la grammaire spécifique décrite par le BNF pour une langue particulière. Les analyseurs lexicaux sont généralement utilisés pour séparer les différents jetons d'une langue (comme un mot-clé, un identifiant ou un nombre), et l'analyseur est utilisé pour comprendre comment les jetons fonctionnent ensemble, comme la construction d'une instruction "for" .

tcrosley
la source
+1 grande rédaction. Mais je ne suis pas surpris que cela n'ait pas été accepté comme réponse. C'est ce que je pensais qu'OP demandait, mais d'après la réponse qu'ils ont choisie, il semble qu'ils voulaient quelque chose de beaucoup plus élevé.
Matthew Rodatus,
5

Tout d'abord, définissons le «langage» en fonction de ce qu'il est. Le langage nécessite d'abord un vocabulaire (une liste de mots qui définissent des concepts qui sont les objets de la communication), puis une syntaxe (un "amorce" ou un ensemble de règles qui définissent la structure de la communication).

À ce niveau le plus élémentaire, C # n'est pas si différent de l'anglais. Ce qui fait de C # un "langage de programmation", c'est son intention, et donc sa conception; il est conçu pour être digéré en commandes individuelles de bas niveau. En tant que tel, le vocabulaire prédéfini est limité, la syntaxe est appliquée de manière très rigide et la langue entière est conçue pour être consommée d'une manière prédéfinie très connue par son "public" (l'ordinateur; plus précisément le compilateur, qui digèrera le code source dans un "langage intermédiaire" de commandes simples qui peuvent ensuite être traduites en code machine par le "runtime"). Vous n'écrivez pas de prose ou de poésie en C #; vous dites à l'ordinateur de faire un travail de la manière la plus claire possible.

Pour les ordinateurs, oui, un outil, généralement appelé compilateur, est nécessaire pour prendre ce que vous écrivez dans le code et le convertir en instructions que l'ordinateur peut utiliser. L'informatique, comme la plupart des technologies, est un processus intrinsèquement itératif, "en couches". Lorsque les ordinateurs ont été inventés pour la première fois, ils ont été programmés en entrant manuellement les instructions binaires. Ces instructions sont devenues standardisées pour chaque processeur en "codes machine" hexadécimaux; la différence réside uniquement dans la façon dont les chiffres binaires sont regroupés pour être affichés aux humains. Ensuite, dans le code assembleur, la liste des commandes et certains identificateurs de base comme les noms de registres ont été substitués à leurs codes hexadécimaux lors de l'écriture de programmes; ASM peut toujours être converti 1: 1 en code machine natif. Le saut quantique a été vers la programmation "impérative" de 3e génération, qui prend essentiellement des concepts abstraits plus compréhensibles par l'homme comme les variables et les boucles logiques et les digère dans les instructions natives, en utilisant des modèles basés sur des mots clés et la syntaxe. Les premiers langages comme COBOL, FORTRAN, Pascal et C peuvent toujours être «traduits» par un humain dans un langage machine particulier (généralement 8086 ASM). Puis vint la révolution de la programmation orientée objet, qui est essentiellement des règles de syntaxe supplémentaires qui définissent le code comme étant encapsulé conceptuellement dans des "objets" qui ont une combinaison d'état et de logique. par un humain dans un langage machine particulier (généralement 8086 ASM). Puis vint la révolution de la programmation orientée objet, qui est essentiellement des règles de syntaxe supplémentaires qui définissent le code comme étant encapsulé conceptuellement dans des "objets" qui ont une combinaison d'état et de logique. par un humain dans un langage machine particulier (généralement 8086 ASM). Puis vint la révolution de la programmation orientée objet, qui est essentiellement des règles de syntaxe supplémentaires qui définissent le code comme étant encapsulé conceptuellement dans des "objets" qui ont une combinaison d'état et de logique.

De nos jours, nous sommes bien dans la "4ème génération" de langages, qui sont des langages écrits pour définir la communication avec d'autres programmes plutôt que directement vers la machine. Largement défini, cela inclut les langages de «balisage» comme XML / HTML, les langages de «script» comme JavaScript et SQL, et la plupart des langages «sandbox» comme Java et .NET Framework (qui se compilent en un IL qui est ensuite interprété par un runtime qui résume les détails spécifiques à la machine et à la plate-forme). Vous pourriez également dire qu'il englobe le domaine des langages de programmation fonctionnels, qui dépendent fortement d'un runtime pour fournir une abstraction non seulement des détails spécifiques à la machine, mais des détails spécifiques à l'opération. Ces langages de 4e génération sont plus ou moins irréalisables pour un humain à traduire en instructions machine natives, et le fait est que ce ne serait pas une entreprise valable; la force de ces langages réside dans le processus en couches dans lequel ils sont éventuellement utilisés pour indiquer à un ordinateur ce qu'il doit faire aux niveaux faibles.

KeithS
la source
Merci. J'ai un aperçu de l'histoire de l'évolution du langage de programmation.
Erica Xu
2
@KeithS: Vous voudrez peut-être reformater le dernier paragraphe pour le rendre un peu plus lisible.
Ivan Vučica
4

C’est une bonne question. Une bonne réponse constitue une bonne moitié de ce qu'on appelle "l'informatique".

Pour commencer, je recommanderais de parcourir la sémantique dénotationnelle et opérationnelle , puis de lire ce livre . Il vous donnera une compréhension plus ou moins solide de ce qu'est le langage de programmation et comment il peut être formellement défini.

Si ce qui précède est un peu trop académique, vous pouvez commencer par Petzold, "Code" , puis revenir à la sémantique.

SK-logic
la source
1
Vous vous attendez vraiment à ce qu'un noob de 18 ans lise une théorie lourde juste pour répondre à cette question?
Job du
2
@Job, selon sa question précédente, il reçoit des doses de Scheme (et, probablement, de SICP) à l'université. Ça devrait aller avec un peu de sémantique alors. Quoi qu'il en soit, il n'y a pas de bonne réponse à cette question sans une théorie lourde.
SK-logic
+1 pour avoir mentionné "Code". Ce livre devrait être une lecture obligatoire pour chaque étudiant CS débutant.
Daniel Pryden
4

Si vous écrivez un programme dans un langage de programmation, un programme différent convertira les symboles de votre programme en symboles que l'ordinateur comprend. Parfois, cela prend plusieurs étapes. Par exemple en C:

  1. L'utilisateur écrit le programme dans un langage de haut niveau (C) qui n'est pas compris par le CPU, mais est directement compris par le programmeur (nous espérons!).

  2. Le compilateur convertit C en langage Assmebly, qui n'est pas directement compris par le CPU mais est facile à convertir en quelque chose d'autre.

  3. Assempler convertit Assembly en une séquence de codes binaires qui sont directement compris par le CPU. Certains compilateurs sautent l'étape ci-dessus (étape 2) et produisent le binaire compilé directement à partir du code source.

Pour garantir que l'ordinateur comprend votre programme, le compilateur ou l'interpréteur vous donnera une erreur et s'arrêtera généralement s'il rencontre quelque chose qui n'est pas compilable, comme une erreur de syntaxe. Si votre programme ne peut pas être compilé, il ne pourra jamais atteindre le stade où votre programme essaiera de l'exécuter et échouera car il ne l'a pas "compris".

Pour créer un nouveau langage, vous devez d'abord concevoir votre langage de haut niveau, puis vous devez trouver un moyen de mapper les symboles de votre nouveau langage aux commandes du langage d'assemblage que votre CPU comprend.

FrustratedWithFormsDesigner
la source
2
Pas vraiment; les compilateurs modernes ne font pas l'étape 2 et produisent simplement du code binaire directement. Mais l'assembly et le code binaire sont de toute façon presque équivalents; vous pouvez démonter (reconvertir le code binaire en assembleur) avec une très haute fidélité.
MSalters