PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : boost::spirit grammar/parser/rule/subrule ...


zeckensack
2005-06-03, 23:56:10
Ich habe jetzt irgendwie nicht ganz gerafft, was ich wann verwenden soll und warum. Überhaupt scheinen die Junx darauf zu stehen, möglichst viele unterschiedliche Methoden für alles mögliche anzubieten :ugly2:

Was ich bis hierhin kapiert habe, ist dass massiver Einsatz von subrule den Compiler stark stresst, und deswegen eher rule zu benutzen ist.
Andererseits kommt's mir so vor, als ob ich überall wo ich rule einsetzen kann, genauso gut parser nehmen kann. In den Beispielen wird da bunt gemischt, einen wirklichen Unterschied kann ich nur insofern erkennen, als dass rule "kein echtes Objekt" ist, nicht kopierbar und nicht speicherbar ist, parser allerdings schon.

Also für mich liest sich das so als ob subrule gefährlich und rule für'n Arsch ist, und ich am besten nur parser benutzen sollte.

Es sei denn ich habe etwas wichtiges übersehen. Wisst ihr's? =)

PS: das wird eine große Grammatik. Ungefähr so wie C (ohne ++).

Pinoccio
2005-06-04, 02:04:45
Könntest du einem völlig Unwissenden einen Hauch von Ahnung vermitteln, wovon du redest? ;-)

mfg Sebastian

Chris Lux
2005-06-04, 02:44:32
oh ich kann mir dir fühlen. ich hab das auch schon alles durch. aber ich find die doku ist sehr gut gemacht von spirit.

zu subrule. ich würde/habe dies nur für kleine sachen verwendet, weil, wie du schon sagst, dies den compiler extrem stresst. meine erfahrung ist folgende. nutze grammatik derivate und schaffe dir damit kleinere 'unterparser', wie zb eine grammatik, die beschreibt wie identifier aussehen. diese grammatiken kannst du dann nutzen, um deine gößeren zusammenzusetzen. diese unterparser kannst du auch xbeliebig oft nutzen. in den gramatiken habe ich immer rules genutzt. so wie ich das verstanden habe (und mich noch erinnern kann) sind parser super{klassen|templates} ;) von rules. das nette mit den grammatiken ist, dass man sie nutzen kann, um einen AST sehr strukturiert aufzubauen und auswertungsfunktionen für die einzelnen grammatiken schreiben kann, in die verzweigt werden kann und somit dieser code auch schön leserlich ist ;).

achja, subrules hab ich genutzt um unabhängig von einem bestimmten scannertyp für die ganze rule zu werden. im beispiel unten war das nötig für die lexeme_d direktive, welche character level parsing forciert (dh leerzeichen werden nicht übersprungen). hätte ich dies mit normalen rules (für ident, non_digit, digit) gemacht, müsste man schon den scannertyp direkt wissen und angeben, so wird der typ zur compilezeit bestimmt (obwohl ich glaube es war dem compiler nur zuviel in der anderen herangehensweise, frag mich nicht ;) aber spirit is schon extrem hart an der grenze des verständlichen und für compiler machbaren -> siehe die compilerfehler bei kleineren ungereimtheiten).

bsp. grammatik für parameter namen (_a-zA-Z und 0-9 und leerzeichen)

struct parameter_name_grammar : public boost::spirit::grammar<parameter_name_grammar>
{
template <typename ScannerT>
struct definition
{
definition( parameter_name_grammar const & )
{
using boost::spirit::ch_p;
using boost::spirit::chset_p;
using boost::spirit::lexeme_d;
using boost::spirit::token_node_d;

// using subrules, to be independent of a specific scannertype
// while using the lexeme directive to do character level parsing
identifier = token_node_d[
lexeme_d[
( ident = non_digit >> *(non_digit | digit | ch_p(' ')),
non_digit = chset_p("_a-zA-Z"),
digit = chset_p("0-9"))
]
];
}

typedef typename boost::spirit::rule<ScannerT> rule_t;

rule_t const & start() const
{
return identifier;
}

private:
boost::spirit::subrule<0> ident;
boost::spirit::subrule<1> non_digit;
boost::spirit::subrule<2> digit;

rule_t identifier;
};
};


ich hoffe das beispiel hilft zu erklären was ich meine. wie gesagt find ich ist dies eine sehr saubere herangehensweise für größere grammatiken.

@pinoccio:

http://www.boost.org/libs/spirit/index.html

