Parser & Lexer in C++

16/01/2013 - 18:56 von Andreas Tscharner | Report spam
Hallo Welt,

In meinem kleinen OpenSource Projekt[1] parse ich eine Datei
zeilenweise. Im Moment geschieht dies mittels fgets und strtok (ugh).
Nun moechte ich das ganze in Zukunft etwas flexibler machen und frage
mich, was heute denn zum Parsen so verwendet wird. Ist das immer noch
Lex und Yacc? Oder gibt's da etwas anderes, bzw. etwas C++ - spezifischeres?

Anforderungen:
* GPL oder kompatibel (um mit GPL verwendet werden zu koennen)
* Entweder auf einem typischen (C++)Entwicklersystem vorhanden oder
klein genug, um allenfalls mit dem Source-Code ausgeliefert werden zu
koennen.

Danke im Voraus
Andreas

[1] https://bitbucket.org/StarFire/lrc/overview
Andreas Tscharner andy@vis.ethz.ch
Gordon's Law:
If you think you have the solution, the question was poorly phrased.
 

Lesen sie die antworten

#1 Edzard Egberts
16/01/2013 - 20:14 | Warnen spam
In meinem kleinen OpenSource Projekt[1] parse ich eine Datei
zeilenweise. Im Moment geschieht dies mittels fgets und strtok (ugh).



*g*

Nun moechte ich das ganze in Zukunft etwas flexibler machen und frage
mich, was heute denn zum Parsen so verwendet wird. Ist das immer noch
Lex und Yacc? Oder gibt's da etwas anderes, bzw. etwas C++ -
spezifischeres?



Ich habe mal geguckt, was Du überhaupt willst und so etwas wie Lex kann
man mit C++ eigentlich recht einfach selber realisieren. Mal so einen
Ansatz mit kleinen Fehlern, weil nicht compiliert, aber die Idee sollte
klar sein:

using namespace std;

typedef int token;
typedef vector< string > td_vector_string;
typedef map< string, token, less< string> > td_map_string_token;
typedef vector< token > td_vector_token;

td_map_string_token TMap; // Mit Map parsen!
TMap["print"]= 1;
TMap["load"]= 2;
TMap["goto"]= 3;

string Zeile; // Zum Einlesen
std::getline(In, Zeile); // Zeile einlesen und zerlegen:
td_vector_string Worte; // die Bestandteile der Zeile
string Wort; // Zum Einlesen
for (unsigned i= 0; i< Zeile.size(); ++i)
if (!whitespace()) Wort.push_back(Zeile[i]);
else {
Worte.push_back(Wort);
Wort.clear();
}
// Mit Map Worte parsen:
td_vector_token VT;
for (unsigned i= 0; i< Worte.size(); ++i)
VT.push_back(TMap[Worte[i]]);

// end

An der Stelle hàtte man in VT für jedes Wort entweder das entsprechende
Token, oder für unbekannte Worte die Null. Na ja, und alle Worte in der
Map, das kann verbessert werden und auch gleich noch die Nummern
auswerten (da braucht man dann ein VT[ struct{ token, double }]).

Also wenn Du auf C-String-Level arbeitest, ist der Schritt auf C++
vielleicht schon ausreichend, so dass Du gar keine Bibliothek brauchst
und trotzdem mit einem Bruchteil des C-Codes hinkommst. Hat eben den
Vorteil, dass man sich die genau passende Lösung schneidern kann...
Die Funktion whitespace() wàre dann natürlich auch ToDo. ;o)

Ähnliche fragen