Ich arbeite daran zu lernen, Spirit Grammatiken zu schreiben, und ich versuche, eine Basis Basis 16 zu Base 64-Konverter erstellen, die eine Zeichenfolge für Hexadezimalwerte, zum Beispiel:Spirit Grammar Um eine Zeichenfolge durch die Anzahl der Zeichen aufzuteilen
parse out 6 oder weniger Zeichen (weniger, wenn die Zeichenfolge nicht ein perfektes Vielfaches von 6 ist) und generieren Sie eine Base 64 codierte Zeichenfolge aus dem Eingang. Eine Grammatik Ich dachte, würde wahrscheinlich funktionieren etwas wie folgt aus:
// 6 characters
`(qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >>
qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >>
qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F")[/*action*/]) |
// or 5 characters
(qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >>
qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >>
qi::char_("0-9a-fA-F")[/*action*/]) | ...`
etc .... den ganzen Weg hinunter zu einem Zeichen oder eine andere Regel für jede Anzahl von Zeichen definiert ist, aber ich denke, es muss sein eine bessere Möglichkeit, die Grammatik zu spezifizieren. Ich las über Spirit Repeat und dachte, ich könnte vielleicht etwas wie +(boost::spirit::repeat(1, 6)[qi::char_("0-9a-fA-F")][/*action on characters*/])
aber der Compiler wirft einen Fehler auf diesem, wegen der sematic Aktion Teil der Grammatik. Gibt es eine einfachere Möglichkeit, eine Grammatik anzugeben, die auf genau 6 oder weniger Zeichen gleichzeitig angewendet werden kann?
bearbeiten Hier ist, was ich bisher ... base16convertergrammar.hpp
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
#include <iostream>
namespace grammar {
namespace qi = boost::spirit::qi;
void toBase64(const std::string& p_input, std::string& p_output)
{
if (p_input.length() < 6)
{
// pad length
}
// use back inserter and generator to append to end of p_output.
}
template <typename Iterator>
struct Base16Grammar : qi::grammar<Iterator, std::string()>
{
Base16Grammar() : Base16Grammar::base_type(start, "base16grammar"),
m_base64String()
{
// get six characters at a time and send them off to be encoded
// if there is less than six characters just parse what we have
start = +(boost::spirit::repeat(1, 6)[qi::char_("0-9a-fA-F")][boost::phoenix::bind(toBase64, qi::_1,
boost::phoenix::ref(m_base64String))]);
}
qi::rule<Iterator, std::string()> start;
std::string m_base64String;
};
}
Und hier getan haben, ist die Verwendung ... base16converter.cpp
#include "base16convertergrammar.hpp"
const std::string& convertHexToBase64(const std::string& p_hexString)
{
grammar::Base16Grammar<std::string::const_iterator> g;
bool r = boost::spirit::qi::parse(p_hexString.begin(), p_hexString.end(), g);
}
int main(int argc, char** argv)
{
std::string test("49276d206b696c6c");
convertHexToBase64(test);
}
Ich weiß nicht, ob es ein Fehler ist, während transkribieren, aber in Ihrem Beispiel der Semantische Aktionen werden nur an den letzten Ihrer Zeichen angehängt, während Sie den Rest ignorieren. Die von Ihnen vorgeschlagene Alternative sollte funktionieren und ein Attribut "vector" haben. Es wäre einfacher (und besser für Sie), wenn Sie ein (fast) vollständiges Beispiel angeben würden. –
llonesmiz
Ich habe hinzugefügt, was ich bisher habe. – joshu