logo
down
shadow

Using boost::spirit defaulting a parsed value to an earlier value when parsing into a struct


Using boost::spirit defaulting a parsed value to an earlier value when parsing into a struct

By : user2949658
Date : November 17 2020, 01:00 AM
around this issue First of all, instead of spelling out omit[+space], just use a skipper:
code :
bool parsed = qi::phrase_parse(iter, end, (
                   qi::lexeme[+(alnum | '_')]
                >> uint_ >> (uint_ | attr(0))
                >> (("//" >> lexeme[+qi::char_]) | attr(""))
            ), qi::space, result);
rule<It, record_struct(), locals<uint8_t>, space_type> g;

g %= lexeme[+(alnum | '_')]
     >> uint_ [_a = _1] >> (uint_ | attr(_a))
     >> -("//" >> lexeme[+char_]);

parsed = phrase_parse(iter, end, g, space, result);
parsed = phrase_parse(iter, end, (
               lexeme[+(alnum | '_')]
            >> uint_ [ phx::ref(dist_) = _1 ] >> (uint_ | attr(phx::ref(dist_)))
            >> (("//" >> lexeme[+char_]) | attr(""))
        ), space, result);
parsed = phrase_parse(iter, end, (
               lexeme[+(alnum | '_')]
            >> uint_ >> (uint_ | attr(phx::at_c<1>(_val)))
            >> (("//" >> lexeme[+char_]) | attr(""))
        ), space, result);
std::string              name;
uint8_t                  distance;
boost::optional<uint8_t> travelDistance;
std::string              comment;

parsed = phrase_parse(iter, end, (
               lexeme[+(alnum | '_')]
            >> uint_ >> -uint_
            >> -("//" >> lexeme[+char_])
        ), space, name, distance, travelDistance, comment);

result = { name, distance, travelDistance? *travelDistance : distance, comment };
rule<It, uint8_t(uint8_t)> def_uint8 = uint_parser<uint8_t>() | attr(_r1);


Share : facebook icon twitter icon
Parsing into a struct using boost spirit

Parsing into a struct using boost spirit


By : himanshu mewari
Date : March 29 2020, 07:55 AM
fixed the issue. Will look into that further +qi::char_ consumes all input because everything matches.
Fixing the grammar: Live On Coliru
code :
wirenameString = +char_("a-zA-Z_0-9"); // lexeme implicit because no skipper
wireList    = ('{' >> wirenameString % ',' >> '}')
            | wirenameString;
start %= qi::lexeme[ "fanout_n" ]
         >> '#' >> numberString
         >> wirenameString >> '(' >> wireList >> ',' >> wireList >> ");"
       ;
#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace client {
    namespace qi    = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    struct GateStruct {
        int numberOfInputs;
        std::string gateName;
        std::vector<std::string> wireNames_first;
        std::vector<std::string> wireNames_second;
    };
}

BOOST_FUSION_ADAPT_STRUCT(client::GateStruct ,
                          (int ,numberOfInputs)
                          (std::string, gateName)
                          (std::vector<std::string>, wireNames_first)
                          (std::vector<std::string>, wireNames_second)
                         )

namespace client 
{
    template <typename Iterator>
    struct gate_parser : qi::grammar<Iterator, GateStruct(), ascii::space_type> {
        gate_parser() : gate_parser::base_type(start) {
            using qi::int_;
            using qi::lit;
            using ascii::char_;

            wirenameString = +char_("a-zA-Z_0-9"); // lexeme implicit because no skipper
            numberString   = "(" >> int_ >> *(',' >> lit('0')) >> ')';
            wireList       = ('{' >> wirenameString % ',' >> '}')
                        | wirenameString;

            start %= qi::lexeme[ "fanout_n" ]
                     >> '#' >> numberString
                     >> wirenameString >> '(' >> wireList >> ',' >> wireList >> ");"
                   ;

            BOOST_SPIRIT_DEBUG_NODES( (start)(numberString)(wirenameString)(wireList) )
        }
      private:

        qi::rule<Iterator , int(),                      ascii::space_type>  numberString;
        qi::rule<Iterator , std::string()               /* lexeme */>       wirenameString;
        qi::rule<Iterator , std::vector<std::string>(), ascii::space_type>  wireList;
        qi::rule<Iterator , GateStruct(),               ascii::space_type>  start;
    };

}

