Question

How could I trace the position of the attribute of spirit?

A simple example

template <typename Iterator>
bool trace_numbers(Iterator first, Iterator last)
{
    using boost::spirit::qi::double_;
    using boost::spirit::qi::phrase_parse;
    using boost::spirit::ascii::space;

    bool r = phrase_parse(first, last,

                          //  Begin grammar
                          (
                              double_ % ','
                          )
            ,
            //  End grammar
            space);

    if (first != last) // fail if we did not get a full match
        return false;
    return r;
}

I want to trace the position(line and column) of "double_", I found line_pos_iterator but have no idea how to use it.I also found multi-pass, but don't know it could be used to trace the positions or not(if it can, how?).

Was it helpful?

Solution

After some research, I found that using spirit::lex alone or combine it with spirit::qi is a solution.

#include <boost/config/warning_disable.hpp>
//[wcp_includes
#include <boost/spirit/include/qi.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_container.hpp>
//]

#include <iostream>
#include <string>
#include <vector>

namespace spiritParser
{

//[wcp_namespaces
using namespace boost::spirit;
using namespace boost::spirit::ascii;

//[wcp_token_ids
enum tokenids
{
    IDANY = lex::min_token_id + 10
};
//]

//[wcp_token_definition
template <typename Lexer>
struct number_position_track_tokens : lex::lexer<Lexer>
{
    number_position_track_tokens()
    {
        // define patterns (lexer macros) to be used during token definition
        // below
        this->self.add_pattern
            ("NUM", "[0-9]+")
        ;

        number = "{NUM}";    // reference the pattern 'NUM' as defined above

        this->self.add
            (number)          // no token id is needed here
            (".", IDANY)      // characters are usable as tokens as well
        ;
    }

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

template<typename Iterator>
struct numberGrammar : qi::grammar<Iterator>
{
    template <typename TokenDef>
    numberGrammar(TokenDef const &tok)
      : numberGrammar::base_type(start)
      , num(0), position(0)
    {
        using boost::phoenix::ref;
        using boost::phoenix::push_back;
        using boost::phoenix::size;
        //"34, 44, 55, 66, 77, 88"
        start =  *(   tok.number        [++ref(num),
                                         boost::phoenix::push_back(boost::phoenix::ref(numPosition), boost::phoenix::ref(position)),
                                         ref(position) += size(_1)
                                        ]
                  |   qi::token(IDANY)  [++ref(position)]
                  )
              ;
    }

    std::size_t num, position;
    std::vector<size_t> numPosition;
    qi::rule<Iterator> start;
};

void lex_word_count_1()
{
    using token_type = lex::lexertl::token<char const*, boost::mpl::vector<std::string> >;

    number_position_track_tokens<lexer_type> word_count;          // Our lexer
    numberGrammar<iterator_type> g (word_count);  // Our parser

    // read in the file int memory
    std::string str ("34, 44, 55, 66, 77, 88");
    char const* first = str.c_str();
    char const* last = &first[str.size()];       

    if (r) {
        std::cout << "nums: " << g.num << ", size: " << g.position <<std::endl;
        for(auto data : g.numPosition){
            std::cout<<"position : "<<data<<std::endl;
        }
    }
    else {
        std::string rest(first, last);
        std::cerr << "Parsing failed\n" << "stopped at: \""
                  << rest << "\"\n";
    }
}

    } 

This is the example from the document Quickstart 3 - Counting Words Using a Parser with some alternation.In my humble opinion, this is far from easy for a small task like this. If the patterns are not difficult for std::regex to descript; need faster speed or both, select spirit::lex to track the locations of simple pattern(like the example I show) is overkill.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top