spirit ist ein sehr nützliches parsing framwork, welches es erlaubt grammatiken durch excessives operator overloading und templateing in c++ syntax aufzuschreiben und zur compilezeit aus diesen extrem effiziente parser zu generieren. schaus dir ruhig mal an, auch wenn es auf den ersten blick wirklich konfus wirkt... naja auch auf den zweiten und dritten ;)

micki
2005-06-04, 06:55:05
PS: das wird eine große Grammatik. Ungefähr so wie C (ohne ++).
irgendwo hab ich mal gelesen (sorry, ich kann mich beim besten willen nicht an die quelle erinnern), dass man spirit zum parsen von kleinen bis mittleren grammern nutzen sollte, soll nicht für große dinge gedacht sein...


nein ich kann dazu nicht mehr wissen beisteuern, aber bevor du dir ein bein abbricht kannst man ja mal schauen was andere hierzu meinen ;)

MfG
micki

zeckensack
2005-06-04, 12:11:24
Könntest du einem völlig Unwissenden einen Hauch von Ahnung vermitteln, wovon du redest? ;-)

mfg SebastianErster Treffer bei Google (http://www.google.com/search?q=boost::spirit). Das hier ist schließlich das Programmierforum :ugly:

Sry dass ich im Titel den Bindestrich zwischen Themenkomplex und Problemstellung vergessen habe :ugly2:

zeckensack
2005-06-04, 12:35:00
oh ich kann mir dir fühlen. ich hab das auch schon alles durch. aber ich find die doku ist sehr gut gemacht von spirit.

zu subrule. ich würde/habe dies nur für kleine sachen verwendet, weil, wie du schon sagst, dies den compiler extrem stresst. meine erfahrung ist folgende. nutze grammatik derivate und schaffe dir damit kleinere 'unterparser', wie zb eine grammatik, die beschreibt wie identifier aussehen.Ja klar =)

Die Frage ist ja welche Basisklassen konkret ich benutzen sollte, weil es ja im Prinzip zwei "unstressige" und eine "stressige" Möglichkeit gibt. Und dass da bunt gemischt werden kann, kann ich auch gut am "verwirrten" Rest deines Postings ablesen, der genauso unpräzise auf meine Frage antwortet wie die spirit-Doku selbst. Sry :ugly2:
... aberdiese grammatiken kannst du dann nutzen, um deine gößeren zusammenzusetzen. diese unterparser kannst du auch xbeliebig oft nutzen. in den gramatiken habe ich immer rules genutzt. so wie ich das verstanden habe (und mich noch erinnern kann) sind parser super{klassen|templates} ;) von rules. das nette mit den grammatiken ist, dass man sie nutzen kann, um einen AST sehr strukturiert aufzubauen und auswertungsfunktionen für die einzelnen grammatiken schreiben kann, in die verzweigt werden kann und somit dieser code auch schön leserlich ist ;).Mal davon abgesehen habe, dass ich durchaus weiß wie eine Grammatik hierarchisch zu strukturieren ist: du wechselst hin und her zwischen Grammatik, parser und rule. Es habe bisher nicht erkannt, wo und warum man sinnvoll die Hierarchie anfängt und enden lässt.
Und deine Antwort kommt mir so vor, als wäre es dir genau so unklar wie mir.
Im Prinzip könnte ich alles mit parser machen. Scheint mir auch am problemlosesten zu sein, weil rule viele Einschränkungen hat (aber nichts besser kann?!).
achja, subrules hab ich genutzt um unabhängig von einem bestimmten scannertyp für die ganze rule zu werden. im beispiel unten war das nötig für die lexeme_d direktive, welche character level parsing forciert (dh leerzeichen werden nicht übersprungen). hätte ich dies mit normalen rules (für ident, non_digit, digit) gemacht, müsste man schon den scannertyp direkt wissen und angeben, so wird der typ zur compilezeit bestimmt (obwohl ich glaube es war dem compiler nur zuviel in der anderen herangehensweise, frag mich nicht ;)IMO nicht nötig.
Du kannst mit lexeme_d alles kapseln, was nicht explizit das Gegenteil möchte.
Also wieder mal parser, rule, subrule ...
Wenn eins davon explizit das Gegenteil möchte, dann klappt das nicht mehr. Diese Problem tritt aber nur auf, indem du (zB) rule <lexeme_scanner<>::type> konstruierst. Auch hier gibt's wieder zwei Möglichkeiten eine Sache zu erreichen. Die eine funktioniert immer, und die andere verhindert das funktionieren der ersten Variante. Was das überhaupt soll, würde ich auch gerne mal wissen, muss aber nicht unbedingt heute sein.

