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

  • Home
  • SEARCH
  • 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 8563739
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T17:01:53+00:00 2026-06-11T17:01:53+00:00

I have two rules with the same attribute. Is it possible to pass the

  • 0

I have two rules with the same attribute.

Is it possible to pass the attribute of the matrix_ rule to the matrixBlock_ child rule?
I want to keep the repeat directive from creating an attribute of the form vector< >. Instead it should just keep writing into the attribute of matrix_ (numBlocks’s times).
I tried to pass the attribute as inherited attribute to the child rule and it compiles(see below). But I get several “ghost” entries in my vector which come not from the phoenix::push_back.
Also this seems not to be the optimal way for me. Is it possible to us automatic attribute propagation in matrixBlock_ instead of semantic actions?

typedef vector<columnT> Matrix;
matrix_ = repeat(numBlocks)[ matrixBlock_(_val) ];
matrixBlock_ = *column[phoenix::push_back(_r1, _1)];

qi::rule<Iterator, Matrix(), ascii::space_type> matrix_;
qi::rule<Iterator, void(Matrix&), ascii::space_type> matrixBlock_;

Update

to clarify the question:

if I write the rule with no semantic actions the synthesized attribute of matrix_ would be

vector< vector< columnT > >

–

typedef vector<columnT> Matrix;
matrix_ = repeat(numBlocks)[ matrixBlock_ ];
matrixBlock_ = *column;

qi::rule<Iterator, Matrix(), ascii::space_type> matrix_;
qi::rule<Iterator, Matrix(), ascii::space_type> matrixBlock_;

I want it to have the same attribute type as matrixBlock_, a 1-dimansional array.


my actual solution is to use only one rule. (looks to easy 🙂 )

typedef vector<columnT> Matrix;
matrix_ = repeat(numBlocks)[ *column_[ phoenix::push_back(_val, _1) ] ];
//matrixBlock_ = *column;

qi::rule<Iterator, Matrix(), ascii::space_type> matrix_;
//qi::rule<Iterator, Matrix(), ascii::space_type> matrixBlock_;

Update

I was able to reproduce the the phantom entries with this code in vs2010 and boost 1.46.1

http://liveworkspace.org/code/505091dc4631a379763567168a728e0c

output was: 42, 45, -9, 3, 2, 1, 12, 34, 56, 0, 0, 0

My mistake was using an old Boost version. There are no phontoms with 1.5.

