Stimuler l’esprit prend à jamais pour parsingr les expressions

je suis nouveau ici travailler avec boost

En lisant beaucoup de très bons articles pour stimuler Spirit, je décide de créer un parsingur et de me lancer dans le problème qui parsing une expression comme celle-ci

1+ (2+ (3+ (4+ (5+) (6+ (7+ (8))))))))

prend toujours pour l’exécution .. le rendant plus simple 1+ (2+ (3)) fonctionne bien. I On dirait que le retour en arrière de l’parsingur est actif. Donnez-moi s’il vous plaît un indice sur la façon de modifier la grid ou le comportement pour que cette exécution se fasse dans le temps.

Voici un peu le code du grammeur. J’utilise le “iter_pos” pour suivre la position.

Cordialement Markus

primary = functioncall | constant_double | constant_integer | name | ssortingng; constant_double = real_parser< double, strict_ureal_policies >() [_val = construct(type_const_double, key_value, _1)]; name = name_pure_location [_val = construct(type_name, phoenix::bind(&getLocation, _1),key_value, phoenix::bind(&getSsortingng, _1))]; ssortingng = (lexeme[L'"' >> +(boost::spirit::standard_wide::char_ - L'"') >> L'"']) [_val = construct(type_const_ssortingng, key_value,phoenix::bind(&makeSsortingng, _1))]; constant_integer = int_ [_val = construct(type_const_int, key_value, construct(_1))]; parenthetical = lit('(') >> expression >> lit(')') | primary; unary = (iter_pos >> unary_op >> unary >> iter_pos) [_val = construct( type_cmd_member_call, LOCATION(_1,_4), key_callname, construct(_2), key_this,construct(_3) )] | parenthetical[_val = _1] ; multiplicative = (iter_pos >> unary >> (multiply_op | divide_op | modulo_op) >> multiplicative >> iter_pos) [_val = construct( type_cmd_member_call, LOCATION(_1, _5), key_callname, construct(_3), key_this, construct(_2), key_parameter, construct(_4) )] | unary[_val = _1]; additive = (iter_pos >> multiplicative >> (add_op | subtract_op) >> additive >> iter_pos) [_val = construct( type_cmd_member_call, LOCATION(_1, _5), key_callname, construct(_3), key_this, construct(_2), key_parameter, construct(_4) )] | multiplicative[_val = _1] ; compares = (iter_pos >> additive >> (compare_op) >> compares >> iter_pos) [_val = construct( type_cmd_member_call, LOCATION(_1, _5), key_callname, construct(_3), key_this, construct(_2), key_parameter, construct(_4) )] | additive[_val = _1] ; expression = compares[_val = _1]; 

Vous avez correctement identifié la source du problème: les règles sont spécifiées “paresseusement” (en ce sens qu’elles donnent, comme il se doit, de manière descriptive les productions correspondant à la règle).

Comme vous pouvez le constater, dans une grammaire PEG, cela conduit rapidement à une mauvaise performance s’il ya beaucoup de retour en arrière.

J’ai déjà montré l’optimisation d’expressions très similaires. Le résumé est le suivant: au lieu d’attendre une expression binary et de revenir en arrière s’il n’est pas satisfait, parsingz le premier opérande «avec gourmandise» et composez différents nœuds d’expression AST en fonction de ce qui suit.

  • Améliorez les performances médiocres de votre esprit avec Alternative Parser

  • Traitement similaire avec une explication plus visuelle Boost :: Spirit: optimisation d’un parsingur d’expression

Peut-être intéressant:

merci pour cette entrée. J’essaie votre échantillon et cela fonctionne comme prévu (et rapidement) .. de toute façon, je n’ai pas pu utiliser la solution de “Boost :: Spirit: Optimisation d’une expression Parser” avec mes actions sématiques. Tout simplement, je ne sais pas comment placer mes actions dans cet exemple. Tous les autres liens sont une source formidable et je comprends aussi les idées qui se cachent derrière la scène, mais il semble que cela rest une solution de contournement au problème plus général de la programmation PEG revenir en arrière. Y a-t-il un moyen plus général de résoudre ce problème? Par exemple, utilisez l’opérateur “>” au lieu de “>>” pour éviter les retours en arrière à un moment donné. Jusqu’ici, je n’ai pas réussi à utiliser l’opérateur “>” dans mon échantillon.

Après avoir joué avec les autres informations sur les liens, je réécris les règles et maintenant, cela fonctionne bien et rapidement.

 primary = functioncall | constant_double | constant_integer | name | ssortingng; constant_double = real_parser>() [_val = construct(type_const_double, key_value, _1)]; name = name_pure_location[_val = construct( type_name, phoenix::bind(&getLocation, _1), key_value, phoenix::bind(&getSsortingng, _1))]; ssortingng = (lexeme[L'"' >> +(boost::spirit::standard_wide::char_ - L'"') >> L'"']) [_val = construct(type_const_ssortingng, key_value, phoenix::bind(&makeSsortingng, _1))]; constant_integer = int_[_val = construct(type_const_int, key_value, construct(_1))]; parenthetical = lit('(') >> expression >> lit(')') | primary; // this define is used to make to code more readable .. #define EXPR_ACTION(NAME) \ [_val = construct(type_cmd_member_call, LOCATION(_1, _3), \ key_callname, construct(NAME), \ key_this, construct(_val), \ key_parameter, construct(_2))] unary = (iter_pos >> unary_op >> unary >> iter_pos)[_val = construct( type_cmd_member_call, LOCATION(_1, _4), key_callname, construct(_2), key_this, construct(_3))] | parenthetical[_val = _1]; multiplicative = unary[_val = _1] >> *(iter_pos >> lit('*') >> unary >> iter_pos) EXPR_ACTION(L"_mul") >> *(iter_pos >> lit('/') >> unary >> iter_pos) EXPR_ACTION(L"_div"); additive = multiplicative[_val = _1] >> *(iter_pos >> lit('-') >> multiplicative >> iter_pos) EXPR_ACTION(L"_sub") >> *(iter_pos >> lit('+') >> multiplicative >> iter_pos) EXPR_ACTION(L"_add"); compares = additive[_val = _1] >> *(iter_pos >> lit('<') >> additive >> iter_pos) EXPR_ACTION(L"_cmp_low") >> *(iter_pos >> lit('>') >> additive >> iter_pos) EXPR_ACTION(L"_cmp_gre") >> *(iter_pos >> lit('=') >> additive >> iter_pos) EXPR_ACTION(L"_cmp_equ"); logical = compares[_val = _1] >> *(iter_pos >> nocaselit(L"and") >> compares >> iter_pos) EXPR_ACTION(L"_and") >> *(iter_pos >> nocaselit(L"or") >> compares >> iter_pos) EXPR_ACTION(L"_or"); expression = logical[_val = _1]; 

merci beaucoup pour les bonnes entrées! Markus