Come posso analizzarlo correttamente con lo spirito?
-
19-08-2019 - |
Domanda
La mia situazione: sono nuovo in Spirit, devo usare VC6 e sto usando Spirit 1.6.4.
Ho una linea che assomiglia a questa:
//The Description;DESCRIPTION;;
Voglio mettere il testo DESCRIPTION
in una stringa se la riga inizia con // The Description;
.
Ho qualcosa che funziona ma non mi sembra così elegante:
vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation
if(parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+~ch_p(';'))[assign(vDescription)]
),
// End grammar
space_p).hit)
{
const string desc(vDescription.begin(), vDescription.end());
}
Mi piacerebbe molto di più assegnare tutti i caratteri stampabili al ';'
successivo ma quanto segue non funzionerà perché parse (...). hit == false
parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+print_p)[assign(vDescription)]
>> ';'
),
// End grammar
space_p).hit)
Come faccio a farlo colpire?
Soluzione
Potresti provare a utilizzare confix_p
:
confix_p(as_lower_d["//the description;"],
(+print_p)[assign(vDescription)],
ch_p(';')
)
Dovrebbe essere equivalente a La risposta di Fred .
Il motivo per cui il tuo codice fallisce è perché print_p
è avido . Il parser + print_p
consumerà caratteri fino a quando non incontra la fine dell'input o un carattere non stampabile. Il punto e virgola è stampabile, quindi print_p
lo rivendica. Il tuo input si esaurisce, la variabile viene assegnata e la corrispondenza non riesce & # 8212; non è rimasto nulla che corrisponda all'ultimo punto e virgola del tuo parser.
La risposta di Fred costruisce un nuovo parser, (print_p - ';')
, che corrisponde a tutto ciò che print_p
, tranne i punti e virgola. " Abbina tutto tranne X , quindi abbina X " è un modello comune, quindi confix_p
viene fornito come scorciatoia per costruire quel tipo di parser. La documentazione suggerisce di usarlo per analizzare i commenti in stile C o Pascal, ma non è necessario.
Affinché il tuo codice funzioni, Spirit dovrebbe riconoscere che l'avido print_p
corrispondeva troppo e quindi backtrack per consentire una corrispondenza inferiore. Ma anche se lo Spirito tornerà indietro, non tornerà indietro al "mezzo" di ciò che un sub-parser corrisponderebbe altrimenti avidamente. Tornerà indietro al prossimo "punto di scelta", " ma la tua grammatica non ne ha. Vedi Backtracking esaustivo e goloso RD nella documentazione di Spirit.
Altri suggerimenti
Non hai successo perché ';' è abbinato a print_p. Prova questo:
parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+(print_p-';'))[assign(vDescription)]
>> ';'
),
// End grammar
space_p).hit)