Now I have two working versions of my grammar. Is it possible to redesign the grammar without the use of the push_back semantic action?

  • 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-11T17:01:54+00:00Added an answer on June 11, 2026 at 5:01 pm

    Updated

    Answering your edited question: Yes you can do this without semantic actions, doing simply:

    template<typename It>
    struct Parser : qi::grammar<It, Matrix(), qi::space_type>
    {
        Parser() : Parser::base_type(matrix_)
        {
            matrixBlock_ = qi::lit(";") >> *qi::int_;
            matrix_      = qi::repeat(3)[ matrixBlock_ ];
        }
        qi::rule<It, Matrix(), qi::space_type> matrixBlock_, matrix_;
    };
    

    Note that you may want to validate the number of rows/columns. See my extended sample, which uses an extra semantic action to check that (note the subtle change from *int_ to +int_ to avoid empty rows):

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace qi    = boost::spirit::qi;
    namespace karma = boost::spirit::karma;
    namespace phx   = boost::phoenix;
    
    typedef std::vector<int> Matrix;
    
    template<typename It>
    struct Parser : qi::grammar<It, Matrix(), qi::space_type>
    {
        Parser() : Parser::base_type(matrix_)
        {
            using namespace qi;
            matrixBlock_ = lit(";") >> +int_ >> eps( 0 == (phx::size(_val) % 3));
            matrix_      = repeat(3)[ matrixBlock_ ];
        }
        qi::rule<It, Matrix(), qi::space_type> matrixBlock_, matrix_;
    };
    
    int main()
    {
        std::string test = ";42 45 -9; 3 2 1; 12 34 56";
    
        std::string::const_iterator f(test.begin()), l(test.end());
    
        Parser<std::string::const_iterator> parser;
        Matrix m;
    
        if (qi::phrase_parse(f,l,parser,qi::space, m))
            std::cout << "Wokay\n";
        else
            std::cerr << "Uhoh\n";
    
        std::cout << karma::format(karma::auto_ % ", ", m) << "\n";
    }
    

    Old answer:

    Yes, you can use Spirit’s customization points to treat your user-defined type as a container. The documentation entry I’d suggest for this is here:

    • http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/advanced/customize/is_container.html

    Here is a simple example showing how to use it, live:

    • http://liveworkspace.org/code/2d708ecb64ad6fbf9708c203f26965ce

    Side note with regards to ‘phantom entries’, in general:

    Note that there is a bit of a FAQ related to backtracking grammars and container attributes. The thing is, for performance reasons, parsers won’t undo (‘rollback’) changes to their underlying containers on backtracking. You can force this behaviour using qi::hold but it may worth the effort to redesign the grammar to either

    • avoid backtracking or
    • commit to the attribute at a later stage (using semantic actions)

    Full code sample:

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    
    namespace qi = boost::spirit::qi;
    namespace karma = boost::spirit::karma;
    
    struct Matrix
    {
       std::vector<int> data;
    };
    
    namespace boost { namespace spirit { namespace traits {
       template <>
          struct is_container<Matrix>
          {
          };
    
       template <typename Attrib>
          struct push_back_container<Matrix, Attrib>
          {
             static bool call(Matrix& c, Attrib const& val)
             {
                c.data.push_back(val);
                return true;
             }
          };
    
       template <>
          struct container_value<Matrix>
          {
             typedef int type;
          };
    } } }
    
    template<typename It>
    struct Parser : qi::grammar<It, Matrix(), qi::space_type>
    {
       Parser() : Parser::base_type(start)
       {
          start = *qi::int_;
       }
       qi::rule<It, Matrix(), qi::space_type> start;
    };
    
    int main()
    {
       std::string test = "42 45 -9";
    
       std::string::const_iterator f(test.begin()),
          l(test.end());
    
       Parser<std::string::const_iterator> parser;
       Matrix m;
    
        if (qi::phrase_parse(f,l,parser,qi::space, m))
          std::cout << "Wokay\n";
       else
          std::cerr << "Uhoh\n";
    
       std::cout << karma::format(karma::auto_ % ", ", m.data) << "\n";
    }
    

    Output:

    Wokay
    42, 45, -9
    

    Update

    A little more background:

    Of course, for a trivial example like this, that just wraps a standard supported container type, it would be fairly easy to employ fusion adaptation instead: ( http://liveworkspace.org/code/56aea8619867451a21cd49fddb1e93bd )

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    #include <boost/fusion/adapted/struct.hpp>
    
    namespace qi = boost::spirit::qi;
    namespace karma = boost::spirit::karma;
    
    struct Matrix { std::vector<int> data; }; 
    BOOST_FUSION_ADAPT_STRUCT(Matrix, (std::vector<int>, data));
    
    int main()
    {
        std::string test = "42 45 -9";
        std::string::const_iterator f(test.begin()), l(test.end());
    
        Matrix m;
        if (qi::phrase_parse(f,l, qi::eps >> *qi::int_, qi::space, m))
            std::cout << karma::format(karma::auto_ % ", ", m.data) << "\n";
    }
    

    Note that the qi::eps is necessary due to a bug (AFAICT) with structs that contain only one data element. See e.g. discussion here (and some other mentions)

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

Sidebar

Related Questions

I have two CSS rules following each other: .some td:first-child:before { content:url('path/to/image.png') ; }
My project have two main requirements 1) Different set of rules applied to same
I have two columns say Main and Sub . (they can be of same
I have two different domains that both point to my homepage in the same
I have two domains for the same website. I have a single page on
I have an area in which I want to add two buttons inside in.
I have a rules engine, which supports two modes of operations: Compilation into a
I have an issue where we are running two systems on the same EC2
I have two types of text that need to follow similar coloring rules based
I am using rails3 and gem devise and i have two roles admin and

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.