Den Rest kommentiere ich mal nicht, habe ihn aber zur Kenntnis genommen. Auf jeden Fall schonmal danke :)

zeckensack
2005-06-04, 12:38:36
irgendwo hab ich mal gelesen (sorry, ich kann mich beim besten willen nicht an die quelle erinnern), dass man spirit zum parsen von kleinen bis mittleren grammern nutzen sollte, soll nicht für große dinge gedacht sein...


nein ich kann dazu nicht mehr wissen beisteuern, aber bevor du dir ein bein abbricht kannst man ja mal schauen was andere hierzu meinen ;)

MfG
mickiIch werde einfach mal sehen, wie weit mich GCC3.4.2 trägt. Auch wenn's nicht reicht, bin ich um eine Erfahrung reicher :ugly2:

Chris Lux
2005-06-04, 13:18:30
Ja klar =)
... aberMal davon abgesehen habe, dass ich durchaus weiß wie eine Grammatik hierarchisch zu strukturieren ist: du wechselst hin und her zwischen Grammatik, parser und rule. Es habe bisher nicht erkannt, wo und warum man sinnvoll die Hierarchie anfängt und enden lässt.
Und deine Antwort kommt mir so vor, als wäre es dir genau so unklar wie mir.
Im Prinzip könnte ich alles mit parser machen. Scheint mir auch am problemlosesten zu sein, weil rule viele Einschränkungen hat (aber nichts besser kann?!).

verzeih mir, es war sehr spät und ich war extrem auf coffein nach ner langen autofahrt ;)

ich habe so oft zwischen den begriffen gewechselt, weil einfach mit spirit eine grammatik nicht gleich einer ganzen grammatik entspricht sondern wieder einem spirit-parser, den man wiederum an vielen stellen verwenden kann. es tut mir leid, wenn ich nicht helfen konnte, aber spirit ist (wie du auch bemerkt hast) extrem konfus, einfach weil mit der c++ syntax sachen gemacht werden, für die sie IMO nie gedacht war. dies sieht man auch an den endlosen template konstrukten die man bauen kann ohne ab einem bestimmten punkt zu wissen was man da eigentlich macht. sicherlich kannst du alles mit parser machen, jedoch sind rule, subrule und grammar dafür da hässliche sachen zu kapseln und somit schöner strukturierbar zu machen. mehr wollte ich nicht aussagen mit meinem posting.

ich kann mich wirklich nicht mehr genau erinnern welche probleme ich genau hatte und somit die subrules genutzt habe in dem beispiel. gerade bei so einer syntax/semantik-gradwanderung die spirit darstellt kann es auch sein, dass verschiedene compiler manche sachen nicht mögen (ich nutzte den VS7.1 C++ compiler).

Edit:
achja, mir ist auch klar wie man eine grammatik strukturiert, aber wie du gemerkt hast gibt es mit spirit sehr viele, um dies zu erreichen. rule/subrule/grammer usw sind dabei nur werkzeuge. klar werden in der hierarchie parser-rule-subrule die möglichkeiten immer weiter eingeschränkt aber sie besitzen IMO alle ihre daseinsberechtigung. du musst sie jedoch nicht alle nutzen ;)

maximAL
2005-06-04, 13:57:24
was genau spirit jetzt soll hab ich auch nie wirklich verstanden. parser, hmm?ist das etwa ein notdüftiger ersatz für eine funktionale sprache?

zeckensack
2005-06-04, 15:48:32
verzeih mir, es war sehr spät und ich war extrem auf coffein nach ner langen autofahrt ;)

ich habe so oft zwischen den begriffen gewechselt, weil einfach mit spirit eine grammatik nicht gleich einer ganzen grammatik entspricht sondern wieder einem spirit-parser, den man wiederum an vielen stellen verwenden kann. es tut mir leid, wenn ich nicht helfen konnte, aber spirit ist (wie du auch bemerkt hast) extrem konfus, einfach weil mit der c++ syntax sachen gemacht werden, für die sie IMO nie gedacht war. dies sieht man auch an den endlosen template konstrukten die man bauen kann ohne ab einem bestimmten punkt zu wissen was man da eigentlich macht. sicherlich kannst du alles mit parser machen, jedoch sind rule, subrule und grammar dafür da hässliche sachen zu kapseln und somit schöner strukturierbar zu machen. mehr wollte ich nicht aussagen mit meinem posting.Jo :)
Ich mach's einfach erstmal irgendwie ;)
Ich hatte nur gehofft, es gibt da einen "besten" Einstiegspunkt.
ich kann mich wirklich nicht mehr genau erinnern welche probleme ich genau hatte und somit die subrules genutzt habe in dem beispiel.Ich weiß es aber mittlerweile.
using namespace boost::spirit;
//kompiliert nicht
rule<ScannerT> identifier=lexeme_d[nondigit&&(*(nondigit|digit))]-reserved_word;

