Bison/Flex tutoriel avec C ++, AST et re-entrant à la fois lexer et parser

I am learning parsing, bison & lex. I am looking for a clear & complete tutorial/example that demonstrates all of:

  1. Arborescence de syntaxe abstraite C ++ (not C).
  2. Lexer ré-entrant.
  3. Analyseur ré-entrant.
  4. Lire à partir d'une chaîne (ou d'un fichier) serait bien aussi.

J'ai trouvé plusieurs exemples et tutoriels, mais chacun ne répond généralement qu'à quelques-unes des exigences ci-dessus. Jusqu'à présent mon meilleur tutoriel vient du chapitre 3-2 du livre d'Oreilly de John Levine - il a AST; tout C cependant, répond seulement Re_1 ci-dessus. J'accueille les recommandations pour de beaux exemples/tutoriels, des projets open source réels. Par exemple, j'ai vu MySQL fichier .yy - semble bien écrit, mais trop gros/complexe pour les débutants comme moi.

0
Vous voulez dire codé en C ++? Ou vous voulez analyser C ++?
ajouté l'auteur Ira Baxter, source
Je veux que mon code qui interagit avec flex/bison soit C ++. En particulier l'AST (Abstract Syntax Tree). L'exemple mentionné dépend de la clémence de type c. De plus, je veux utiliser STL, etc. En ce qui concerne ce que j'essaye d'analyser: une syntaxe simple similaire aux expressions régulières.
ajouté l'auteur Radim Cernej, source

2 Réponses

In the end I combined several examples to get what I wanted. The top two examples were from John Levine's book on bison&flex (2nd edition), ISBN-10: 0596155972. The other one was from a phpcompiler website which unfortunaltly as of 2017-02-28 no longer exists. I am leaving the link here, in case the site is archived somewhere: www.phpcompiler.org/articles/reentrantparser.html

Merci Adrien, voici une version archivée (fonctionne à partir du 2017-03-02):

http: //web.archive. org/web/20120520150851/http: //www.phpcompiler.org/articles/reentrantparser.html

0
ajouté
En effet le webiste phpcompiler.org est parti, merci de m'avoir notifié. J'ai modifié ma réponse de 2012 en conséquence.
ajouté l'auteur Radim Cernej, source
Désolé, Jack, je ne serai pas en mesure de télécharger le code ou d'aider autrement. Nous parlons de 2012 (il y a presque 5 ans) et la propriété intellectuelle appartenait à mon employeur, Fluential Inc/LLC (je ne sais pas s'ils sont encore en affaires). Depuis lors, je n'ai pas travaillé sur l'analyse et je ne me souviens pas beaucoup :(.
ajouté l'auteur Radim Cernej, source
Oui, autant que je sache, cela semble être le même article.
ajouté l'auteur Radim Cernej, source
Le lien semble être mort.
ajouté l'auteur Adrien, source
L'URL a été téléchargée sur archive. org plusieurs fois. L'instantané le plus proche du site a été pris le 20/05/2017, est-ce la bonne version que vous vouliez montrer dans votre réponse?
ajouté l'auteur Adrien, source
Salut Radim, j'ai juste besoin d'écrire un compilateur (pas si simple). Cela vous convient-il de télécharger l'exemple que vous avez assemblé quelque part comme Github? Les gens peuvent trouver cela utile, car il n'est pas facile de jouer avec des exemples existants. Je me demandais juste, merci quand même.
ajouté l'auteur jack, source

Tout d'abord je veux dire que la grammaire C ++ est trop complexe pour Lex/Bison. Le problème ici est principalement dans les conflits de grammaire. Il n'est pas possible d'écrire une grammaire C ++ qui n'en a pas. La norme C ++ l'énonce explicitement et contient des directives sur la façon de les résoudre.

Il n'y a pas de solution générique pour résoudre les conflits de grammaire. En particulier, la résolution des conflits de grammaire pour C ++ requiert des connaissances détaillées sur les identifiants déjà définis. Cela signifie que vous devez avoir une plus grande partie du frontal C ++. Avoir juste la grammaire ne suffit pas.

Néanmoins, la construction d'un AST est possible. Regardez un petit exemple de programme.

class HashEntry
{
private:

      int key;
      int value;

public:

      HashEntry(int key, int value)
      {
            this->key = key;
            this->value = value;
      }

      int getKey() { return key; }

      int getValue() { return value; }
};

const int TABLE_SIZE = 128;

class HashMap
{
private:

      HashEntry **table;

public:

      HashMap()
      {
            table = new HashEntry*[TABLE_SIZE];

            for (int i = 0; i < TABLE_SIZE; i++)
                  table[i] = NULL;
      }

      int get(int key)
      {
            int hash = (key % TABLE_SIZE);

            while (table[hash] != NULL && table[hash]->getKey() != key)
                  hash = (hash + 1) % TABLE_SIZE;

            if (table[hash] == NULL)
                  return -1;
            else
                  return table[hash]->getValue();
      }

      void put(int key, int value)
      {
            int hash = (key % TABLE_SIZE);

            while (table[hash] != NULL && table[hash]->getKey() != key)
                  hash = (hash + 1) % TABLE_SIZE;

            if (table[hash] != NULL)
                  delete table[hash];

            table[hash] = new HashEntry(key, value);
      }     

      ~HashMap()
      {
            for (int i = 0; i < TABLE_SIZE; i++)
                  if (table[i] != NULL)
                        delete table[i];

            delete[] table;
      }
};

And this is an AST for this program: enter image description here

Cet arbre est sévèrement agrandi. Les cercles jaunes sur les feuilles (très petites) sont des symboles terminaux, les cercles verts au milieu ne sont pas des terminaux. Le cercle rose au centre est le TranslationUnit. Cet arbre a 2009 nœuds.

0
ajouté
Salut Kirill, comme je l'ai indiqué dans un autre commentaire, je n'essaie pas d'analyser c ++, je veux juste utiliser bison/flex dans un projet c ++. J'ai une solution maintenant, je vais essayer de fermer cette question.
ajouté l'auteur Radim Cernej, source