int main() 
{
    using boost::spirit::ascii::space;
    typedef std::string::const_iterator iterator_type;
    typedef client::gate_parser<iterator_type> gate_parser;

    gate_parser g;
    std::string str;
    while(getline(std::cin, str)) {
        if(str.empty() || str[0] == 'q' || str[0] == 'Q') {
            break;
        }

        client::GateStruct gate;
        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        bool r = phrase_parse(iter, end, g, space, gate);

        if(r) {
            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded\n";
            std::cout << "\n-------------------------\n";
        } else {
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }
        if (iter != end)
            std::cout << "Remaining unparsed: '" << std::string(iter,end) << "'\n";
    }

    std::cout << "Bye...\n";
}
Parsing struct with arrays with Boost Spirit

Parsing struct with arrays with Boost Spirit


By : vextant
Date : March 29 2020, 07:55 AM
With these it helps You have more than 10 fields. You need raise the default sequence size limit in fusion/container/vector/limits.hpp.
Include this before including any boost fusion header (or, any boost header because many libraries may implicitly include it):
code :
#define FUSION_MAX_VECTOR_SIZE 15
boost::spirit parsing into struct with std::array

boost::spirit parsing into struct with std::array


By : kenric yep
Date : March 29 2020, 07:55 AM
Any of those help You are going places :) You seem to have reached warp speed with Spirit in no time.
EDITED After reading the question closer I noticed that you ask for a shorter, less intrusive way.
code :
#include <boost/fusion/include/tuple.hpp>
#include <boost/fusion/adapted/boost_array.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>

namespace boost { namespace spirit { namespace traits {
    template <typename T, size_t N>
        struct is_container<boost::array<T, N>, void> : mpl::false_ { };
} } }

namespace qi    = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct StructWithArray
{
    double dummy_; // see http://stackoverflow.com/questions/19823413/spirit-qi-attribute-propagation-issue-with-single-member-struct
    boost::array<double, 6> ary_;
};

BOOST_FUSION_ADAPT_STRUCT(StructWithArray, dummy_, ary_)

template <typename Iterator, typename Skipper>
struct StructWithArrayParser
    : qi::grammar<Iterator, StructWithArray(), Skipper>
{
    StructWithArrayParser() : StructWithArrayParser::base_type(start)
    {
        using qi::double_;

        arrayLine = double_ > double_ > double_ > double_ > double_ > double_;
        start     = double_ > arrayLine;
    }

  private:
    qi::rule<Iterator, boost::array<double, 6>(), Skipper> arrayLine;
    qi::rule<Iterator, StructWithArray(), Skipper> start;
};

int main() {
    std::string arrayStr = "0 1 2 3 4 5 6";
    using It = std::string::const_iterator;
    It it = arrayStr.begin(), endIt = arrayStr.end();
    StructWithArrayParser<It, ascii::space_type> grammar;

    StructWithArray structWithArray;
    bool ret = phrase_parse(it, endIt, grammar, ascii::space, structWithArray);
    std::cout << std::boolalpha << ret << "\n";

    for (double v : structWithArray.ary_)
        std::cout << v << " ";
}
true
1 2 3 4 5 6 
Boost-Spirit: Parsing lists into different fields of a struct

Boost-Spirit: Parsing lists into different fields of a struct


By : Joao Pimenta
Date : March 29 2020, 07:55 AM
I hope this helps you . I don't really like using semantic actions, but given the choice of AST and input, I don't think there's much of a choice.
I'd simplify the grammar:
code :
    rule  = '(' >> (int_[head_(_val, _1)] % ',') >> ')'
        >> '{' >> +(
                'X' >> int_[X_(_val, _1)]
              | 'Y' >> int_[Y_(_val, _1)]
              | 'Z' >> int_[Z_(_val, _1)]
          )
        >> '}';
template <std::vector<int> my_struct::*m> struct push {
    void operator()(my_struct& ms, int v) const { (ms.*m).push_back(v); }
};
px::function<push<&my_struct::head> > head_;
px::function<push<&my_struct::X> > X_;
px::function<push<&my_struct::Y> > Y_;
px::function<push<&my_struct::Z> > Z_;
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

struct my_struct {
    std::vector<int> head;
    std::vector<int> X;
    std::vector<int> Y;
    std::vector<int> Z;
};

