Compléter SQL. Partie 1. La complexité de l'analyse. Histoires sur la finalisation du fichier ANTLR

Je publie l'article original sur Habr, dont la traduction est publiée sur le blog Codingsight .

Que se passera-t-il dans cet article?


Je travaille dans l'entreprise depuis plus de cinq ans, qui développe la ligne IDE pour travailler avec des bases de données. Lorsque j'ai commencé à travailler sur cet article, je ne pouvais pas imaginer combien d'histoires intéressantes je pouvais me souvenir, car lorsque j'ai terminé, j'ai reçu plus de 30 pages de texte. Après un peu de réflexion, j'ai regroupé les histoires par sujet et divisé l'article en plusieurs.

Au fur et à mesure de ma publication, j'ajouterai des liens vers les parties suivantes:

Partie 1. La complexité de l'analyse. Histoires sur la finalisation d'ANTLR avec un fichier
Partie 2. Optimisation du travail avec des chaînes et l'ouverture de fichiers
Partie 3. Durée de vie des extensions pour Visual Studio. Travaillez avec IO. Utilisation inhabituelle de SQL
Partie 4. Travailler avec des exceptions, l'impact des données sur le processus de développement. Utilisation de ML.NET

Beaucoup de choses intéressantes se sont produites pendant le travail: nous avons trouvé plusieurs bogues dans .NET, optimisé plusieurs fois certaines fonctions, et certaines seulement en pourcentage, fait quelque chose de très cool la première fois, et quelque chose que nous n'avons pas réussi même après quelques tentatives. Mon équipe développe et prend en charge les fonctionnalités du langage IDE, la principale étant l'achèvement du code. D'où le nom de la série d'articles. Dans chacune de leurs parties, je raconterai plusieurs histoires: certaines sur les succès, d'autres sur les échecs.

Dans cette partie, je me concentrerai sur les problèmes d'analyse syntaxique de SQL, la lutte contre ces problèmes et les erreurs commises dans ce combat.



Pour ceux qui ne sont intéressés que par une partie de cela et juste pour une navigation facile, le contenu de l'article:

Contenu




Qui suis je?


Je suis arrivé à ce poste en juin avec très peu d'expérience. Comme beaucoup, je suis venu à la programmation parce que je voulais faire des jouets. Plusieurs ont même réussi. J'ai même écrit sur le développement d'un ici. Récemment, au fait, il l'a ressuscitée sur un autre serveur. Il restait une douzaine de jeux créés ou abandonnés à différents stades de préparation. En plus des jeux, avant de décrocher ce travail, j'ai réussi à réaliser plusieurs projets en freelance. Le plus important d'entre eux était l'application de médias sociaux, qui était un portail de football avec des tables de tournois, des données de joueurs et la possibilité d'informer les utilisateurs du score final ou des buts marqués par SMS. Cela a été fait il y a près de 10 ans. À cette époque, tout le monde n'était pas allé avec des smartphones, et qui se rendait plus souvent sans Internet ou avec le EDGE à trois maudits sur lequel ouvrir un site de texte n'était pas toujours possible. L'idée m'a donc semblé bonne.

D'une manière ou d'une autre, il s'est avéré qu'en plus des jeux, j'étais également amené à créer différents réglages pour moi-même ou d'autres développeurs. Parfois, il était proche de ce que je devais faire au travail un peu plus tard. Par exemple, l'un des projets que j'ai réalisés en étudiant l'API Win32 était un programme mettant en évidence le code XML dans Rich Edit Control. De plus, il était possible de télécharger du code rétro-éclairé sur des codes BMP, HTML ou BB qui étaient à la mode alors sur différents forums.

