Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8946051
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T12:24:45+00:00 2026-06-15T12:24:45+00:00

How should I modify this boost::spirit code to parse for any combination of ranges

  • 0

How should I modify this boost::spirit code to parse for any combination of ranges or lists?

Note that this question is somewhat different from my previous question. In this case, I don’t have a special pre-tag like RANGE: and LIST: that helps me parse, so I’m not sure if we require some kind of look-ahead here.

I do need to keep the parses separate, though, as doing so will help me capture the results into different data structures.

objective get all four test-cases to pass

EDIT ANSWER that seems to work with more complicated expressions

// #define BOOST_SPIRIT_DEBUG

#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/tuple.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>

#include <iostream>

namespace qi = boost::spirit::qi;

typedef std::vector<boost::tuple<std::string,std::vector<int>>>   MY_TYPE;

template <typename Iterator, typename Skipper>
struct my_grammar :
qi::grammar<Iterator, MY_TYPE(), Skipper>
{
    my_grammar() :
        my_grammar::base_type( entries )
    {
        entries %=
            *(
                +(qi::char_ - '-')
                >> qi::lit( "->" )
                >> ( comma | range )
            )
            ;

        range %= '{' >> qi::int_ >> ':' >> qi::int_ >> ':' >> qi::int_ >> '}';
        comma %= '{' >> (qi::int_ % ',') >> '}';

        BOOST_SPIRIT_DEBUG_NODE( range   );
        BOOST_SPIRIT_DEBUG_NODE( comma   );
        BOOST_SPIRIT_DEBUG_NODE( entries );
    }

    qi::rule<Iterator, std::vector<int>(), Skipper> 
        range, comma;

    qi::rule<Iterator, MY_TYPE(), Skipper> 
        entries;
};

// -----------------------------------------------------------------------------

static void TryParse( const std::string& input, const std::string& label )
{
    MY_TYPE entries;
    auto it(input.cbegin()), end( input.cend() );
    my_grammar<decltype(it), qi::space_type> entry_grammar;

    if (qi::phrase_parse(it, end, entry_grammar, qi::space, entries)
            && it == end)
    {
        std::cerr << label << " SUCCESS" << std::endl;
    }
    else
    {
        std::cerr << label << " FAIL" << std::endl;
    }
}

int
main( int argc, char* argv[] )
{
    std::string range_first = "foo -> {1:9:1}\nbar -> {1,2,3,4,5}\n";
    std::string comma_first = "foo -> {1,2,3,4,5}\nbar -> {1:9:1}\n";
    std::string comma_only  = "foo -> {1,2,3,4,5}\n";
    std::string range_only  = "foo -> {1:9:1}\n";

    TryParse( range_first, "RANGE FIRST" );
    TryParse( comma_first, "COMMA FIRST" );
    TryParse( range_only,  "RANGE ONLY"  );
    TryParse( comma_only,  "COMMA ONLY"  );
}

EDIT NEW OUTPUT (STILL CAN’T HANDLE HETEROGENEOUS LIST)

/tmp$ g++ -g -std=c++11 sandbox.cpp -o sandbox && ./sandbox 
COMMA FIRST FAIL
RANGE FIRST FAIL
COMMA ONLY SUCCESS
RANGE ONLY SUCCESS
/tmp$ 

EDIT IMPROVED CODE (STILL CAN’T HANDLE HETEROGENEOUS LIST)

// #define BOOST_SPIRIT_DEBUG

#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>

namespace qi = boost::spirit::qi;

template <typename Iterator, typename Skipper>
struct my_grammar :
qi::grammar<Iterator, std::vector<int>(), Skipper>
{
    my_grammar() :
        my_grammar::base_type(entries)
    {
        entries %= 
            *('{' >> qi::int_
            >> ( range_tail | comma_tail ))
        ;

        range_tail %= ':' >> qi::int_ >> ':' >> qi::int_ >> '}';
        comma_tail %= *( ',' >> qi::int_ ) >> '}';

        BOOST_SPIRIT_DEBUG_NODE(entries   );
        BOOST_SPIRIT_DEBUG_NODE(comma_tail);
        BOOST_SPIRIT_DEBUG_NODE(range_tail);
    }

    qi::rule<Iterator, std::vector<int>(), Skipper> entries, comma_tail, range_tail;
};

// -----------------------------------------------------------------------------

