Frage zu boost:spirit
-
Hallo zusammen,
mit boost kenne ich mich nicht wirklich gut aus, hab mir aber mal einen Parser geschrieben, der soweit auch ganz gut funktioniert. Ein Problem hab ich allerdings noch:
Geparst werden soll eine Datei, die mehrere Nachrichten enthält, die einer bestimmten Syntax unterliegen.
Vereinfacht dargestellt:
Jede Nachricht wird mit dem Schlüsselwort "BO_" eingeleitet. Danach stehen folgende Eigenschaften der Nachticht: ID, Name der Nachricht, ":", Nachrichtenlänge, Name des Senders.
Zusätzlich habe ich mir eine Klasse "Message" geschrieben, die alle diese Eigenschaften enthält. Immer wenn eine Nachricht geparst wird, wird eine neue Instanz der Klasse Message angelegt und die Eigenschaften dort gespeichert. Für jede dieser Eigenschaften existiert also ein Functor Object.Die Datei wird mit einem Header eingeleitet, dann folgt ein Block von mehreren Nachrichten und danach kann kommen was will.
Meine Code sieht nun folgendermaßen aus:
typedef scanner_list<scanner<>, phrase_scanner_t> scanners; rule<scanners> message = str_p("BO_")[ newMessage ] // Functor zum Anlegen einer neuen Instanz >> uint_p[ setId ] // ID wird der aktuellen Instanz zugewiesen >> name_p [ setName ] // eigene rule, name wird gesetzt >> ':' >> uint_p [setLength ] // Functor für Nachrichtenlänge >> sender_p [ setSenderName ]; // eigene rule, Functor für Sendername // rule für gesamte datei rule<scanners> file_parser = header_p // eigene rule >> (*messages) >> *(anychar_p) >> end_p; // parse Aufruf parse_info<> info = parse(buffer, file_parser, space_p);Die zu parsende Datei sieht beispielsweise und vereinfacht so aus:
Header...
BO_ 100 Nachricht1 : 10 Sender1
BO_ 200 Nachricht2 : 20 Sender2
BO_ZUSÄTZLICHE_ZEICHEN 333 : text1, text2;Restlicher Text
Folgender Fehler tritt nun beim Parsen auf:
Zwei Nachrichten werden korrekt abgespeichert. Bei der dritten Zeile wird fälschlicherweise noch mal der newMessage Functor aufgerufen, obwohl diese Zeile eindeutig nicht der message-rule entspricht und die Stelle an der der Functor aufgerufen wird eigentlich gar nicht erreicht werden dürfte.Was mache ich falsch? Ich hoffe es kann mir jemand weiter helfen.
Vielen Dank,
markus
-
Es ist zwar schon eine Weile her, seitdem ich mich mit Spirit beschäftigt habe. Aber afair wird die Aktion ausgeführt, sobald die zugehörige Teilregel zugeschlagen hat (unabhängig davon, ob die Gesamtregel letztendlich etwas gefunden hat). Und in deinem Fall hat der str_p() zugeschlagen und einen (aus seiner Sicht) gültigen Zeilenanfang entdeckt.
Wie man das umgehen kann, weiß ich auf Anhieb leider nicht (vielleicht entdeckt ja Tobia Gerg deine Frage) - als Workaround würde ich an das (*anycahr_p) eine Aktion anhängen, die die eventuell überflüssig erzeugte Message wieder beseitigt.
-
Vielen Dank schonmal. Den Workaround werde ich mal überdenken und währenddessen Tobias Gerg "hertelepathisieren".
Gruß
markus
-
Was ist, wenn Du die Werte in einer temporären Instanz ablegst und erst dann die echte Message erzeugst, wenn sie vollständig geparst ist? Also die Aktion erst in die file_parser-Regel reinschreibst?
-
Gute Idee! So hab ich es jetzt gemacht.
Mich würde trotzdem noch interessieren, ob man das auch irgendwie auf dem ersten Weg realisieren könnte. So, dass die Funktionsobjekte aus der message-rule nur aufgerufen werden, wenn es tatsächlich eine message ist.Vielen Dank für eure Tipps,
markus
-
Hm, wie sieht sender_p aus?
evtl. hilft schon ein (*anychar -eol_p), damit liest du dann alles ein, bis zum Zeilenende.
Aber generell wäre es hilfreich alle Regeln zu sehen die du definiert hast.