[spirit]chset_p("+-*/") vs chset_p("*/+-")
-
//... struct m_parser :public boost::spirit::grammar<m_parser> { static void on_float(float f){std::cout<<f<<' ';}; static void on_char(char c){std::cout<<'('<<c<<')'<<' ';}; static void on_sign(char c){std::cout<<c<<' ';}; template<class ScannerT> struct definition { boost::spirit::rule<ScannerT> r; boost::spirit::rule<ScannerT> const& start()const{return r;}; definition(const m_parser&) { r=*((boost::spirit::real_p[&m_parser::on_float])>>((boost::spirit::chset_p("+-*/")[&m_parser::on_sign])|(boost::spirit::anychar_p)[&m_parser::on_char])>>(boost::spirit::real_p[&m_parser::on_float])); }; }; }; //...
compile run
7+4 7 (+) 4 7-4 7 (-) 4 7*4 7 * 4 7/4 7 / 4
(die jeweils 2. Zeile ist Ausgabe)
r=*((boost::spirit::real_p[&m_parser::on_float])>>((boost::spirit::chset_p("*/+-")[&m_parser::on_sign])|(boost::spirit::anychar_p)[&m_parser::on_char])>>(boost::spirit::real_p[&m_parser::on_float]));
(Nur die Zeile geändert)
compile run
7+4 7 + 4 7-4 7 - 4 7*4 7 * 4 7/4 7 / 4
Was soll das? Ich hab da jetzt mindestens 1h dran gesessen (musste erst mal rausfinden, dass chset scheinbar nix mir chset_p zu tun hat...).
Ich weiß, dass das unleserlich ist, wollte eigentlich nur mal spirit probieren ('s mein erster Versuch), aber das hat mich dann schon stutzig gemacht...
-
Du willst select_p aus <boost/spirit/dynamic/select.hpp>:
namespace bs = boost::spirit; r = *(bs::real_p[&m_parser::on_float] >> bs::select_p(bs::chset_p("+-*/")[&m_parser::on_sign], bs::anychar_p [&m_parser::on_char]) >> bs::real_p[&m_parser::on_float]);
Auf die Art wird garantiert die erste passende pattern gematcht, was bei | nicht der Fall ist.
-
ness schrieb:
r=*((boost::spirit::real_p[&m_parser::on_float])>>((boost::spirit::chset_p("*/+-")[&m_parser::on_sign])|(boost::spirit::anychar_p)[&m_parser::on_char])>>(boost::spirit::real_p[&m_parser::on_float]));
liegt das an der programmiersprache, an der library, an deinem programmierstil oder an was sonst, dass solche zeilen entstehen
-
net schrieb:
liegt das an der programmiersprache, an der library, an deinem programmierstil oder an was sonst, dass solche zeilen entstehen
c++ ist ganz ok. daran liegt's nicht.
der stil würde viellecht erlauben, das in mehrer zeilen zu schreiben. aber ne echte verbesserung ist nicht drin.
die lib ist so schlimm. und es wird täglich schlimmer. die c++-gemeinde hat's nämlich aufgegeben, die sprache zu verbessern (standardisierungskomitee träge wie sonstwas) und rockt jetzt mit templates herum auf der suche nach grenzen.
-
@0xdeadbeef:
thx, schau ich mir später mal an. Warum geht meins nicht?
/edit: zuende lesen wär nicht schlecht...
/nochmaledit: bei mir gehts trotzdem nicht!
/edit: hab die Zeile noch mal veränbdert (semantischer Fehler):r=((boost::spirit::real_p[&m_parser::on_float])>>*(boost::spirit::select_p((boost::spirit::chset_p("+-*/")[&m_parser::on_sign]),(boost::spirit::anychar_p)[&m_parser::on_char])>>(boost::spirit::real_p[&m_parser::on_float])));
Geht nicht.
@net,volkard:
Wo ist das Problem, mit eingebauten features zu machen was geht?
Man kann das ganze auch aufteilen oder besser formatieren, entweder semantisch staffeln oder implizite temp. Variablen explizit aufschreiben...
-
was die lesbarkeit angeht ist die lib wirklich nicht so das gelbe vom ei.
zwar lässt sich noch sehr schön die sytax abbilden, aber sobald auch nur irgendwas mit actors kommt, wirds absolut unlesbar.es gibt zwei Regeln, die ich mir beid er verwendung von spirit aufgestellt hab:
1. bastel dir einen neuen namen für den namespace:
namespace bs=boost::spirit;
2. lagere soviel wie möglich in kleinere rules oder noch besser in subrules aus.
zum thema op| oder spirit::select_p:
ich wär dafür den für genau diesen fall überladenen op|| zu nutzen,da hier beim ersten gelungenen match aufgehört wird.
(zwar genau wie bei select_p, aber der op|| ist wesentlich einfacher zu lesen)floatNumber=bs::real_p[&m_parser::on_float]; sign=bs::chset_p("+-*/")[&m_parser::on_sign]||bs::anychar_p[&m_parser::on_char]; r=floatNumber>>*(sign>>floatNumber);
ist das lesbarer?
-
+-*/ */+- | 7 (+) 4 7 (+) 4 || 7 + 4 7 + (4) | 7 / 4 7 / 4 || 7 / (4) 7 / (4)
Hier noch ein Mitschnitt aus | + "*/+-":
7d5 7 (d) 5 7+4 7 + 4 7*4 7 * 4 7/4 7 / 4 7-4 7 - 4 7^4 7 (^) 4 7+4+5+6 7 + 4 + 5 + 6 7-8*4/6 7 - 8 * 4 / 6 7.8-7.7 7.7 7.8 - 7.7 ( ) 7.7
Sieht gut so aus. Ich denke mal, ich lass das einfach. Ein wenig mulmig ist mir aber doch...
/edit: soh hab ich getestet (übersichtlicher, auch wenn die Namenswahl nicht ganz glücklich ist...struct definition { boost::spirit::rule<ScannerT> r,term,val; boost::spirit::rule<ScannerT> const& start()const{return r;}; definition(const m_parser&) { val=(boost::spirit::real_p[&m_parser::on_float]); term=((boost::spirit::chset_p("*/+-")[&m_parser::on_sign])|(boost::spirit::anychar_p)[&m_parser::on_char]); r=val>>*(term>>val); }; };
-
kann nicht glauben, dass der op|| son müll verzapft
achja, deine Klammerung is auch etwas komisch,vielleicht versteh ich auch nur nicht, wass der sinn dabei ist, hier Klammern zu setzen?
(boost::spirit::anychar_p)[&m_parser::on_char]
andererseits biste aber auch nicht konsequent in der ausführung, denn auf der anderen seite des op| setzt du die klammern anders...
(boost::spirit::chset_p("*/+-")[&m_parser::on_sign])
-
Keine Ahnung. Aber am Anfang hatte ich nicht wirklich gecheckt, wie das Funktioniert, daher hab ich dann halt überall Klammern gesetzt, warum dort, weiß ich nicht. Wollte eigentlich die zweite Variante (dachte vmtl., da gibts probleme mit der Operatorenreihenfolge...)