Je suis en train d'analyser une fonction C comme des expressions d'arbres comme les suivantes (en utilisant le Spirit Parser Framework):Parsing une grammaire avec l'Esprit Boost
F(A() , B(GREAT(SOME , NOT)) , C(YES))
Pour cela, je suis en train d'utiliser les trois règles sur les points suivants grammaire:
template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {
InputGrammar() : InputGrammar::base_type() {
tag = (qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9"))[ push_back(at_c<0>(qi::_val) , qi::_1) ];
command = tag [ at_c<0>(qi::_val) = at_c<0>(qi::_1) ] >> "(" >> (*instruction >> ",")
[ push_back(at_c<1>(qi::_val) , qi::_1) ] >> ")";
instruction = (command | tag) [qi::_val = qi::_1];
}
qi::rule< Iterator , ExpressionAST() , space_type > tag;
qi::rule< Iterator , ExpressionAST() , space_type > command;
qi::rule< Iterator , ExpressionAST() , space_type > instruction;
};
Notez que ma règle d'étiquette essaie juste de capturer les identifiants utilisés dans les expressions (les noms de fonction « »). Notez également que la signature de la règle d'étiquette renvoie un ExpressionAST
au lieu d'un std::string
, comme dans la plupart des exemples. La raison pour laquelle je veux faire comme ceci est en fait assez simple: je déteste utiliser des variantes et je les éviterai si possible. Ce serait génial de garder le gâteau et de le manger aussi je suppose. Une commande doit commencer par une balise (le nom du nœud actuel, le premier champ de chaîne du nœud AST) et un nombre variable d'arguments entre parenthèses, et chacun des arguments peut être une balise elle-même ou une autre commande .
Cependant, cet exemple ne fonctionne pas du tout. Il compile et tout, mais au moment de l'exécution, il ne parvient pas à analyser toutes mes chaînes de test. Et la chose qui m'ennuie vraiment, c'est que je n'arrive pas à comprendre comment le réparer, puisque je ne peux pas vraiment déboguer le code ci-dessus, au moins dans le sens traditionnel du mot. Fondamentalement, la seule façon dont je vois que je peux réparer le code ci-dessus est de savoir ce que je fais mal. Donc, la question est que je ne sais pas quel est le problème avec le code ci-dessus. Comment définiriez-vous la grammaire ci-dessus?
Le type ExpressionAST
J'utilise est:
struct MockExpressionNode {
std::string name;
std::vector<MockExpressionNode> operands;
typedef std::vector<MockExpressionNode>::iterator iterator;
typedef std::vector<MockExpressionNode>::const_iterator const_iterator;
iterator begin() { return operands.begin(); }
const_iterator begin() const { return operands.begin(); }
iterator end() { return operands.end(); }
const_iterator end() const { return operands.end(); }
bool is_leaf() const {
return (operands.begin() == operands.end());
}
};
BOOST_FUSION_ADAPT_STRUCT(
MockExpressionNode,
(std::string, name)
(std::vector<MockExpressionNode>, operands)
)
Quelque chose que j'ai découvert récemment est que les identificateurs C et C++ peuvent avoir des caractères '$' dans leurs noms. Alors que a-z, A-Z, 0-9 (sauf pour le premier caractère), _ et $ sont valides dans un identifiant C/C++. – Cthutu
@Cthutu MSVC autorise les caractères accentués dans les identifiants. Cela ne veut pas dire que c'est conforme aux normes. –
Plus important encore, quel est le point que vous essayez de faire @Cthutu? Y a-t-il une pénurie d'identifiants? Votre compilateur ne prend-il pas en charge les espaces de noms correctement? – sehe