Analysieren Sie zitierte Zeichenfolgen mit boost :: spirit

Ich möchte einen Satz analysieren, in dem einige Zeichenfolgen nicht in Anführungszeichen, "Anführungszeichen" oder "Anführungszeichen" stehen. Der folgende Code funktioniert fast - entspricht jedoch nicht den schließenden Anführungszeichen. Ich vermute, das liegt an der qq-Referenz. Eine Änderung wird im Code kommentiert, die Änderung führt dazu, dass "quoted" oder "quoted" ebenfalls analysiert wird, und zeigt, dass das ursprüngliche Problem im schließenden Anführungszeichen liegt. Der Code beschreibt auch die genaue Grammatik.

Um ganz klar zu sein: Nicht zitierte Zeichenfolgen werden analysiert. Eine zitierte Zeichenfolge wie'hello' wird das offene Zitat analysieren'alle Zeichenhello, aber dann nicht das endgültige Zitat zu analysieren'.

Ich habe einen weiteren Versuch unternommen, ähnlich wie beim Start / Ende-TagBoost-Tutorials, aber ohne Erfolg.

<code>template <typename Iterator>
struct test_parser : qi::grammar<Iterator, dectest::Test(), ascii::space_type>
{
    test_parser()
        :
    test_parser::base_type(test, "test")
    {
        using qi::fail;
        using qi::on_error;
        using qi::lit;
        using qi::lexeme;
        using ascii::char_;
        using qi::repeat;
        using namespace qi::labels;
        using boost::phoenix::construct;
        using boost::phoenix::at_c;
        using boost::phoenix::push_back;
        using boost::phoenix::val;
        using boost::phoenix::ref;
        using qi::space;

        char qq;          

        arrow = lit("->");

        open_quote = (char_('\'') | char_('"')) [ref(qq) = _1];  // Remember what the opening quote was
        close_quote = lit(val(qq));  // Close must match the open
        // close_quote = (char_('\'') | char_('"')); // Enable this line to get code 'almost' working

        quoted_string = 
            open_quote
            >> +ascii::alnum        
            >> close_quote; 

        unquoted_string %= +ascii::alnum;
        any_string %= (quoted_string | unquoted_string);

        test = 
            unquoted_string             [at_c<0>(_val) = _1] 
            > unquoted_string           [at_c<1>(_val) = _1]   
            > repeat(1,3)[any_string]   [at_c<2>(_val) = _1]
            > arrow
            > any_string                [at_c<3>(_val) = _1] 
            ;

        // .. <snip>set rule names
        on_error<fail>(/* <snip> */);
        // debug rules
    }

    qi::rule<Iterator> arrow;
    qi::rule<Iterator> open_quote;
    qi::rule<Iterator> close_quote;

    qi::rule<Iterator, std::string()> quoted_string;
    qi::rule<Iterator, std::string()> unquoted_string;
    qi::rule<Iterator, std::string()> any_string;     // A quoted or unquoted string

    qi::rule<Iterator, dectest::Test(), ascii::space_type> test;

};


// main()
// This example should fail at the very end 
// (ie not parse "str3' because of the mismatched quote
// However, it fails to parse the closing quote of str1
typedef boost::tuple<string, string, vector<string>, string> DataT;
DataT data;
std::string str("addx001 add 'str1'   \"str2\"       ->  \"str3'");
std::string::const_iterator iter = str.begin();
const std::string::const_iterator end = str.end();
bool r = phrase_parse(iter, end, grammar, boost::spirit::ascii::space, data);
</code>

Für Bonusguthaben: Eine Lösung, die ein lokales Datenmitglied vermeidet (wie zchar qq in obigem Beispiel) wäre vorzuziehen, aber aus praktischer Sicht verwende ich alles, was funktioniert!

Antworten auf die Frage(1)

Ihre Antwort auf die Frage