2012-07-10 67 views
2

是否有可能从Spirit分析器的语义操作中检索在词法分析器中定义的标记的标识,如下所示:token_def<> tok;检索token_def的标识<>

我想要做的是使用每个运算符的标识ID(如+, - ,*等),并从解析器语义操作(如添加,减,时间等)

据我明白,在象生产:

toks.symbol >> >> toks.plus toks.symbol;

如果toks.plus是或类型token_def<> plus;,_1将参照第一toks.symbol和_2将参考第二toks.symbol。真的吗?如果是这样,我怎样才能访问中间令牌(只是为了检索ID)?

谢谢!

回答

2

您可以使用内置的懒惰占位lex::_tokenid,请参阅文档:

我适应了second word-count sample from the tutorials打印在飞行令牌IDS:

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_statement.hpp> 
#include <boost/spirit/include/phoenix_algorithm.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 

#include <iostream> 
#include <string> 

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

struct distance_func 
{ 
    template <typename Iterator1, typename Iterator2> 
    struct result : boost::iterator_difference<Iterator1> {}; 

    template <typename Iterator1, typename Iterator2> 
    typename result<Iterator1, Iterator2>::type 
    operator()(Iterator1& begin, Iterator2& end) const 
    { 
     return std::distance(begin, end); 
    } 
}; 
boost::phoenix::function<distance_func> const distance = distance_func(); 

template <typename Lexer> 
struct word_count_tokens : lex::lexer<Lexer> 
{ 
    word_count_tokens() 
     : c(0), w(0), l(0) 
     , word("[^ \t\n]+")  // define tokens 
     , eol("\n") 
     , any(".") 
    { 
     using boost::spirit::lex::_start; 
     using boost::spirit::lex::_end; 
     using boost::spirit::lex::_tokenid; 
     using boost::phoenix::ref; 

     // associate tokens with the lexer 
     this->self 
      = word [++ref(w), ref(c) += distance(_start, _end), phx::ref(std::cout) << _tokenid << ";" ] 
      | eol [++ref(c), ++ref(l), phx::ref(std::cout) << _tokenid << ";" ] 
      | any [++ref(c), phx::ref(std::cout) << _tokenid << ";" ] 
      ; 
    } 

    std::size_t c, w, l; 
    lex::token_def<> word, eol, any; 
}; 

/////////////////////////////////////////////////////////////////////////////// 
int main(int argc, char* argv[]) 
{ 
    typedef 
     lex::lexertl::token<char const*, lex::omit, boost::mpl::false_> 
     token_type; 

    typedef lex::lexertl::actor_lexer<token_type> lexer_type; 

    word_count_tokens<lexer_type> word_count_lexer; 

    std::string str ("the lazy moon jumped over the brazen mold"); 
    char const* first = str.c_str(); 
    char const* last = &first[str.size()]; 

    lexer_type::iterator_type iter = word_count_lexer.begin(first, last); 
    lexer_type::iterator_type end = word_count_lexer.end(); 

    while (iter != end && token_is_valid(*iter)) 
     ++iter; 

    if (iter == end) { 
     std::cout << "\nlines: " << word_count_lexer.l 
      << ", words: " << word_count_lexer.w 
      << ", characters: " << word_count_lexer.c 
      << "\n"; 
    } 
    else { 
     std::string rest(first, last); 
     std::cout << "Lexical analysis failed\n" << "stopped at: \"" 
      << rest << "\"\n"; 
    } 
    return 0; 
} 

输出:

65536;65538;65536;65538;65536;65538;65536;65538;65536;65538;65536;65538;65536;65538;65536; 
lines: 0, words: 8, characters: 41 
+0

谢谢sehe。因此,这是如何从词法分析器语义操作中访问令牌ID的。有没有一种方法可以从解析器语义操作中访问它?如下所示:tok.symbol >> tok.plus >> tok.symbol [std :: cout <<“plus_token_id”<< std :: endl]; – 2012-07-10 17:14:55

+0

@HaithamGad [这是Lex教程改编的第三个示例](http://ideone.com/YqoDo)使用SA从解析器SA打印标记ID。我不明白这是否会增加价值,因为令牌在您匹配时已经知道了? – sehe 2012-07-10 23:39:32

+0

我看到在这种情况下,单词被定义为token_def 。如果单词被定义为token_def <>,这个代码是否可以工作?据我所知,像这样定义的令牌在解析器语义操作中不能被占位符访问。真的吗? – 2012-07-11 15:23:26