//kompiliert
subrule<0> identifier=lexeme_d[nondigit&&(*(nondigit|digit))]-reserved_word;Warum das so ist, verstehe ich nicht :|
gerade bei so einer syntax/semantik-gradwanderung die spirit darstellt kann es auch sein, dass verschiedene compiler manche sachen nicht mögen (ich nutzte den VS7.1 C++ compiler).

Edit:
achja, mir ist auch klar wie man eine grammatik strukturiert, aber wie du gemerkt hast gibt es mit spirit sehr viele, um dies zu erreichen. rule/subrule/grammer usw sind dabei nur werkzeuge. klar werden in der hierarchie parser-rule-subrule die möglichkeiten immer weiter eingeschränkt aber sie besitzen IMO alle ihre daseinsberechtigung. du musst sie jedoch nicht alle nutzen ;)EBNF oder Grammatik-Definitionen im allgemeinen sind ja sowieso schon hierarchisch, baumartige Komposita. Eben deswegen habe ich so große Probleme damit zu verstehen, wieso es bei spirit mehrere Typen für Grammatik/Parser/Regeln/weißderteufel gibt. Es würde ja vom Konzept her ausreichen, dass jeder Knoten in dem Baum den gleichen Typ hat, und die Wurzel sich nur dadurch von den anderen unterscheidet, dass sie keine übergeordneten Knoten hat.

Terminale/Nonterminale, wo ich die Unterscheidung noch verstehen würde, scheinen spirit dagegen einen Dreck zu scheren.

Anstrengend das zu sein scheint.