Un autre projet qui s'est avéré très proche de ce que je faisais au travail était un programme qui analyse le code C / C ++ et en construit un diagramme. L'organigramme était strictement conforme aux exigences d'un enseignant de l'université. Il a été fait maladroitement, dans le front, sans aucune connaissance de la théorie de l'analyse syntaxique, et a travaillé exclusivement sur mon caractère merdique. Quelques années plus tard, tout en nettoyant l'ordinateur de vieux déchets, je suis tombé dessus et je ne pouvais pas le retirer, alors je l'ai posté sur github pour l'histoire.

Ces expériences, couplées à du freelance, ont donné une assez bonne expérience et ont permis d'obtenir un emploi. Au fil du temps, après une douzaine de revues trempées de sang et de larmes, je commence même à bénéficier à l'entreprise et au produit. Revenir en arrière, c’est plutôt drôle de comprendre qu’à la suite de plusieurs accidents, j’ai commencé à faire exactement ce qui m’attirait.

Quelles sont les difficultés?


Ce bloc est nécessaire pour plonger le lecteur dans le contexte de ce que nous faisons réellement.



Développement de bureau


Ce n'est peut-être même pas de la complexité, car c'est déjà un domaine très mature dans lequel il n'y a pas grand-chose d'inconnu, les bibliothèques sont stables, les meilleures pratiques sont connues. Cette fonctionnalité de notre projet est ici, parce que moi, comme beaucoup d'autres programmeurs, j'ai tendance à la nouveauté, et la nouveauté a maintenant disparu sur le Web. Il y a eu des jours où, sous la pluie, je suis monté sur le rebord de la fenêtre, recouvert d'une couverture, avec une tasse de cacao, et j'ai pensé à redis, réagir, charger et systèmes distribués qui sont développés quelque part sans moi en ce moment. L'autre côté de ce problème est qu'il n'est pas facile de décrire la complexité du projet à des développeurs familiers par rapport à la bière, et lorsque vous travaillez sur des applications qui fonctionnent selon des lois fondamentalement différentes, cela devient encore plus difficile.


Analyse SQL et dialectes


J'ai également écrit de petits analyseurs pour différentes langues avant ce travail. Pendant un certain temps, j'ai enseigné des cours .NET. Pour certains groupes, en tant que tâche supplémentaire, dans le cadre du sujet «chaîne», ils ont suggéré d'écrire leur propre analyseur JSON simple. Seuls SQL et ses variantes sont loin d'être XML ou JSON conçus pour être également compréhensibles par les analyseurs et les utilisateurs. De plus, SQL est syntaxiquement plus complexe que C / C ++, avec ses nombreuses fonctions accumulées sur une longue histoire. SQL est structuré différemment, ils ont essayé de le faire ressembler à un langage naturel, avec succès, soit dit en passant. La langue a plusieurs milliers de mots-clés (selon le dialecte). Souvent, pour distinguer une expression d'une autre, vous devez jeter un œil à deux mots ou plus (jetons). Cette approche est appelée l'anticipation. Il existe une classification des analyseurs selonjusqu'où ils peuvent regarder en avant: LA (1), LA (2) ou LA (*), ce qui signifie que l'analyseur peut regarder aussi loin que possible pour déterminer la branche correcte. Parfois, la fin facultative d'une clause à l'intérieur d'une instruction SQL coïncide avec le début d'une autre, qui est également facultative: de telles situations rendent les analyseurs beaucoup plus compliqués. T-SQL verse de l'eau dans le feu, dans lequel le point-virgule est facultatif, et la fin possible, mais non obligatoire, de certaines instructions SQL peut entrer en conflit avec le début d'autres.de telles situations compliquent grandement les analyseurs. T-SQL verse de l'eau dans le feu, dans lequel le point-virgule est facultatif, et la fin possible, mais non obligatoire, de certaines instructions SQL peut entrer en conflit avec le début d'autres.de telles situations compliquent grandement les analyseurs. T-SQL verse de l'eau dans le feu, dans lequel le point-virgule est facultatif, et la fin possible, mais non obligatoire, de certaines instructions SQL peut entrer en conflit avec le début d'autres.