template<typename Iterator>
struct my_parser : qi::grammar<Iterator, my_struct()> {
    my_parser() : my_parser::base_type(start) {
        using namespace qi;
        using px::push_back;

        rule  = '(' >> (int_[head_(_val, _1)] % ',') >> ')'
            >> '{' >> +(
                    'X' >> int_[X_(_val, _1)]
                  | 'Y' >> int_[Y_(_val, _1)]
                  | 'Z' >> int_[Z_(_val, _1)]
              )
            >> '}';

        start = skip(space) [rule];
    }
  private:
    template <std::vector<int> my_struct::*m> struct push {
        void operator()(my_struct& ms, int v) const { (ms.*m).push_back(v); }
    };
    px::function<push<&my_struct::head> > head_;
    px::function<push<&my_struct::X> > X_;
    px::function<push<&my_struct::Y> > Y_;
    px::function<push<&my_struct::Z> > Z_;

    qi::rule<Iterator, my_struct()> start;
    qi::rule<Iterator, my_struct(), qi::space_type> rule;
};

int main() {
    using It = boost::spirit::istream_iterator;
    It f(std::cin >> std::noskipws), l;

    my_struct data;
    if (parse(f, l, my_parser<It>{}, data)) {
        std::cout << "Parsed:";
        std::copy(data.head.begin(), data.head.end(), std::ostream_iterator<int>(std::cout << "\nhead: ", " " ));
        std::copy(data.X.begin(), data.X.end(), std::ostream_iterator<int>(std::cout << "\nX: ", " " ));
        std::copy(data.Y.begin(), data.Y.end(), std::ostream_iterator<int>(std::cout << "\nY: ", " " ));
        std::copy(data.Z.begin(), data.Z.end(), std::ostream_iterator<int>(std::cout << "\nZ: ", " " ));
        std::cout << "\n";
    } else {
        std::cout << "Parse failed\n";
    }


    if (f != l)
        std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
Parsed:
head: 111 222 333 
X: 231 54 
Y: 227 1112 
Z: 41156 
Remaining unparsed input: '
'
Parsing inherited struct with boost spirit

Parsing inherited struct with boost spirit


By : skh
Date : March 29 2020, 07:55 AM
will be helpful for those in need So there's two questions here, I feel:
How to adapt derived classes Can I use BOOST_FUSION_ADAPT_STRUCT with inherited stuff? How can I use polymorphic attributes with boost::spirit::qi parsers? Update
code :
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted.hpp>
#include <map>
#include <iomanip> // std::quoted

struct Base {}; // dynamic polymorphism not required for us now, no problem if you want it

struct A : Base {
    int value;
    void operator()() const { std::cout << "Hello A: " << value << std::endl; };
};

struct B : Base {
    float value;
    void operator()() const { std::cout << "Hello B: " << value << std::endl; };
};

using Node = boost::variant<A, B>;
struct BaseContainer {
    using Map = std::multimap<std::string, Node>;
    Map container;
};

BOOST_FUSION_ADAPT_STRUCT(A, value)
BOOST_FUSION_ADAPT_STRUCT(B, value)
BOOST_FUSION_ADAPT_STRUCT(BaseContainer, container)

namespace qi = boost::spirit::qi;

template <typename It> 
struct Parser : qi::grammar<It, BaseContainer()> {
    Parser() : Parser::base_type(start) {
        using namespace qi;
        _key       = lexeme['"' >> *('\\' >> char_ | ~char_('"')) >> '"'];
        _a_node    = "A(" >> int_ >> ")";
        _b_node    = "B(" >> float_ >> ")";
        _node      = _a_node | _b_node;
        _pair      = '{' >> _key >> ',' >> _node >> '}';
        _container = '{' >> -(_pair % ',') >> '}';

        start = skip(space) [ _container ];

        BOOST_SPIRIT_DEBUG_NODES((start)(_container)(_pair)(_key)(_node)(_a_node)(_b_node))
    }
  private:
    qi::rule<It, BaseContainer()> start;

    // lexeme
    qi::rule<It, std::string()> _key;

    using Skipper = qi::space_type;
    using Pair = std::pair<std::string, Node>;

    qi::rule<It, BaseContainer::Map(), Skipper> _container;
    qi::rule<It, Pair(), Skipper> _pair;
    qi::rule<It, Node(), Skipper> _node;
    qi::rule<It, A(), Skipper> _a_node;
    qi::rule<It, B(), Skipper> _b_node;
};

int main() {
    Parser<std::string::const_iterator> const p;
    for (std::string const input : {
            R"({})",
            R"({ { "one", A(42) } })",
            R"({ { "two", B(3.14) } })",
            R"({ { "three", A( -42 ) }, { "four", B( -3.14 ) } })",
            })
    {
        std::cout << "-------\n";
        std::cout << "Parsing " << input << "\n";
        auto f = begin(input), l = end(input);

        BaseContainer result;
        if (qi::parse(f, l, p, result)) {
            for (auto const& [k,v] : result.container) {
                std::cout << " Key " << std::quoted(k) << ": ";
                boost::apply_visitor([](auto const& node) { node(); }, v);
            }
        } else {
            std::cout << "Parse failed\n";
        }

        if (f!=l) {
            std::cout << "Remaining unparsed: " << std::quoted(std::string(f,l)) << "\n";
        }
    }
}
-------
Parsing {}
-------
Parsing { { "one", A(42) } }
 Key "one": Hello A: 42
-------
Parsing { { "two", B(3.14) } }
 Key "two": Hello B: 3.14
-------
Parsing { { "three", A( -42 ) }, { "four", B( -3.14 ) } }
 Key "four": Hello B: -3.14
 Key "three": Hello A: -42
Related Posts Related Posts :
  • How to use SDL_MapRGB with SDL 2.0
  • how compiler and interpreter work in case of array declaration
  • GSL integration behaves strange
  • Cropping an image with OpenCV and C
  • Find the last line in text file and select the first 10 char and print to a new file?
  • Created many CCSprits but when triggering ccTouchBegan gives the last one allways
  • seekp and seekg don't work with fstream
  • Taking input in Sublime Text 3
  • ld: -bind_at_load and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together
  • C++ storing #define as std::string would give size as zero compile time
  • How to use static linking with OpenSSL in C/C++
  • What is the difference between a trap, an error, a failure and program abortion?
  • Dynamic members allocation in qt
  • How to reduce object file size when compiling for VxWorks 5.5.1?
  • Printing char by integer qualifier
  • How to write code to be executed before main() gets control?
  • Blocking socket - waitForReadyRead()
  • std::string related errors and handling them, c++
  • VM interpreter - weighting performance benefits and drawbacks of larger instruction set / dispatch loop
  • C / C++ SHIFT / OFFSET / MOVE a Bitmap to the LEFT or RIGHT?
  • Printing numbers column by column
  • How do you change your app icon in visual studio 2013?
  • Fast Screen Transfer
  • c++ Read text file and input the numbers into a 2D array
  • Why are my C++ pointers suddenly diverging?
  • Is there a macro-based adapter to make a functor from a class?
  • CRTP and multilevel inheritance
  • How to implement timer for each object in c++?
  • Stuck when testing custom list class in c++
  • Using each member of class within one function to calculate average
  • check whether if two squares are intersecting with each other
  • Glm Quaternion lookat function
  • Is there guarantee heap allocated block address will not change(implicitly)?
  • Cosine Calculation without cmath library
  • Manually deleting a pointer returned by function
  • Avoid output interleaving
  • C++ error : Expected an identifier
  • Segmentation fault when I call operator new in linux mint
  • Recursively Solving A Sudoku Puzzle Using Backtracking Theoretically
  • lambda closure type and default argument in function template
  • How to ensure the function return consistent floating point values in C/C++?
  • What does throw do when not in used with try and catch?
  • The Unpredictablilty of the Order of Evaluation of Subexpressions
  • cannot convert const wchar_t to 'const_char' for argument 2 in MessageBOX etc etc
  • Size of a empty Class & Derived Virtual Class
  • unformatted i/o to and from memory
  • Storing an std::thread object as a class member
  • Remove duplicate string in an array
  • How to use copy_if() polymorphically?
  • How to organize a class's member functions?
  • How to wrap std::chrono in a c++ iterator type
  • Check if a socket is connected in mac os x
  • Grabbing the mouse cursor in GLFW
  • Calling Windows shell menu (same as right-click in Explorer) for multiple files programmatically
  • Pop up dialog to save file in seperate thread
  • Why would you use the keyword const if you already know variable should be constant?
  • Detecting Small Sound Effects In C++
  • How to avoid the copy when I return
  • Getting error code C2228: left of '._Ptr' must have class/struct/union
  • In win32 C++ programming how can I duplicate a window style?
  • shadow
    Privacy Policy - Terms - Contact Us © ourworld-yourmove.org