2015-02-06 1 views
2

Я пытаюсь прочитать математическую функцию, которая зависит от символа t с boost :: spirit.Определение символа, который может быть частью литерала в boost boost

В приведенном ниже примере, я пытаюсь оценить функцию "tan(t)" в . Вместо того, чтобы

Exit: 1, value = 2.5721 

Я получаю

Exit: 1, value = 1.2 

Я понимаю, что когда я пытаюсь прочитать функцию "tan(t)", вместо вычисления тангенса t, значение t присваивается первой букве в слове tan. Можно ли обойти это поведение, не меняя символ t? Кроме того, не следует ли разобраться в синтаксическом анализе?

#include <string> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/spirit/include/qi_symbols.hpp> 
#include <boost/phoenix/stl/cmath.hpp> 

namespace qi = boost::spirit::qi; 
namespace ascii=boost::spirit::ascii; 
using boost::spirit::ascii::space; 
using boost::spirit::qi::symbols; 


template< typename Iterator > 
struct Grammar : public qi::grammar< Iterator, double(), ascii::space_type > 
{ 

    Grammar() : Grammar::base_type(expression) 
    { 
     using qi::double_; 
     using qi::_val; 
     using qi::_1; 

     expression = double_     [_val = _1] 
        | symbol     [_val = _1] 
        | function     [_val = _1] 
        | group     [_val = _1]; 

     function = qi::lit("tan") >> group [_val = boost::phoenix::tan(_1)]; 
     group = '(' >> expression [_val = _1] >> ')' ; 
    } 

    qi::rule<Iterator, double(), ascii::space_type> expression, function, group; 
    qi::symbols<char, double > symbol; 
}; 


int main() 
{ 
    typedef std::string::iterator iterator; 
    Grammar<iterator> grammar; 
    std::string function = "tan(t)"; //it would work if function = "tan(x)" 
    grammar.symbol.add("t",1.2);  // and add("x",1.2) 
    double value; 
    bool r = qi::phrase_parse(function.begin(), function.end(), grammar, space, value); 
    std::cout << "Exit: " << r << ", value = " << value << std::endl; 

    return 0; 
} 
+1

Вам не нужны семантические действия '[_val = _1]'. [Boost Spirit: «Семантические действия злы»?] (Http://stackoverflow.com/questions/8259440/boost-spirit-semantic-actions-are-evil) – sehe

ответ

1

Вы должны изменить порядок правил. Ваш символ (t) ест первую букву tan. Итак, вы вообще не разбираете все данные!

Если вы включите отладку вы видите этот вывод:

<expression> 
<try>tan(t)</try> 
<success>an(t)</success> 
<attributes>[1.2]</attributes> 
</expression> 
Exit: 1, value = 1.2 

"королевский путь", чтобы исправить это с помощью Distinct директивы Ключевое слово Qi от Repository Духа: boost::spirit::qi keywords and identifiers

Live On Coliru

#define BOOST_SPIRIT_DEBUG 
#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/spirit/include/qi_symbols.hpp> 
#include <boost/spirit/repository/include/qi_distinct.hpp> 
#include <boost/phoenix/stl/cmath.hpp> 

namespace qi = boost::spirit::qi; 
namespace ascii=boost::spirit::ascii; 
using boost::spirit::ascii::space; 
using boost::spirit::qi::symbols; 


template< typename Iterator > 
struct Grammar : public qi::grammar< Iterator, double(), ascii::space_type > 
{ 

    Grammar() : Grammar::base_type(expression) 
    { 
     using qi::double_; 
     using qi::_val; 
     using qi::_1; 
     using boost::spirit::repository::qi::distinct; 

     expression = double_ 
        | distinct(qi::char_("a-zAZ09_")) [ symbol ] 
        | function 
        | group; 

     function = "tan" >> group [_val = boost::phoenix::tan(_1)]; 
     group = '(' >> expression >> ')' ; 

     BOOST_SPIRIT_DEBUG_NODES((expression)(function)(group)); 
    } 

    qi::rule<Iterator, double(), ascii::space_type> expression, function, group; 
    qi::symbols<char, double > symbol; 
}; 


int main() 
{ 
    typedef std::string::iterator iterator; 
    Grammar<iterator> grammar; 
    std::string function = "tan(t)"; 
    grammar.symbol.add("t",1.2); 
    double value; 
    bool r = qi::phrase_parse(function.begin(), function.end(), grammar, space, value); 
    std::cout << "Exit: " << r << ", value = " << value << std::endl; 

    return 0; 
} 

Т он выводит с отладочной информацией:

<expression> 
    <try>tan(t)</try> 
    <function> 
    <try>tan(t)</try> 
    <group> 
     <try>(t)</try> 
     <expression> 
     <try>t)</try> 
     <success>)</success> 
     <attributes>[1.2]</attributes> 
     </expression> 
     <success></success> 
     <attributes>[1.2]</attributes> 
    </group> 
    <success></success> 
    <attributes>[2.57215]</attributes> 
    </function> 
    <success></success> 
    <attributes>[2.57215]</attributes> 
</expression> 
Exit: 1, value = 2.57215 
+0

Добавлен рабочий образец на основе 'repository :: qi: : distinct' – sehe