Vous ne croyez toujours pas? Il existe un mécanisme pour décrire les langages formels à travers les grammaires . La grammaire est un code dans une langue qui en décrit une autre. À partir d'une grammaire, vous pouvez souvent générer un analyseur à l'aide d'un outil. Les outils et langages de description de grammaire les plus connus sont YACC et ANTLR . Les analyseurs générés par YACC sont utilisés directement dans les moteurs MySQL , MariaDB , PostgreSQL. Vous pouvez essayer de les prendre directement à partir de l'open source et de développer la complétion de code et d'autres fonctions basées sur l'analyse SQL basée sur eux. De plus, une telle implémentation recevrait des mises à jour gratuites en termes de développement, et l'analyseur se comporterait garanti d'être identique au moteur de base de données. Alors pourquoi utilisons-nous ANTLR? Il supporte qualitativement C # /. NET, il existe de bons outils pour travailler avec lui, sa syntaxe est beaucoup plus facile à lire et à écrire. La syntaxe ANTLR s'est avérée si pratique que Microsoft l'a récemment utilisée dans la documentation officielle C #.

Revenons à ma preuve de la complexité de SQL, par rapport à d'autres langages, en termes d'analyse. Pour ce faire, je veux comparer les tailles de grammaire pour différentes langues disponibles publiquement. Dans dbForge, nous utilisons nos propres grammaires, elles sont plus complètes que celles disponibles publiquement, mais, malheureusement, sont très obstruées par des insertions de code C # pour prendre en charge différentes fonctions, plus à ce sujet dans la section «Analyse sans arborescence» dans la section «Erreurs».

Voici les tailles de grammaire pour différentes langues:

JS - analyseur de 475 lignes + 273 lexer = 748 lignes
Java - analyseur de 615 lignes + 211 lexer = 826 lignes
C # - analyseur de 1159 lignes + 433 lexer = 1592 lignes
C ++ - 1933 lignes

MySQL- analyseur 2515 lignes + 1189 lexer = 3704 lignes
T-SQL - 4035 lignes analyseur + 896 analyseurs lexicaux = 4931 lignes
PL SQL - 6719 lignes analyseur + 2366 lexer = 9085 lignes

A la fin de certains lexers il y a une énumération des caractères Unicode dans la langue, cela est inutile dans évaluation de la complexité de la langue. J'ai pris le nombre de lignes avant de commencer de tels transferts.

Il peut y avoir des questions concernant la complexité de l'analyse d'une langue en fonction du nombre de lignes dans sa grammaire. Les questions peuvent également porter sur la plénitude des grammaires ouvertes par rapport à la syntaxe réelle des langues. Malgré cela, je considère toujours utile de donner ces chiffres, car l'écart est trop important.


Ce n'est pas tout, car nous n'avons pas seulement besoin d'analyser plusieurs fichiers en SQL. Nous faisons un IDE, ce qui signifie que nous devons travailler sur des scripts incomplets ou invalides. Même si vous écrivez vos scripts sans erreurs, peut-être que vous les écrivez de manière incohérente, il est peu probable que le script soit valide tout au long du processus de développement. Par exemple, j'écris d'abord «SELECT FROM», après quoi je serai heureux de voir la liste des tables disponibles. Lorsque je sélectionne une table, je réorganise le chariot sur SELECT, j'appuie sur la barre d'espace et j'attends la liste des colonnes de cette table particulière. Il s'agit d'un exemple très simple, mais il montre que l'analyseur fournissant la complétion de code dans l'EDI ne peut pas planter, à l'exception de rencontrer un script non valide. Nous avons dû trouver de nombreuses astuces pour nous assurer que l'infobulle fonctionne correctement dans de nombreux scénarios de ce type,mais les utilisateurs envoient toujours différents scénarios pour travailler avec des scripts inachevés, ce qui signifie que nous devons trouver de nouvelles astuces.

Guerres de prédicat


