2011-12-03 58 views
2

我使用助推精神解析數學表達式,並遇到了一個問題,我將其解壓縮到以下代碼中。助推精神:使用語義動作和鳳凰時的參數類型

有一個簡單的詞法分析器帶有一個標記,具有一個保存匹配字符串的屬性。解析器定義了一個單獨的規則,用於獲取令牌的屬性並用它調用一個函數。函數調用的結果應該是規則的屬性值。

這無法編譯(calc_something:不能從常量升壓轉換參數1 ::精神:: _ 1_type爲const的std :: string &) - 顯然,因爲氣的類型:: _ 1是不正確的推斷。但是,將操作更改爲簡單的「cout < < qi :: _1」的作品。

我對提升精神很新,但已經設法讓我的語法正確行事。現在我需要解析值,我被卡在這裏,並希望得到任何幫助。

// spiritTest.cpp : Defines the entry point for the console application. 
// 

#include <stdio.h> 
#include <tchar.h> 

#include <string> 
#include <iostream> 

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 

namespace qi = boost::spirit::qi; 
namespace lex = boost::spirit::lex; 
namespace phoenix = boost::phoenix; 

template <typename Lexer> 
class TestLexer : public lex::lexer<Lexer> 
{ 
public: 
    TestLexer() 
    { 
     number = "(\\d*\\.)?\\d+([eE][-+]?\\d+)?";  
     self = number; 
    } 

    lex::token_def<std::string> number; 
}; 

int calc_something(const std::string & s) 
{ 
    return 5; 
} 

template <typename Iterator> 
class Parser : public qi::grammar<Iterator, int> 
{ 
public: 
    template <typename TokenDef> 
    Parser(const TokenDef& tok) : Parser::base_type(value) 
    { 
     // the following line causes error C2664: 'calc_something' : cannot convert parameter 1 from 'const boost::spirit::_1_type' to 'const std::string &'  
     value = tok.number [qi::_val = calc_something(qi::_1)];   

     // the following line works as expected 
     //value = tok.number [std::cout << qi::_1 << std::endl];    
    } 

    qi::rule<Iterator, int> value; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    typedef const char* base_iterator_type; 
    typedef lex::lexertl::token<base_iterator_type> token_type; 
    typedef lex::lexertl::lexer<token_type> lexer_type; 
    typedef TestLexer<lexer_type> TestLexer; 
    typedef TestLexer::iterator_type iterator_type; 
    typedef Parser<iterator_type> Parser; 

    TestLexer lexer; 
    Parser parser(lexer); 

    const char * formula = "530"; 
    bool result = lex::tokenize_and_parse(formula, formula + strlen(formula), lexer, parser); 

    return 0; 
} 

回答

2

我沒有經驗spirit lex,但我以爲這是類似qi,所以你想使用一個phoenix function做到這一點:

#include <boost/spirit/include/phoenix_function.hpp> 

struct calc_something_impl 
{ 
    template <typename T1> 
    struct result { typedef int type; }; 

    int operator()(const std::string & s) const 
    { 
    return 5; 
    } 
}; 

boost::phoenix::function<calc_something_impl> calc_something; 
1

EDDI已確定的部分問題;我設法得到這個工作與其他兩個變化:

  • 你的語法和規則必須使用函數調用語法的綜合屬性,即簽名,<Iterator, int()>
  • 雖然我無法得到偷懶菲尼克斯功能eddi詳細工作(它編譯,但從來沒有被稱爲),切換到鳳凰V3使其工作。新增第一個靈前,包括:

#define BOOST_SPIRIT_USE_PHOENIX_V3 1