2016-04-04 11 views
0

Ich schreibe einen kleinen Compiler nur zum Spaß und ich benutze Boost Spirit Qi, um meine Grammatik zu beschreiben. Jetzt möchte ich eine kleine Änderung in der Grammatik vornehmen, um einige weitere Ergänzungen vorzubereiten. Leider werden diese Änderungen nicht kompiliert und ich würde gerne verstehen, warum das so ist.Boost Spirit Qi: Kompilierfehler bei geringfügiger Regeländerung

Hier ist ein Ausschnitt aus dem Code, den ich ändern möchte. Ich hoffe, dass die bereitgestellten Informationen ausreichen, um die Idee zu verstehen. Der vollständige Code ist ein bisschen groß, aber wenn Sie ihn anschauen oder sogar testen wollen (Makefile und Travis CI wird mitgeliefert), siehe https://github.com/Kruecke/BFGenerator/blob/8f66aa5/bf/compiler.cpp#L433.

typedef boost::variant< 
    function_call_t, 
    variable_declaration_t, 
    variable_assignment_t, 
    // ... 
> instruction_t; 

struct grammar : qi::grammar<iterator, program_t(), ascii::space_type> { 
    grammar() : grammar::base_type(program) { 
     instruction = function_call 
        | variable_declaration 
        | variable_assignment 
       // | ... 
        ; 

     function_call = function_name >> '(' > -(variable_name % ',') > ')' > ';'; 
     // ... 
    } 

    qi::rule<iterator, instruction::instruction_t(), ascii::space_type> instruction; 
    qi::rule<iterator, instruction::function_call_t(), ascii::space_type> function_call; 
    // ... 
}; 

Bis jetzt funktioniert alles nur gut. Jetzt möchte ich das Parsen des abschließenden Semikolons (> ';') von der function_call Regel zur instruction Regel verschieben. Mein Code sieht nun wie folgt aus:

struct grammar : qi::grammar<iterator, program_t(), ascii::space_type> { 
    grammar() : grammar::base_type(program) { 
     instruction = (function_call > ';') // Added trailing semicolon 
        | variable_declaration 
        | variable_assignment 
       // | ... 
        ; 

     // Removed trailing semicolon here: 
     function_call = function_name >> '(' > -(variable_name % ',') > ')'; 
     // ... 
    } 

Von meinem Verständnis haben die Regeln nicht wirklich geändert, weil der Charakter-Parser ';' keine Attribut ergeben und so sollte es keine Rolle, wo diese Parser positioniert ist. Allerdings wird diese Änderung nicht kompilieren:

/usr/include/boost/spirit/home/support/container.hpp:278:13: error: no matching function for call to ‘std::basic_string<char>::insert(std::basic_string<char>::iterator, const bf::instruction::function_call_t&)’ 
      c.insert(c.end(), val); 
      ^

(Dieser Fehler kommt von der instruction = ... Linie.)

Warum ist diese Änderung Kompilieren nicht? Ich bin eher auf der Suche nach einer Erklärung, um zu verstehen, was vor sich geht, als ein Workaround.

Antwort

2

Ok, also nach genauer Betrachtung versuchen Sie, mehrere Zeichenfolgen in Ihren function_call_t-Typ einzufügen, der eine Fusionssequenz ist, die in eine einzige std :: string konvertiert werden kann. Wahrscheinlich werden Sie jedoch Probleme mit der Funktion function_call bekommen, weil das Attribut tatsächlich tuple <std::string, optional <vector <std::string>>> ist. Ich könnte mir vorstellen, dass der Geist Probleme hat, diese Struktur abzuflachen, und das verursacht Ihr Problem, aber ich habe keinen Compiler, um es im Moment zu testen.

+0

Sie haben absolut Recht! Da ich in 'function_call_t' nur einen' std :: string' hatte, war ich nie so, wie ich es mir vorgestellt habe. Daher bin ich sehr überrascht, dass mein vorheriger Code überhaupt gelaufen ist! Ich habe meiner Struktur einen 'std :: vector variable_names' hinzugefügt, der das Problem sofort behebt. Danke vielmals! –

Verwandte Themen