static void TryParse( const std::string& input, const std::string& label )
{
    std::vector<int> entries;
    auto it(input.cbegin()), end( input.cend() );
    my_grammar<decltype(it), qi::blank_type> entry_grammar;

    if (qi::phrase_parse(it, end, entry_grammar, qi::blank, entries)
            && it == end)
    {
        std::cerr << label << " SUCCESS" << std::endl;
    }
    else
    {
        std::cerr << label << " FAIL" << std::endl;
    }
}

int
main( int argc, char* argv[] )
{
    std::string range_first = "{3:5:7}\n{1,2,3,4,5}";
    std::string comma_first = "{1,2,3,4,5}\n{3:5:7}";
    std::string comma_only  = "{1,2,3,4,5}";
    std::string range_only  = "{3:5:7}";

    TryParse( comma_first, "COMMA FIRST" );
    TryParse( range_first, "RANGE FIRST" );
    TryParse( comma_only,  "COMMA ONLY"  );
    TryParse( range_only,  "RANGE ONLY"  );
}

ORIGINAL CODE

compile and run

/tmp$ g++ -g -std=c++11 sandbox.cpp -o sandbox && ./sandbox 
COMMA FIRST FAIL
RANGE FIRST FAIL
COMMA ONLY SUCCESS
RANGE ONLY FAIL
/tmp$ 

sandbox.cpp

// #define BOOST_SPIRIT_DEBUG

#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>


namespace qi = boost::spirit::qi;
typedef int Entry;

template <typename Iterator, typename Skipper>
struct my_grammar :
qi::grammar<Iterator, std::vector<Entry>(), Skipper>
{
    my_grammar() :
        my_grammar::base_type(entries)
    {
        entries %= 
            *( 
                '{' >>
                    ( comma_list | range_list )
                >> '}'
            )
        ;

        comma_list %= qi::int_ % ',';
        range_list %= qi::int_ >> ':' >> qi::int_ >> ':' >> qi::int_;

        BOOST_SPIRIT_DEBUG_NODE(entries);
        BOOST_SPIRIT_DEBUG_NODE(comma_list);
        BOOST_SPIRIT_DEBUG_NODE(range_list);
    }

    qi::rule<Iterator, std::vector<Entry>(), Skipper> entries, comma_list, range_list;
};

// -----------------------------------------------------------------------------
static void TryParse( const std::string& input, const std::string& label )
{
    std::vector<Entry> entries;
    auto it(input.cbegin()), end( input.cend() );
    my_grammar<decltype(it), qi::blank_type> entry_grammar;

    if (qi::phrase_parse(it, end, entry_grammar, qi::blank, entries)
            && it == end)
    {
        std::cerr << label << " SUCCESS" << std::endl;
    }
    else
    {
        std::cerr << label << " FAIL" << std::endl;
    }
}

int
main( int argc, char* argv[] )
{
    std::string range_first = "{3:5:7}\n{1,2,3,4,5}";
    std::string comma_first = "{1,2,3,4,5}\n{3:5:7}";
    std::string comma_only  = "{1,2,3,4,5}";
    std::string range_only  = "{3:5:7}";

    TryParse( range_first, "COMMA FIRST" );
    TryParse( comma_first, "RANGE FIRST" );
    TryParse( comma_only,  "COMMA ONLY"  );
    TryParse( range_only,  "RANGE ONLY"  );
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T12:24:46+00:00Added an answer on June 15, 2026 at 12:24 pm

    Consume the leading number in common code. After that number have either a range tail or a list tail. List tails start with a , and range tails start with a :.

    Possibly fold the } into the tail, so a list tail is (,number)*} and a range tail is :number:number}, which makes the empty list easier to parse.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

How should I modify this in order to display Chinese characters? Those question marks
The comment for the class BillingService recommends that: You should modify and obfuscate this
Working with WCF how it should modify this DataContract or code: <DataContract()> Public Class
The following code lies within cellForRowAtIndexPath . 1.) i need to modify this code
Given the following code and the suggestions given in this question , I've decided
Where to modify this code IT STILL GIVES A MSGBOX IF I SELECT THE
I discovered that iterator methods in value types are allowed to modify this .
modify this question again, because the solution does not work in the new version
Found this code on the net. Want to modify it to make it scroll
This should be easy, but I'm stuck trying to modify this build.xml I'm getting

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.