J'ai déclaré les règles de ma grammaire comme const static. Cela a fonctionné bien jusqu'à ce que j'aie essayé d'utiliser des règles croisées récursives (la règle1 est définie en utilisant rule2 qui est définie en utilisant rule1). Le code source peut encore être construit, mais segfaults sur la source d'analyse contenant un tel cas récursif. est ici un code simplifié de la grammaire:Déclaration des règles de recoupement
template < typename Iterator >
class Skipper : public qi::grammar<Iterator> {
public:
Skipper () : Skipper::base_type(_skip_rule) { }
private:
static qi::rule<Iterator> const
_comment,
_skip_rule;
};
template < typename Iterator >
typename qi::rule<Iterator> const
Skipper<Iterator>::_comment(
boost::spirit::repository::confix("/*", "*/")[*(qi::char_ - "*/")] // Multi-line
| boost::spirit::repository::confix("//", qi::eol)[*(qi::char_ - qi::eol)] // Single-line
);
template < typename Iterator >
typename qi::rule<Iterator> const
Skipper<Iterator>::_skip_rule(qi::ascii::space | _comment);
template < typename Iterator, typename Skipper >
class Grammar : public qi::grammar<Iterator, Skipper > {
public:
Grammar () : Grammar::base_type(expression) { }
private:
static qi::rule<Iterator, Skipper> const
// Tokens
scalar_literal,
identifier,
// Rules
operand,
expression;
};
template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
Grammar<Iterator, Skipper>::scalar_literal(qi::uint_ | qi::int_);
template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
Grammar<Iterator, Skipper>::identifier(qi::lexeme[(qi::alpha | '_') >> *(qi::alnum | '_')]);
template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
Grammar<Iterator, Skipper>::operand((scalar_literal | identifier | ('(' >> expression >> ')')));
template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
Grammar<Iterator, Skipper>::expression(operand);
(expression règle est identique à opérande pour rendre le code plus facile à comprendre, bien sûr, il devrait être plus compliqué encore basé sur opérande) . opérande déclaration utilise expression un et vice versa. Ce segfaults en essayant de parse_phrase par exemple (123). Je suppose que c'est à cause de "forward" en utilisant expression; même si je mets expression déclaration avant l'opérande un. Alors, de quelle manière ces règles devraient-elles être déclarées pour éviter les erreurs d'exécution?
Merci beaucoup! Mais une question de plus: si j'essaie d'initialiser des règles en dehors du corps du constructeur: 'Grammaire(): scalaire_literal (qi :: uint_ | qi :: int_), identificateur ((qi :: alpha | '_') >> * (qi :: alnum | '_')), opérande ((scalar_literal | identifiant | ('(' ('>> expression') '))), expression (opérande), Grammaire :: base_type (expression) ' J'ai reçu un avertissement indiquant que _expression_ sera initialisé après _base_type_ call. Ensuite, l'analyse échoue. Donc les règles DOIVENT être assignées UNIQUEMENT dans le corps du constructeur? Ou existe-t-il un moyen de modifier l'ordre d'initialisation? – Vercetti
N'est pas lié à la base: http://en.cppreference.com/w/cpp/language/initializer_list#Initialization_order et http://stackoverflow.com/a/2669911/85371. Je pense que la vraie raison est la différence entre l'assignation et l'initialisation (copie). Je ne suis pas motivé pour découvrir la différence si :) juste coller aux idiomes communs. Inner-const n'est pas très utile de toute façon. – sehe
J'ai compris. Merci beaucoup, votre réponse m'a vraiment aidé. – Vercetti