[spirit] Zusammengesetzte Typen parsen : functor_parser bringt viel Redundanz



  • Hi,

    mir ist im XML-Thread aufgefallen, dass hier scheinbar einige spirit-Profis unterwegs sind. Ich habe ein (für mich) unlösbares Problem:

    Mein Format, welches ich parsen will könnte z.B. so aus sehen...

    Beispiel:

    auto [
     farbe : 0xFF0033
     leistung : 65.0
     ...
    ]
    
    lkw
    [
      farbe : 0xEEF024
      leistung : 320.5
      ladefläche : 23.0
      ...
    ]
    

    Nun teilen sich LKW und Auto ja offensichtlich einige Attribute. Mein erster Ansatz sah so aus, dass ich quasi nur mit functor-Parsern gearbeitet habe:

    struct AutoParser
    {
    	typedef boost::shared_ptr<Auto> result_t;
    
    	template<typename ScannerType>
    	std::ptrdiff_t operator()(const ScannerType& scan, result_t& result) const
    	{
    		if(scan.at_end())
    			return -1;
    
    		result_t ptr(new Auto);
    		Auto& ref = static_cast<Auto&>(*ptr);
    
    		parse_info<typename ScannerType::iterator_t> info = 
    		parse(scan.first, scan.last, str_p("auto") >> '[' >> *(
    			(str_p("farbe")		>> ':' >> color_p[assign_a(ref.farbe)])	|
    			(str_p("leistung")	>> ':' >> real_p[assign_a(ref.leistung)])	|
    		) >> ']', skip_p);
    
    		if(info.hit)
    		{
    			result = ptr;
    			scan.first = info.stop;
    			return info.length;
    		}
    
    		return -1;
    	}
    };
    
    struct LKWParser
    {
    	typedef boost::shared_ptr<Auto> result_t;
    
    	template<typename ScannerType>
    	std::ptrdiff_t operator()(const ScannerType& scan, result_t& result) const
    	{
    		if(scan.at_end())
    			return -1;
    
    		result_t ptr(new LKW);
    		LKW& ref = static_cast<LKW&>(*ptr);
    
    		parse_info<typename ScannerType::iterator_t> info = 
    		parse(scan.first, scan.last, str_p("lkw") >> '[' >> *(
    			(str_p("farbe")			>> ':' >> color_p[assign_a(ref.farbe)])		|
    			(str_p("leistung")		>> ':' >> real_p[assign_a(ref.leistung)])	|
    			(str_p("ladefläche")	>> ':' >> real_p[assign_a(ref.ladeflaeche)])	|
    		) >> ']', skip_p);
    
    		if(info.hit)
    		{
    			result = ptr;
    			scan.first = info.stop;
    			return info.length;
    		}
    
    		return -1;
    	}
    };
    

    Das sieht für mich alles sehr redundant aus, aber selbst nach stundenlangem büffeln der spirit-Doku ist mir kein Weg eingefallen da etwas zu sparen.

    BTW: Wie findet ihr den Weg, wie ich den Functor-Parser implementiert habe, also mit dem shared_ptr, der sich automatisch zerstört, wenn das parsen fehlschlägt? Die zusammengesetzten Objekte die in meiner tatsächlichen Anwendung geparst werden können ziemlich groß werden, weswegen ich kein Fan von großer Kopiererei an dieser Stelle war.

    Ich hoffe hier kann mir jemand helfen...

    Viele Grüße,

    Dennis



  • Hi,

    schau dir doch einfach mal http://boost.org/libs/spirit/doc/grammar.html das genau an

    MfG



  • Das Problem an einer Grammar ist, dass es dort nich ganz trivial ist das Objekt auch tatsächlich herauszulesen, weswegen ich sie bislang nur für kleinere Syntaxchecks eingesetzt habe. Ich habe nicht herausgefunden, wie ich das am geschicktesten lösen kann: Eigentlich will ich nur die Objekte auslesen und in eine liste einfügen.


Anmelden zum Antworten