Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

c++ - Boost Spirit parser with inherited attributes - simple example won't compile

I'm trying to write a parser for a C-like language with boost::spirit that uses inherited attributes to transfer information about variable scope. For instance, "namespace a { var b }" would pass "a" as an attribute to the parser for "var b".

I'm having trouble getting a basic parser using inherited attributes to compile this code:

#ifndef CPARSER_DEF_HPP
#define CPARSER_DEF_HPP

#include <string>

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

namespace encoding = boost::spirit::ascii;
using boost::spirit::unused_type;
using boost::spirit::qi::rule;

template <typename Iterator>
struct cparser : boost::spirit::qi::grammar<
                    Iterator,
                    std::string(std::string),
                    encoding::space_type
                    >
{
    rule<Iterator, std::string(std::string), encoding::space_type> start;
    rule<Iterator, std::string(std::string), encoding::space_type> sym_list;

    cparser() :
        cparser::base_type(start)
    {
        sym_list         = encoding::string(boost::spirit::qi::_r1);
        start            = sym_list(boost::spirit::qi::_r1);
    }

};

#endif

This parser is instantiated in main() with cparser<std::string::const_iterator> parser.

I believe this parser should accept a std::string as its inherited attribute, parse input matching this string, then return the string as a synthesised attribute. This example code does not compile, and I cannot figure out why. I have been compiling with GCC and Clang with C++11 enabled. The output from either compiler is huge (approx. 1000 lines), and I cannot make any sense of it. Is there a problem with the use of boost::spirit::qi::_r1? A problem with std::string(std::string) in the rule declarations?

Thanks in advance for your help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I've tried to construct an example here. I'm not sure I've faced the same issues you have(since you didn't provide a way to reproduce them) but I think there were two different problems: The first one, very common, is that PhoenixV2 does not work with "modern compilers" since the breaking change in Boost 1.52 that made BOOST_RESULT_OF_USE_DECLTYPE the default. There are two ways to solve this (at least with the clang version that coliru uses) either use V3 by defining BOOST_SPIRIT_USE_PHOENIX_V3(this is what I would recommend, and I think it should be the default) or return the result_of protocol to the behaviour V2 expects by defining BOOST_RESULT_OF_USE_TR1. The second problem, of which I'm not as familiarized so take this with a grain of salt or simply wait for an answer from "someone" more experienced, is that it seems that you can't pass string literals directly as an inherited attribute, you need to pass them as a string (using phx::val("foo") also seems to work).

Short version: Define BOOST_SPIRIT_USE_PHOENIX_V3 and pass your inherited attributes as a std::string not as a string literal.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...