Lors de l'analyse du code, il existe parfois des situations où le mot suivant ne précise pas laquelle des deux alternatives choisir. Parfois, il suffit de jeter un œil à un nombre strictement défini de mots à l'avance et vous pouvez certainement choisir une alternative. Le mécanisme de résolution de ce type d'inexactitude est appelé l'anticipation ANTLR. Dans ce cas, la méthode de l'analyseur syntaxique est construite comme une chaîne imbriquée d'if, dont chacun regarde un mot plus loin. Ci-dessous, un exemple de grammaire générant une telle incertitude.

rule1:
    'a' rule2 | rule3
    ;

rule2:
    'b' 'c' 'd'
    ;

rule3:
    'b' 'c' 'e'
    ;

Au milieu de la règle 1, ayant déjà passé le jeton 'a', l'analyseur devra regarder 2 jetons devant pour choisir la règle à suivre. Encore une fois, cette vérification se fera à l'intérieur de la règle. Cette grammaire peut être réécrite de sorte que cette anticipation n'existe pas, malheureusement la structure souffre souvent de telles optimisations, et le gain de performances est relativement peu élevé.

Des mécanismes plus complexes existent pour résoudre des incertitudes plus complexes. L'un d'eux est le mécanisme de prédicat de syntaxe (synpred) dans ANTLR3.

Il vient à la rescousse dans les cas où, par exemple, l'achèvement facultatif d'une clause recoupe le début de l'autre optionnel suivant. Le prédicat, en termes ANTLR3, est la méthode générée, qui effectue un passage virtuel à travers le texte conformément à l'une des alternatives et, en cas de succès, retourne vrai, cet achèvement du prédicat est appelé réussi. La passe virtuelle est également appelée passe de retour en arrière. Si le prédicat a fonctionné avec succès, une véritable passe est effectuée. Cela devient un problème lorsqu'un autre prédicat commence à l'intérieur d'un prédicat, puis une section peut être parcourue cent mille fois.

Prenons un exemple simplifié. Il y a 3 points d'incertitude (A, B, C).

  1. L'analyseur saisit A, se souvient de la position dans le texte, commence un passage virtuel du 1er niveau.
  2. B, , 2- .
  3. C, , 3- .
  4. 3- , 2 .
  5. 2 , 1 B .
  6. , A, B .

Ainsi, tous les contrôles à l'intérieur de C seront effectués 4 fois, B - 3 fois, A - 2 fois. Mais que faire si l'alternative appropriée est deuxième ou troisième de la liste? Ensuite, à un certain stade de l'un des prédicats, il échouera, la position dans le texte sera annulée et un autre prédicat commencera à s'exécuter.

En analysant à plusieurs reprises la cause du gel de l'application, nous sommes tombés sur des cas où la «queue» synpred a été exécutée plusieurs milliers de fois. Les synpreds sont particulièrement problématiques dans les règles récursives. Malheureusement, de par sa nature, SQL est récursif, ce qui est au moins la possibilité d'utiliser une sous-requête presque partout. Parfois, à l'aide de divers trucs et astuces, il s'avère que la règle est éliminée de sorte que le prédicat a disparu.

De toute évidence, synpred a un effet négatif sur les performances. À un moment donné, il a fallu mettre leur population sous contrôle strict. Le seul problème est que lors de l'écriture de code de grammaire, l'apparence de synpred peut ne pas être évidente. De plus, parfois, un changement dans une règle entraîne l'apparition d'un prédicat dans une autre. Cela ne peut pas être contrôlé manuellement. Pour contrôler le nombre de prédicats, nous avons écrit un simple régulier, qui a été appelé par une tâche MsBuild spéciale. Si le nombre de prédicats était différent du nombre spécifié dans un fichier séparé, la tâche a interrompu l'assembly et signalé une erreur. Voyant une telle erreur, le développeur a dû réécrire le code de règle plusieurs fois, essayant de se débarrasser des prédicats inutiles, impliquant éventuellement d'autres développeurs dans le problème. Si un prédicat est inévitable,puis le développeur met à jour le nombre de prédicats dans le fichier correspondant. Une modification de ce fichier attire davantage l'attention sur la révision.

