Terminapor I'll see you rise. | Hi there J'ai écris un parseur de fichier texte en utilisant boost::spirit::qi qui marche très bien. Je viens d'essayer de compiler en release (avec le flag -O2) et là, il est incapable de me parser mon fichier Voilà la class qui gère les règles : (mp::Property est une structure, mp::Type est un enum, MaterialInfo est la structure renvoyée ) Code :
- //-------------------------------------------------------
- // Material parser
- // Performs the parsing
- template < typename iterator_t, typename skipper_t >
- class MaterialParser : public qi::grammar< iterator_t, Graphic::MaterialInfo(), skipper_t >
- {
- private:
- //----------------------------------------------------
- // Rules
- qi::rule< iterator_t, std::string() > GenericStringRule;
- qi::rule< iterator_t, mp::Property(), skipper_t > PropertyRule;
- qi::rule< iterator_t, std::vector<mp::Property>(), skipper_t > PropertiesGroupRule;
- qi::rule< iterator_t, Graphic::MaterialInfo(), skipper_t > MaterialRule;
- //-----------------------------------------------------
- //-----------------------------------------------------
- // Symbols
- qi::symbols< char, mp::Type > PropertyTypeSymbols;
- //-----------------------------------------------------
- public:
- MaterialParser() : MaterialParser::base_type( MaterialRule )
- {
- //-----------------------------------
- // Set-up symbols ( properties types )
- PropertyTypeSymbols.add
- ("int", mp::TYPE_int)
- ("uint", mp::TYPE_uint)
- ("float", mp::TYPE_float)
- ("ivec2", mp::TYPE_ivec2)
- ("ivec3", mp::TYPE_ivec3)
- ("ivec4", mp::TYPE_ivec4)
- ("uvec2", mp::TYPE_uvec2)
- ("uvec3", mp::TYPE_uvec3)
- ("uvec4", mp::TYPE_uvec4)
- ("vec2", mp::TYPE_vec2)
- ("vec3", mp::TYPE_vec3)
- ("vec4", mp::TYPE_vec4);
- //-----------------------------------
- //-----------------------------------
- // Generic string rule
- // a-z, A-Z, 0-9, _
- GenericStringRule = +(ascii::char_("a-zA-Z0-9_" ));
- GenericStringRule.name("string" );
- //-----------------------------------
- //-----------------------------------
- // Property rule
- // {type} {name};
- PropertyRule = (PropertyTypeSymbols) > (GenericStringRule) > (qi::lit(";" ));
- //-----------------------------------
- //-----------------------------------
- // Group rule
- // name { [...] }
- PropertiesGroupRule = (qi::lit("properties" )) > (qi::lit("{" )) > (*PropertyRule) > (qi::lit("}" ));
- //-----------------------------------
- MaterialRule = +( (PropertiesGroupRule[ phx::bind( &Graphic::MaterialInfo::SetProperties, qi::_val, qi::_1 ) ]) );
- }
- };
- //-------------------------------------------------------
| Pour ce qui est de l'invocation, ça se passe comme ça : Code :
- Graphic::MaterialInfo ParseMaterial( std::istream& Input, const std::string& RefFileName )
- {
- //-------------------------------------------------------------------------
- // Aliases declaration
- using base_iterator_type = std::istreambuf_iterator<char> ;
- using forward_iterator_type = boost::spirit::multi_pass<base_iterator_type>;
- using pos_iterator_type = classic::position_iterator2<forward_iterator_type>;
- //-------------------------------------------------------------------------
- //-------------------------------------------------------------------------
- // Generate all iterators, initialize them
- base_iterator_type InputIt ( Input );
- forward_iterator_type fwd_first = boost::spirit::make_default_multi_pass( InputIt );
- forward_iterator_type fwd_last;
- pos_iterator_type pos_first(fwd_first, fwd_last, RefFileName );
- pos_iterator_type pos_last;
- //-------------------------------------------------------------------------
- Graphic::MaterialInfo Result;
- MaterialParser<pos_iterator_type, ascii::space_type > Parser;
- try
- {
- //-------------------------
- // Perform the actual parse
- bool r = qi::phrase_parse(
- pos_first, pos_last,
- Parser,
- ascii::space,
- Result
- );
- //-------------------------
- //-------------------------------
- // Check for completeness
- if (!r || pos_first != pos_last)
- {
- std::stringstream Message;
- const classic::file_position_base<std::string>& Pos = pos_first.get_position();
- Message<<"Line # "<<Pos.line <<" at position "<< Pos.column<<std::endl;
- Message<<pos_first.get_currentline()<<std::endl;
- for ( int i=1;i<Pos.column;++i) Message<<' ';
- Message<<"^ here"<<std::endl;
- throw std::runtime_error( Message.str() );
- }
- //-------------------------------
- }
- // Pas le catch ici, l'erreur est reportée dans la condition if !r || pos_first != post_last )
- return Result;
- }
| Toutes les structures parsées par les règles sont adaptés à boost::spirit::qi avec BOOST_FUSION_ADAPT_STRUCT (certaine le sont partiellement ceci-dit, j'ai des attributs de ces structures qui ne sont pas utilisés par le parseur, ça peut être gênant ? ) Mon fichier d'entrée : Code :
- properties {
- int i;
- uint u;
- float f;
- }
| Et le parser se stop dès le première caractère, il m'affiche ça : Line # 1 at position 1 properties { ^ here
| Je sais pas tellement ce qui se passe, on dirait que le compilateur optimise les opérateurs utilisés pour générer les règles, mais j'ai pas trouvé grand chose sur internet Merci à vous edit : J'ai oublié de préciser, les namespace boost sont ré-associés pour raccourcir un peu (dans le cpp) : Code :
- namespace qi = boost::spirit::qi;
- namespace ascii = boost::spirit::ascii;
- namespace classic = boost::spirit::classic;
- namespace phx = boost::phoenix;
|
Message édité par Terminapor le 11-03-2014 à 14:51:29 ---------------
Perhaps you don't deserve to breathe
|