Estoy tratando de analizar un C-función como expresiones de árboles como el siguiente (utilizando el Spirit Parser Framework):Analizar una gramática con el Espíritu Boost
F(A() , B(GREAT(SOME , NOT)) , C(YES))
Por esto estoy tratando de utilizar las tres reglas en el siguiente gramática:
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;
};
en cuenta que mi regla de etiqueta simplemente trata de captar los identificadores utilizados en las expresiones (los nombres de función ''). También observe que la firma de la regla de etiqueta devuelve un ExpressionAST
en lugar de un std::string
, como en la mayoría de los ejemplos. La razón por la que quiero hacerlo así es bastante simple: odio usar variantes y las evitaré si es posible. Sería genial conservar el pastel y comérselo también, supongo.
Un comando debe comenzar con una etiqueta (el nombre del nodo actual, primer campo de cadena del nodo AST) y un número variable de argumentos entre paréntesis, y cada uno de los argumentos puede ser una etiqueta u otro comando .
Sin embargo, este ejemplo no funciona en absoluto. Compila y todo, pero en tiempo de ejecución no puede analizar todas mis cadenas de prueba. Y lo que realmente me molesta es que no sé cómo solucionarlo, ya que no puedo depurar el código anterior, al menos en el sentido tradicional de la palabra. Básicamente, la única forma en que veo que puedo corregir el código anterior es saber qué estoy haciendo mal.
Entonces, la pregunta es que no sé cuál es el problema con el código anterior. ¿Cómo definirías la gramática anterior?
El tipo ExpressionAST
que estoy usando es:
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)
)
Algo que descubrí recientemente es que los identificadores C y C++ pueden tener caracteres '$' en sus nombres. De modo que a-z, A-Z, 0-9 (excepto el primer carácter), _ y $ son válidos en un identificador C/C++. – Cthutu
@Cthutu MSVC permite caracteres acentuados en los identificadores. No significa que cumple con los estándares. –
Más importante aún, ¿cuál es el punto que estás tratando de hacer @Cthutu? ¿Hay escasez de identificadores? ¿Su compilador no admite espacios de nombres correctamente? – sehe