Dans de rares cas, nous avons même écrit nos propres prédicats en C # pour contourner ceux générés par ANTLR. Heureusement, un tel mécanisme existe également.

Solutions de vélo cool




Héritage grammatical


Après l'annonce de tout changement dans chacun des SGBD que nous prenons en charge, notre travail pour les prendre en charge commence. Presque toujours, le point de départ est de prendre en charge les constructions syntaxiques dans la grammaire. Pour chaque dialecte SQL, nous écrivons notre propre grammaire, cela génère une certaine répétition du code, mais finalement c'est plus facile que de chercher un commun entre eux. Il y a quelques années à peine, MySQL et MariaDB étaient très similaires, il n'était pas pratique d'écrire des grammaires séparées. Parce que ces quelques constructions qui étaient dans MariaDB, mais qui n'étaient pas dans MySQL, nous avons pris en charge dans la grammaire MySQL. Ce fut un moment désagréable: pour l'utilisateur MySQL, nous pouvions suggérer des constructions qui ne seraient pas valides. Ces dernières années, MariaDB et MySQL sont devenus très divergents en termes de syntaxe et plus encore. Il est devenu évidentqu'il est faux de prendre en charge deux langues différentes dans la même grammaire.

Une solution possible pourrait être une copie complète de la grammaire, après quoi chacune est prise en charge séparément. À la suite d'une longue discussion, nous avons pris une décision audacieuse. Je suis très content que nous n'ayons pas copié le code, chaque cellule en moi a résisté à cette décision. Il a été décidé d'écrire votre propre préprocesseur de grammaire ANTLR, qui implémente le mécanisme d'héritage grammatical. Il y a quelque temps, je suis tombé sur une grammaire ANTLR3 dans le référentiel officiel des grammaires ANTLR4. Je pense que cette phrase doit être lue plusieurs fois pour réaliser la profondeur de la folie.

En discutant de l'idée d'hérédité, nous avons rapidement réalisé que nous aimerions avoir un mécanisme pour le polymorphisme. La capacité dans la grammaire de l'héritier non seulement de redéfinir la règle, mais aussi d'appeler la base. De plus, je veux contrôler la position de l'appel de la règle de base: début, milieu ou fin. Nous avons décidé que toutes les règles peuvent être redéfinies, pour cela vous n'avez pas besoin de spécifier quoi que ce soit de plus. Pour redéfinir une règle, il suffit de déclarer une règle du même nom dans la grammaire suivante. Après cela, la règle de la grammaire parent sera disponible sous un nom différent.

ANTLR est un outil de développement agréable en optimisant - il existe une extension pour VS, il y a ANTLRWorks. En introduisant le mécanisme d'héritage, je ne voudrais pas perdre cette opportunité. Mais comment alors indiquer la grammaire de base? Vous pouvez trouver une sorte de convention pour nommer les fichiers, mais ce n'est pas du tout évident. Une autre option pourrait être d'indiquer ces informations supplémentaires dans un fichier séparé, mais même maintenant, en tapant ces lignes, je sentais la puanteur de cette solution. Le résultat était une indication de la grammaire de base dans la grammaire de l'héritier sous la forme d'un commentaire ANTLR. Tous les outils ignoreront simplement ce texte, et nous pouvons facilement extraire le code qui nous intéresse.

Les exigences ont été formées, il est temps de les mettre en œuvre. Nous avons écrit la tâche MsBuild, qui a été intégrée au système de build général en tant qu'action de pré-build. La tâche a effectué le travail du préprocesseur de grammaire ANTLR, générant la grammaire résultante à partir de la base et héritée. La grammaire résultante a déjà été traitée par ANTLR lui-même. Si une règle portant le même nom que dans le parent a été trouvée dans la grammaire suivante, la règle de base a été renommée: le nom de la grammaire parent a été ajouté à son nom après le trait de soulignement. Par ce nom, il pouvait être contacté chez l'héritier.

