Interpreter

Catégorie

Pattern comportemental

Problème

Étant donné un langage, définir une représentation de sa grammaire ainsi qu’un interpréteur qui utilise cette représentation pour interpréter des phrases du langage. Utile pour les grammaires simples ou les DSL.

Solution

  • Définir la grammaire comme une hiérarchie de classes (chaque règle est une classe)
  • Chaque classe implémente une méthode interpret()
  • Construire un arbre de syntaxe abstraite représentant la phrase
  • Appeler interpret() sur le nœud racine pour évaluer la phrase

Structure

  • AbstractExpression : Déclare une méthode interpret()
  • TerminalExpression : Implémente interpret() pour les règles de grammaire terminales
  • NonterminalExpression : Implémente interpret() pour les règles non-terminales ; contient des expressions enfants
  • Context : Contient les informations globales nécessaires à l’interpréteur
  • Client : Construit l’arbre de syntaxe abstraite représentant une phrase du langage

Avantages clés

  • Facile de changer/étendre la grammaire — Les nouvelles règles sont de nouvelles classes
  • Représentation claire de la grammaire — La grammaire est exprimée sous forme de classes

Compromis

  • Performance — L’interprétation peut être lente par rapport au code compilé
  • Évolutivité — La complexité de la grammaire croît de manière quadratique avec le nombre de règles

Quand l’utiliser

  • La grammaire est suffisamment simple pour être implémentée manuellement
  • La performance n’est pas un critère critique
  • Vous avez besoin de représenter un langage sous forme de modèle d’objets

Exemples

  • Les analyseurs de requêtes SQL interprètent la grammaire SQL
  • Les moteurs de regex interprètent la grammaire des expressions régulières
  • Pythonetexec()` comme interpréteurs
  • Les analyseurs de fichiers de configuration (YAML, JSON, XML)
  • Les langages spécifiques au domaine dans Ruby On Rails