Les langues modernes utilisent-elles encore des générateurs d'analyseurs?

38

Je faisais des recherches sur la suite du compilateur gcc sur wikipedia ici , quand cela a été annoncé:

GCC a commencé par utiliser des analyseurs LALR générés avec Bison, mais a progressivement adopté des analyseurs manuscrits à descente récursive; pour C ++ en 2004 et pour C et Objective-C en 2006. Actuellement, tous les frontaux utilisent des analyseurs syntaxiques à descente récursive écrits à la main.

Donc, par cette dernière phrase (et pour autant que je me fie à wikipedia), je peux définitivement dire que "C (gcc), C ++ (g ++), Objective-C, Objective-C ++, Fortran (gfortran), Java (gcj), Ada (GNAT), Go (gccgo), Pascal (gpc), ... Mercury, Modula-2, Modula-3, PL / I, D (gdc) et VHDL (ghdl) "sont tous des interfaces qui ne plus utiliser un générateur d'analyseur. C'est-à-dire qu'ils utilisent tous des analyseurs syntaxiques écrits à la main.

Ma question est alors, est-ce que cette pratique est omniprésente? Plus précisément, je cherche des réponses exactes à "l'implémentation standard / officielle de x a-t-elle un analyseur manuscrit" pour x dans [Python, Swift, Ruby, Java, Scala, ML, Haskell]? (En fait, les informations sur les autres langues sont également les bienvenues ici.) Je suis sûr de pouvoir le trouver moi-même après de nombreuses recherches. Mais je suis également sûr que la communauté peut facilement répondre à cette question. Merci!

eatonphil
la source
3
Point de données: CPython dispose d’un générateur d’analyseur LALR (pgen). Je ne sais pas pour le reste.
8
Point de données: Ghc (haskell) utilise un générateur d’analyseur LALR (happy), comme le fait OCaml.
Twan van Laarhoven
1
Devrait être "Faites des compilateurs modernes hautes performances ..." ou similaire, car le langage correspond à la spécification et non à la mise en oeuvre, alors que c'est le compilateur qui utilise ou non un analyseur généré par la machine.
dmckee
@dmckee, oui vous avez raison. Cependant, la dénomination commence à être longue et moins pertinente. N'hésitez pas à l'éditer si vous êtes plus créatif que moi!
eatonphil
En ce qui concerne ML: MLton utilise un générateur d’analyseur spécifique à ML, je suis sûr à 90% que SML / NJ le fait aussi bien que je le connaisse moins. Vous pouvez ou non vouloir considérer cela comme "écrit à la main".
Patrick Collins

Réponses:

34

D’après les informations dont nous disposons, GCC utilise des analyseurs syntaxiques écrits à la main, en particulier, pour améliorer le diagnostic des erreurs syntaxiques (c’est-à-dire donner des messages humains significatifs sur les erreurs de syntaxe).

La théorie de l'analyse syntaxique (et les générateurs d'analyse descendants de celle-ci) consiste principalement à reconnaître et à analyser une phrase d'entrée correcte . Mais nous attendons des compilateurs qu'ils donnent un message d'erreur significatif (et qu'ils soient capables d'analyser de manière significative le reste de l'entrée après l'erreur syntaxique), pour certaines entrées incorrectes.

En outre, les anciens langages hérités, comme C11 ou C ++ 11 (qui sont conceptuellement anciens, même si leur dernière révision date de trois ans) ne sont pas du tout dépourvus de contexte. Faire face à cette sensibilité au contexte dans les grammaires pour les générateurs d’analyseurs (c’est-à-dire le bison ou même le menhir ) est ennuyeux.

Basile Starynkevitch
la source
2
D'accord. Bien récupérer des erreurs d’analyse (lorsque vous ne voulez pas arrêter l’analyse à la toute première erreur, comme à l’ancien Pascal Borland) et créer des messages d’erreur de bonne qualité (comprenant des astuces et des suggestions de résolution, comme le souhaitent les utilisateurs), sont tous deux inhérents au contexte. -sensibles, tâches heuristiques. Elles peuvent être effectuées au-dessus de la sortie du générateur d’analyseur d’actions, mais c’est un peu difficile.
Jonathan Eunice
2
Dealing with that context sensitiveness in grammars for parser generators is boringly difficult. C'est aussi plus ou moins impossible, car ces outils génèrent des analyseurs syntaxiques sans contexte. Le bon endroit pour vérifier si toutes les contraintes contextuelles sont présentes est après avoir généré l'arbre d'analyse syntaxique si vous utilisez des outils comme celui - ci.
dtech
7

Les générateurs et moteurs d'analyse sont assez généraux. L’avantage de la généralité est qu’il est facile, dans l’ensemble, de créer rapidement un analyseur précis et de le rendre fonctionnel.

Le moteur de l'analyseur lui-même souffre sur le plan des performances en raison de sa généralité. Tout code manuscrit sera toujours beaucoup plus rapide que les moteurs d’analyse par table.

Le deuxième domaine qui pose problème aux générateurs / moteurs d'analyse est que tous les langages de programmation sont sensibles au contexte, souvent de manière assez subtile. Les langues LR sont dépourvues de contexte, ce qui signifie qu'il existe de nombreuses subtilités concernant le positionnement et l'environnement qui sont impossibles à transmettre correctement dans la syntaxe. Les grammeurs attribués tentent de traiter des règles de base du langage, telles que "déclarer avant utilisation", etc. Le câblage de cette sensibilité au contexte dans du code manuscrit est simple.

BobDalgleish
la source
15
Citation pour la demande de performance s'il vous plaît? Être axé sur les tables peut être une optimisation significative des performances et les générateurs ont accès à des algorithmes très efficaces mais pratiquement jamais implémentés à la main (précisément parce qu’il s’agit d’un fouillis impénétrable de tableaux et de nombres magiques).
2
Et à propos de la deuxième zone: Beaucoup de nombreuses grandes langues de programmation réelle ne sont pas sensibles au contexte dans un sens qui s'applique (vous auriez à se référer à l'ensemble de tous valides programmes après vérification du type et ce qui est jamais ce qu'un écrit à la main ou l'analyseur généré tente d'analyser). Il est vrai que les analyseurs manuscrits sont plus flexibles, ce qui est utile pour certaines langues, mais principalement dans le domaine de la récupération et de la génération de rapports sur les erreurs, de l’incrémentalité, etc. - les générateurs d’analyseurs sont rarement évités en raison du pouvoir de reconnaissance (que vous le fassiez ou non). vouloir écrire une telle grammaire est une histoire différente). -1
Si vous utilisez des informations de table de symboles lors de l'analyse, vous pouvez également les appeler contextuelles. Les grammaires attribuées ne sont certainement pas dépourvues de contexte, même si je ne pense pas qu'elles soient totalement sensibles au contexte. Vos autres points concernant la récupération d’erreurs et les rapports sont bien pris.
BobDalgleish
1
C et C ++ ont besoin des informations de la table des symboles lors de l'analyse (ou acceptez un arbre d'analyse beaucoup moins spécifique dans lequel aucune distinction n'est faite entre, par exemple, les déclarations d'expression et les déclarations de variable). Mais je n'y pensais pas. Des langages comme Java, Lisps, JavaScript, Ruby, Python, Go, Rust, Scala, Swift, Haskell (et probablement plusieurs autres, peut-être aussi C # et ML?) N'ont pas besoin de telles informations pour créer le type d'AST veux quand même. Beaucoup d’entre eux ont en fait des grammaires LL (1), voire des grammaires LALR.
1
citation pour toutes les langues réelles sont sensibles au contexte s'il vous plaît?
psr