Le mécanisme du préprocesseur lui-même n'a pas pris beaucoup de temps, mais avec la génération de l'analyseur, il s'est avéré qu'il ralentissait chaque réassemblage du projet de 10 à 20 secondes. À un moment donné, cela a cessé de nous convenir. Nous avons décidé de réfléchir à la manière d'optimiser cela. La solution a été d'ajouter le hachage de la somme de toutes les grammaires dont il dépend sous forme de commentaire à l'en-tête du fichier analyseur CS. Avant de faire quoi que ce soit, le préprocesseur a comparé ces hachages avec les hachages de fichiers sur le disque, et s'ils ne diffèrent pas, le fichier analyseur a été considéré comme pertinent. Au stade de développement initial, nous avons dû marcher plusieurs fois sur le rake d'analyseurs et de grammaires invalides collectés par la version obsolète du préprocesseur. Par conséquent, la somme de hachage de l'assembly avec le préprocesseur est apparue dans le commentaire d'en-tête.

Un autre post-traitement ANTLR


Dans de nombreux langages de programmation, si le mot est la clé, il ne peut plus être utilisé comme nom d'objet. En SQL, selon le dialecte, de 800 à 3000 mots-clés. La plupart d'entre eux sont étroitement liés au domaine, en outre, ils n'ont pas tous été introduits immédiatement, de sorte qu'une interdiction de les utiliser tous comme noms d'objet se heurterait à une vague d'indignation. SQL introduit le concept de mots clés réservés et non réservés. Vous ne pouvez pas nommer un objet de la même manière qu'un mot clé réservé (SELECT, FROM, etc.) sans le citer, car ce n'est pas un mot clé réservé (CONVERSATION, DISPONIBILITÉ, etc.) - vous le pouvez. Ce comportement complique le développement de l'analyseur. Au moment de l'analyse lexicale, le contexte est inconnu, mais l'analyseur requiert des numéros différents pour l'identifiant et le mot-clé. Pour résoudre ce problème, nous avons ajouté un post-traitement supplémentaire à l'analyseur ANTLR.Le post-traitement remplace toutes les vérifications explicites par un identifiant, avec un appel à une méthode spéciale. Cette méthode implémente une vérification plus délicate. Si un identifiant est entré et qu'un identifiant est attendu plus loin, alors tout va bien, mais si un mot clé non réservé est fourni à l'entrée, il doit être vérifié en plus. Une vérification supplémentaire est que la méthode est examinée dans le contexte actuel dans la recherche de branches, où ce mot-clé non réservé peut être utilisé précisément comme mot-clé, et s'il n'y a pas de telles branches, alors il peut être utilisé comme identifiant.mais si un mot clé non réservé est entré, il doit être vérifié en plus. Une vérification supplémentaire est que la méthode est examinée dans le contexte actuel dans la recherche de branches, où ce mot-clé non réservé peut être utilisé précisément comme mot-clé, et s'il n'y a pas de telles branches, alors il peut être utilisé comme identifiant.mais si un mot clé non réservé est entré, il doit être vérifié en plus. Une vérification supplémentaire est que la méthode est examinée dans le contexte actuel dans la recherche de branches, où ce mot-clé non réservé peut être utilisé précisément comme mot-clé, et s'il n'y a pas de telles branches, alors il peut être utilisé comme identifiant.

À strictement parler, ce problème ne peut être résolu qu'au moyen d'ANTLR, mais une telle solution ne sera pas optimale. Une solution classique à ce problème consiste à créer une règle qui répertorie tous les mots clés non réservés et un jeton d'identification. De plus, partout où il est permis d'utiliser un identifiant, il n'est plus utilisé le jeton identifiant de l'identifiant, mais il s'agit d'une règle spéciale. Une telle solution vous fait non seulement penser à ajouter le mot-clé lorsque vous le saisissez, non seulement là où il est utilisé, mais également dans cette règle spéciale, cela fonctionne également beaucoup plus lentement.

