Bison/Flex tutorial cu C ++, AST și re-entrant atât lexer cât și parser

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

  1. C ++ (nu C) Arbore de sintaxă abstractă.
  2. Lexer reîncărcat.
  3. parser de reintroducere.
  4. Citirea dintr-un șir (față de fișier) ar fi de asemenea plăcută.

Am găsit mai multe exemple și tutoriale, dar fiecare îndeplinește de obicei doar câteva din cerințele de mai sus. Până în prezent, cel mai bun tutorial este din capitolul 3-2 din cartea Oreilly de John Levine - are AST; tot C, întâlnește numai Re_1 de mai sus. Apreciez recomandările pentru exemplele/tutorialele, proiectele open source cu viață reală. De exemplu, am văzut fișierul MySql .yy - arată bine scris, dar prea mare/complex pentru începători ca mine.

0
Vrei să spui codul în C ++? Sau vrei să analizezi C ++?
adăugat autor Ira Baxter, sursa
Vreau ca codul meu care interacționează cu flex/bizon să fie C ++. În special, AST (Tree Syntax Tree). Exemplul menționat depinde de tipul de clemență. În plus, vreau să folosesc STL, etc. În ceea ce încerc să analizez: o sintaxă simplă similară cu expresiile regulate.
adăugat autor Radim Cernej, sursa

2 răspunsuri

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

Multumesc lui Adrien, aici este o versiune arhivată (funcționează din 2017-03-02):

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

0
adăugat
Într-adevăr, webpostul phpcompiler.org a dispărut, mulțumită că mi-a anunțat-o. Am editat răspunsul meu 2012 în consecință.
adăugat autor Radim Cernej, sursa
Îmi pare rău, Jack, nu voi putea să încarc codul sau să ajuți altfel. Vorbim despre 2012 (acum aproape cinci ani), iar IP a fost deținut de angajatorul meu, Fluential Inc/LLC (nu știu dacă este încă în afaceri). De atunci nu am lucrat la parsare și nu-mi amintesc prea mult.
adăugat autor Radim Cernej, sursa
Da, în măsura în care pot spune acest lucru, pare să fie același articol.
adăugat autor Radim Cernej, sursa
Linkul pare să fie mort.
adăugat autor Adrien, sursa
Adresa URL a fost încărcată pe arhivă. org de mai multe ori. Cel mai apropiat instantaneu al site-ului a fost luat pe 2017/05/20, este că versiunea corectă pe care ați intenționat să o afișați în răspunsul dvs.?
adăugat autor Adrien, sursa
Bună Radim, tocmai am întâmplat să scriu un compilator (nu atât de simplu). E bine să încărcați exemplul pe care l-ați adunat undeva, cum ar fi Github? Oamenii pot considera că este util, deoarece exemplele extezitoare nu sunt cu adevărat ușor de jucat. Mă întrebam, oricum, mulțumesc.
adăugat autor jack, sursa

Mai intai vreau sa spun ca gramatica C ++ este prea complexa pentru Lex/Bison. Problema aici este în primul rând în conflictele de gramatică. Nu este posibilă scrierea gramaticii C ++ care nu le are. Standardul C ++ menționează în mod explicit acest lucru și conține câteva linii directoare cu privire la modul de rezolvare a acestora.

Nu există o soluție generică pentru rezolvarea conflictelor gramaticale. În special, rezolvarea conflictelor gramaticale pentru C ++ necesită cunoștințe detaliate despre identificatorii deja definiți. Aceasta înseamnă că trebuie să aveți o parte mai mare a frontului C ++. Având doar gramatica nu este suficient.

Cu toate acestea, este posibilă construirea unui AST. Uită-te la un mic exemplu de program.

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

Acest copac este foarte mic. Cercurile galbene de pe frunze (foarte mici) sunt simboluri terminale, cercurile verde în mijloc nu sunt terminale. Cercul roz în centru este TranslationUnit. Acest arbore are noduri din 2009.

0
adăugat
Bună Kirill, așa cum am arătat într-un alt comentariu, nu încerc să parsez c ++, vreau doar să folosesc bison/flex într-un proiect c ++. Am o soluție acum, voi încerca să închid această întrebare.
adăugat autor Radim Cernej, sursa