Pinoccio
2005-06-05, 16:51:58
Erster Treffer bei Google (http://www.google.com/search?q=boost::spirit). Das hier ist schließlich das Programmierforum
Google: boost::spirit grammar/parser/rule/subrule ... (http://www.google.com/search?q=boost%3A%3Aspirit+grammar%2Fparser%2Frule%2Fsubrule+...): 0 Treffer. :P
Bei Google Teile der Überschrift einzugeben setzt Wissen vorraus, welche Teile sinnvoll sind. Wer sagt mir, daß diese Variante (http://www.google.com/search?q=grammar%2Fparser%2Frule%2Fsubrule), diese (http://www.google.com/search?q=spirit+rule) oder gar diese Formulierung (http://www.google.com/search?q=%22Zeckensacks+Problem%22) mir nicht weiterhelfen? Und alle Varianten auszuprobieren? Da frag ich leiber und hoffe, noch was zu lernen. Das hier ist schließlich ein Forum.
Gelernt habe ich, daß boost::spirit so kompliziert ist, daß viele Anwender meist nicht wissen wie was geht und manche es noch nichtmal in höflichen Worten anderen erklären können.@pinoccio:

http://www.boost.org/libs/spirit/index.html

spirit ist ein sehr nützliches parsing framwork, welches es erlaubt grammatiken durch excessives operator overloading und templateing in c++ syntax aufzuschreiben und zur compilezeit aus diesen extrem effiziente parser zu generieren. schaus dir ruhig mal an, auch wenn es auf den ersten blick wirklich konfus wirkt... naja auch auf den zweiten und dritten ;)Danke! Anschauen ja, aber nicht mit dem Hintergedanken, selber mal damit was anzufangen. Da bleibe ich lieber bei meiner Mathematik, die ist nicht ganz so konfus.

mfg Sebastian

zeckensack
2005-06-05, 19:55:05
Google: boost::spirit grammar/parser/rule/subrule ... (http://www.google.com/search?q=boost%3A%3Aspirit+grammar%2Fparser%2Frule%2Fsubrule+...): 0 Treffer. :P
Bei Google Teile der Überschrift einzugeben setzt Wissen vorraus, welche Teile sinnvoll sind. Wer sagt mir, daß diese Variante (http://www.google.com/search?q=grammar%2Fparser%2Frule%2Fsubrule), diese (http://www.google.com/search?q=spirit+rule) oder gar diese Formulierung (http://www.google.com/search?q=%22Zeckensacks+Problem%22) mir nicht weiterhelfen? Und alle Varianten auszuprobieren? Da frag ich leiber und hoffe, noch was zu lernen. Das hier ist schließlich ein Forum.
Gelernt habe ich, daß boost::spirit so kompliziert ist, daß viele Anwender meist nicht wissen wie was geht und manche es noch nichtmal in höflichen Worten anderen erklären können.Tut mir leid, war nicht bös' gemeint ;(
Ich hatte mich ja schon dafür entschuldigt, dass der Bindestrich fehlte. Das macht das Googeln tatsächlich unnötigt schwer :redface:

Ja, spirit ist ein Inline-Parsergenerator (also kein Parser-Code-Generator). Nachdem ich jetzt zwei Tage damit rumgefrickelt habe, freue ich mich schon mächtig darauf, meine Grammatik dann doch lieber klassisch mittels Flex und Bison zu parsen ...

Gast
2006-01-22, 11:57:34
Jo :)
Ich mach's einfach erstmal irgendwie ;)
Ich hatte nur gehofft, es gibt da einen "besten" Einstiegspunkt.
Ich weiß es aber mittlerweile.
using namespace boost::spirit;
//kompiliert nicht
rule<ScannerT> identifier=lexeme_d[nondigit&&(*(nondigit|digit))]-reserved_word;

//kompiliert
subrule<0> identifier=lexeme_d[nondigit&&(*(nondigit|digit))]-reserved_word;Warum das so ist, verstehe ich nicht :|
EBNF oder Grammatik-Definitionen im allgemeinen sind ja sowieso schon hierarchisch, baumartige Komposita. Eben deswegen habe ich so große Probleme damit zu verstehen, wieso es bei spirit mehrere Typen für Grammatik/Parser/Regeln/weißderteufel gibt. Es würde ja vom Konzept her ausreichen, dass jeder Knoten in dem Baum den gleichen Typ hat, und die Wurzel sich nur dadurch von den anderen unterscheidet, dass sie keine übergeordneten Knoten hat.

Terminale/Nonterminale, wo ich die Unterscheidung noch verstehen würde, scheinen spirit dagegen einen Dreck zu scheren.

Anstrengend das zu sein scheint.

zeckensack
2006-01-22, 12:47:31
Hmmm? War das ein Unfall? Und wenn ja, welche Sorte Unfall?

Coda
2006-01-22, 12:52:40
was genau spirit jetzt soll hab ich auch nie wirklich verstanden. parser, hmm?ist das etwa ein notdüftiger ersatz für eine funktionale sprache?Nein. Das ist ein Parser-Generator der als Metasprache direkt in C++ verwendet werden kann. Also im Prinzip das gleiche wie Bison/Flex nur ohne extra Kompilierschritt.

Allerdings sind das böse Freaks die das Implementiert haben und das ganze Ding ist ein herrliches Monster :D

mekakic
2009-03-04, 13:23:22
Ich frage mich ob boost::spirit taugliche ist, für das was ich vorhabe. Das wäre eine relativ einfache Grammatik zu parsen (zeilenorientiert, schlüsselwort immer am anfang einer zeile, danach einige werte mit weiteren wenigen schlüsselwörtern). Aus einer Eingabedatei in dieser Grammatik möchte ich dann C++ Code Generieren.

Zu parsen wäre es auch so recht leicht, aber ich wollte mich schon länger mal an spirit probieren. Mir ist nur noch nicht klar, was es leisten kann. Wenn ich eine EBNF Sprachdefinition Boost übergeben habe, habe ich dann hierarchischen Zugriff auf verschiedene, benamste Felder? Kann ich über bestimmte Schlüsselwörter und deren Vorkommen iterieren?

danke

Coda
2009-03-04, 15:15:51
Man kann einen AST generieren lassen, also einen abstrakten Syntaxbaum.

mekakic
2009-03-12, 15:22:51
Danke. Habe mich heute morgen dran gesetzt und angefangen Spirit erstmal aufzusetzen und mich einzulesen, dann habe ich die EBNF Grammatik des Sprache formuliert. Nun läuft der (rudimentäre) Parser bereits und ich kriege das Grinsen gar nicht mehr aus meinem Gesicht, wie klasse und komfortabel das funktioniert. :D

Bin zwar noch nicht fertig, aber daß es so schnell schon so gut läuft hätte ich nicht gedacht.

Chris Lux
2009-03-17, 09:39:41
ich habe spirit jetzt schon eine weile nicht mehr angefasst. in der boost 1.38 ist ja scheinbar die spirit v2 schon enthalten und das ganze 1.8.x zeug ist in boost::spirit::classic gewandert. aber eine doku zu v2 gibt es scheinbar noch nicht.

v2 sollte ein wenig aufraeumen in diesem monster von bibliothek. welche version nutzt du denn jetzt? und gibt es eine doku zu v2 irgendwo?