Erreurs



Analyse sans arbre




Le résultat de l'analyseur, en règle générale, est un arbre de syntaxe. Un arbre de syntaxe ( abstrait ou concret ) est une structure de données qui reflète le texte du programme à travers le prisme de la grammaire formelle. Si vous souhaitez implémenter un éditeur de code avec saisie semi-automatique pour la langue que vous avez récemment trouvée, après avoir étudié le problème, vous êtes susceptible d'implémenter approximativement l'algorithme suivant:

  1. Analyser le texte dans l'éditeur. Obtenez l'arbre de syntaxe.
  2. Trouvez le nœud sous le chariot. Associez-le à la grammaire. Découvrez quels mots-clés et types d'objets seront disponibles sur le point.

Dans ce cas, la grammaire est représentée de manière pratique sous la forme d'un graphique ou d'une machine à états finis.

Malheureusement, au début du développement, l'IDE ANTLR existait dans sa troisième version. La quatrième version a été réécrite à partir de zéro et est fondamentalement différente de la troisième; en passant le code, l'analyseur génèrera automatiquement un arbre d'analyse sans une seule ligne supplémentaire. Dans la troisième version, il y avait un mécanisme par lequel on pouvait dire à ANTLR comment construire un arbre, mais ce n'était pas très agréable de l'utiliser. De plus, de nombreux exemples et articles sur ce sujet suggèrent d'utiliser le mécanisme d'actions pour exécuter du code au moment où l'analyseur passe la règle. Ce mécanisme est incroyablement pratique et vous permet d'obtenir rapidement des résultats. Malheureusement, cette solution a entraîné des problèmes architecturaux majeurs avec le développement du produit et une augmentation de la complexité de la prise en charge de nouvelles fonctionnalités. Le fait est que dans un fichier, dans un fichier de grammaire,les actions ont commencé à s'accumuler associées à un grand nombre de fonctionnalités différentes, ce qui serait bien de se propager à différents assemblages. À l'avenir, nous avons pu distribuer les gestionnaires des actions eux-mêmes pour différents assemblages, mettant en œuvre une version assez délicate du modèle d'abonné-notifiant, mais les appels eux-mêmes, avec la transmission des informations nécessaires, encombrent toujours notre grammaire, compliquent le support de nouvelles fonctionnalités et imposent des restrictions sérieuses et désagréables à l'architecture.compliquer le support de nouvelles fonctionnalités et imposer des restrictions sérieuses et désagréables à l'architecture.compliquer le support de nouvelles fonctionnalités et imposer des restrictions sérieuses et désagréables à l'architecture.

Mais tout n'est pas aussi évident qu'il y paraît. Le fait est que ANTLR3 est beaucoup plus rapide que ANTLR4. Selon nos mesures, les différences sont environ 6 fois. De plus, l'arborescence de syntaxe pour les gros scripts peut prendre beaucoup d'espace RAM, et tant que nous devons survivre dans l'espace d'adressage 32 bits des studios Visual et SqlServer Management, cela peut être critique.

Conclusion


Les sous-totaux peuvent être les suivants:

  • ANTLR un outil puissant pour construire des analyseurs
  • Son avantage sur les autres est les outils, la syntaxe pratique, un grand nombre de langues prises en charge
  • ANTLR4 a été réécrit à partir de zéro et implique de travailler avec l'analyseur différent de la troisième version
  • Il y a toujours un moyen d'obtenir un peu plus des bibliothèques ThirdParty qu'elles n'en donnent
  • Langage spécifique à SQL, construire des analyseurs n'est pas une tâche facile
  • L'analyse du code pour les tâches liées à la construction d'un IDE a ses propres particularités: vous devez envisager de travailler sur des scripts non chiffrés ou invalides

Rendez-vous dans la prochaine partie!

All Articles