无法获得boost :: spirit解析器和词法分析器,除了std :: string或int或double之外的令牌类型

时间:2017-11-08 23:33:24

标签: c++ boost boost-spirit boost-spirit-qi boost-spirit-lex

这不编译(下面的代码)。

这里有另一个问题,同样的错误。但我不明白答案。我已经尝试在地方插入qi :: eps - 但没有成功。

我也尝试为已使用的类型添加元函数(boost :: spirit :: raits :: is_container) - 但这也无济于事。

我也尝试使用包含我需要在任何地方使用的所有类型的相同变体。同样的问题。

有没有人为lexer返回其他东西而不是double或int或string?并且解析器还返回非平凡的对象?

我尝试在返回默认对象的地方实现语义功能。但这也无济于事。

代码如下:

// spirit_error.cpp : Defines the entry point for the console application.
//

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/phoenix/object.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/mpl/index_of.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>

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


namespace frank
{
class ref_counter:public boost::intrusive_ref_counter<ref_counter>
{   public:
    virtual ~ref_counter(void)
    {
    }
};
class symbol:public ref_counter
{   public:
    typedef boost::intrusive_ptr<const symbol> symbolPtr;
    typedef std::vector<symbolPtr> symbolVector;
    struct push_scope
    {   push_scope()
        {
        }
        ~push_scope(void)
        {
        }
    };
};
class nature:public symbol
{   public:
    enum enumAttribute
    {   eAbstol,
        eAccess,
        eDDT,
        eIDT,
        eUnits
    };
    struct empty
    {   bool operator<(const empty&) const
        {   return false;
        }
        friend std::ostream &operator<<(std::ostream &_r, const empty&)
        {   return _r;
        }
    };
    typedef boost::variant<empty, std::string> attributeValue;
};
class discipline:public symbol
{   public:
    enum enumDomain
    {   eDiscrete,
        eContinuous
    };
};

class type:public ref_counter
{   public:
    typedef boost::intrusive_ptr<type> typePtr;
};
struct myIterator:std::iterator<std::random_access_iterator_tag, char, std::ptrdiff_t, const char*, const char&>
{   std::string *m_p;
    std::size_t m_iPos;
    myIterator(void)
        :m_p(nullptr),
        m_iPos(~std::size_t(0))
    {
    }
    myIterator(std::string &_r, const bool _bEnd = false)
        :m_p(&_r),
        m_iPos(_bEnd ? ~std::size_t(0) : 0)
    {
    }
    myIterator(const myIterator &_r)
        :m_p(_r.m_p),
        m_iPos(_r.m_iPos)
    {
    }
    myIterator &operator=(const myIterator &_r)
    {   if (this != &_r)
        {   m_p = _r.m_p;
            m_iPos = _r.m_iPos;
        }
        return *this;
    }
    const char &operator*(void) const
    {   return m_p->at(m_iPos);
    }
    bool operator==(const myIterator &_r) const
    {   return m_p == _r.m_p && m_iPos == _r.m_iPos;
    }
    bool operator!=(const myIterator &_r) const
    {   return m_p != _r.m_p || m_iPos != _r.m_iPos;
    }
    myIterator &operator++(void)
    {   ++m_iPos;
        if (m_iPos == m_p->size())
            m_iPos = ~std::size_t(0);
        return *this;
    }
    myIterator operator++(int)
    {   const myIterator s(*this);
        operator++();
        return s;
    }
    myIterator &operator--(void)
    {   --m_iPos;
        return *this;
    }
    myIterator operator--(int)
    {   const myIterator s(*this);
        operator--();
        return s;
    }
    bool operator<(const myIterator &_r) const
    {   if (m_p == _r.m_p)
            return m_iPos < _r.m_iPos;
        else
            return m_p < _r.m_p;
    }
    std::ptrdiff_t operator-(const myIterator &_r) const
    {   return m_iPos - _r.m_iPos;
    }
};
struct onInclude
{   auto operator()(myIterator &_rStart, myIterator &_rEnd) const
    {       // erase what has been matched (the include statement)
        _rStart.m_p->erase(_rStart.m_iPos, _rEnd.m_iPos - _rStart.m_iPos);
        // and insert the contents of the file
        _rStart.m_p->insert(_rStart.m_iPos, "abcd");
        _rEnd = _rStart;
        return lex::pass_flags::pass_ignore;
    }
};
template<typename LEXER>
class lexer:public lex::lexer<LEXER>
{   public:
    lex::token_def<type::typePtr> m_sKW_real, m_sKW_integer, m_sKW_string;
    lex::token_def<lex::omit> m_sLineComment, m_sCComment;
    lex::token_def<lex::omit> m_sWS;
    lex::token_def<lex::omit> m_sSemicolon, m_sEqual, m_sColon, m_sInclude, m_sCharOP, m_sCharCP,
        m_sComma;
    lex::token_def<std::string> m_sIdentifier, m_sString;
    lex::token_def<double> m_sReal;
    lex::token_def<int> m_sInteger;
    lex::token_def<lex::omit> m_sKW_units, m_sKW_access, m_sKW_idt_nature, m_sKW_ddt_nature, m_sKW_abstol,
        m_sKW_nature, m_sKW_endnature, m_sKW_continuous, m_sKW_discrete,
        m_sKW_potential, m_sKW_flow, m_sKW_domain, m_sKW_discipline, m_sKW_enddiscipline, m_sKW_module,
        m_sKW_endmodule, m_sKW_parameter;
    //typedef const type *typePtr;
    template<typename T>
    struct extractValue
    {   T operator()(const myIterator &_rStart, const myIterator &_rEnd) const
        {   return boost::lexical_cast<T>(std::string(_rStart, _rEnd));
        }
    };
    struct extractString
    {   std::string operator()(const myIterator &_rStart, const myIterator &_rEnd) const
        {   const auto s = std::string(_rStart, _rEnd);
            return s.substr(1, s.size() - 2);
        }
    };
    lexer(void)
        :m_sWS("[ \\t\\n\\r]+"),
        m_sKW_parameter("\"parameter\""),
        m_sKW_real("\"real\""),
        m_sKW_integer("\"integer\""),
        m_sKW_string("\"string\""),
        m_sLineComment("\\/\\/[^\\n]*"),
        m_sCComment("\\/\\*"
            "("
                "[^*]"
                    "|" "[\\n]"
                    "|" "([*][^/])"
            ")*"
            "\\*\\/"),
        m_sSemicolon("\";\""),
        m_sEqual("\"=\""),
        m_sColon("\":\""),
        m_sCharOP("\"(\""), 
        m_sCharCP("\")\""),
        m_sComma("\",\""),
        m_sIdentifier("[a-zA-Z_]+[a-zA-Z0-9_]*"),
        m_sString("[\\\"]"
            //"("
            //  "(\\[\"])"
            //  "|"
                //"[^\"]"
            //")*"
            "[^\\\"]*"
            "[\\\"]"),
        m_sKW_units("\"units\""),
        m_sKW_access("\"access\""),
        m_sKW_idt_nature("\"idt_nature\""),
        m_sKW_ddt_nature("\"ddt_nature\""),
        m_sKW_abstol("\"abstol\""),
        m_sKW_nature("\"nature\""),
        m_sKW_endnature("\"endnature\""),
        m_sKW_continuous("\"continuous\""),
        m_sKW_discrete("\"discrete\""),
        m_sKW_domain("\"domain\""),
        m_sKW_discipline("\"discipline\""),
        m_sKW_enddiscipline("\"enddiscipline\""),
        m_sKW_potential("\"potential\""),
        m_sKW_flow("\"flow\""),
//realnumber      ({uint}{exponent})|((({uint}\.{uint})|(\.{uint})){exponent}?)
//exponent        [Ee][+-]?{uint}
//uint            [0-9][_0-9]*

        m_sReal("({uint}{exponent})"
            "|"
                "("
                    "(({uint}[\\.]{uint})|([\\.]{uint})){exponent}?"
                ")"
        ),
        m_sInteger("{uint}"),
        m_sInclude("\"`include\""),
        m_sKW_module("\"module\""),
        m_sKW_endmodule("\"endmodule\"")
    {   this->self.add_pattern
            ("uint", "[0-9]+")
            ("exponent", "[eE][\\+\\-]?{uint}");
        this->self = m_sSemicolon
            | m_sEqual
            | m_sColon
            | m_sCharOP
            | m_sCharCP
            | m_sComma
            | m_sString[lex::_val = boost::phoenix::bind(extractString(), lex::_start, lex::_end)]
            | m_sKW_real//[lex::_val = boost::phoenix::bind(&type::getReal)]
            | m_sKW_integer//[lex::_val = boost::phoenix::bind(&type::getInteger)]
            | m_sKW_string//[lex::_val = boost::phoenix::bind(&type::getString)]
            | m_sKW_parameter
            | m_sKW_units
            | m_sKW_access
            | m_sKW_idt_nature
            | m_sKW_ddt_nature
            | m_sKW_abstol
            | m_sKW_nature
            | m_sKW_endnature
            | m_sKW_continuous
            | m_sKW_discrete
            | m_sKW_domain
            | m_sKW_discipline
            | m_sKW_enddiscipline
            | m_sReal[lex::_val = boost::phoenix::bind(extractValue<double>(), lex::_start, lex::_end)]
            | m_sInteger[lex::_val = boost::phoenix::bind(extractValue<int>(), lex::_start, lex::_end)]
            | m_sKW_potential
            | m_sKW_flow
            | m_sKW_module
            | m_sKW_endmodule
            | m_sIdentifier
            | m_sInclude [ lex::_state = "INCLUDE" ]
            ;
        this->self("INCLUDE") += m_sString [
            lex::_state = "INITIAL", lex::_pass = boost::phoenix::bind(onInclude(), lex::_start, lex::_end)
        ];
        this->self("WS") = m_sWS
            | m_sLineComment
            | m_sCComment
            ;
    }
};
template<typename Iterator, typename Lexer>
class natureParser:public qi::grammar<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> >
{   qi::rule<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> > m_sStart;
    qi::rule<Iterator, std::pair<nature::enumAttribute, nature::attributeValue>(void), qi::in_state_skipper<Lexer> > m_sProperty;
    qi::rule<Iterator, std::string(), qi::in_state_skipper<Lexer> > m_sName;
    public:
    template<typename Tokens>
    natureParser(const Tokens &_rTokens)
        :natureParser::base_type(m_sStart)
    {   m_sProperty = (_rTokens.m_sKW_units
                >> _rTokens.m_sEqual
                >> _rTokens.m_sString
                >> _rTokens.m_sSemicolon
                )
            | (_rTokens.m_sKW_access
                >> _rTokens.m_sEqual
                >> _rTokens.m_sIdentifier
                >> _rTokens.m_sSemicolon
                )
            | (_rTokens.m_sKW_idt_nature
                >> _rTokens.m_sEqual
                >> _rTokens.m_sIdentifier
                >> _rTokens.m_sSemicolon
                )
            | (_rTokens.m_sKW_ddt_nature
                >> _rTokens.m_sEqual
                >> _rTokens.m_sIdentifier
                >> _rTokens.m_sSemicolon
                )
            | (_rTokens.m_sKW_abstol
                >> _rTokens.m_sEqual
                >> _rTokens.m_sReal
                >> _rTokens.m_sSemicolon
                )
            ;
        m_sName = (_rTokens.m_sColon >> _rTokens.m_sIdentifier);
        m_sStart = (_rTokens.m_sKW_nature
            >> _rTokens.m_sIdentifier
            >> -m_sName
            >> _rTokens.m_sSemicolon
            >> *(m_sProperty)
            >> _rTokens.m_sKW_endnature
            );
        m_sStart.name("start");
        m_sProperty.name("property");
    }
};
/*
// Conservative discipline
discipline electrical; 
  potential    Voltage;
  flow         Current;
enddiscipline
*/
// a parser for a discipline declaration
template<typename Iterator, typename Lexer>
class disciplineParser:public qi::grammar<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> >
{   qi::rule<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> > m_sStart;
    typedef std::pair<bool, boost::intrusive_ptr<const nature> > CPotentialAndNature;
    struct empty
    {   bool operator<(const empty&) const
        {   return false;
        }
        friend std::ostream &operator<<(std::ostream &_r, const empty&)
        {   return _r;
        }
    };
    typedef boost::variant<empty, CPotentialAndNature, discipline::enumDomain> property;
    qi::rule<Iterator, discipline::enumDomain(), qi::in_state_skipper<Lexer> > m_sDomain;
    qi::rule<Iterator, property(void), qi::in_state_skipper<Lexer> > m_sProperty;
    public:
    template<typename Tokens>
    disciplineParser(const Tokens &_rTokens)
        :disciplineParser::base_type(m_sStart)
    {   m_sDomain = _rTokens.m_sKW_continuous
            | _rTokens.m_sKW_discrete
            ;
        m_sProperty = (_rTokens.m_sKW_potential >> _rTokens.m_sIdentifier >> _rTokens.m_sSemicolon)
            | (_rTokens.m_sKW_flow >> _rTokens.m_sIdentifier >> _rTokens.m_sSemicolon)
            | (_rTokens.m_sKW_domain >> m_sDomain >> _rTokens.m_sSemicolon)
            ;
        m_sStart = (_rTokens.m_sKW_discipline
            >> _rTokens.m_sIdentifier
            >> _rTokens.m_sSemicolon
            >> *m_sProperty
            >> _rTokens.m_sKW_enddiscipline
        );
    }
};
template<typename Iterator, typename Lexer>
class moduleParser:public qi::grammar<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> >
{   public:
    qi::rule<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> > m_sStart;
    qi::rule<Iterator, symbol::symbolVector(void), qi::in_state_skipper<Lexer> > m_sModulePortList;
    qi::rule<Iterator, symbol::symbolVector(void), qi::in_state_skipper<Lexer> > m_sPortList;
    qi::rule<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> > m_sPort;
    qi::rule<Iterator, std::shared_ptr<symbol::push_scope>(void), qi::in_state_skipper<Lexer> > m_sModule;

    typedef boost::intrusive_ptr<const ref_counter> intrusivePtr;
    typedef std::vector<intrusivePtr> vectorOfPtr;
    qi::rule<Iterator, vectorOfPtr(void), qi::in_state_skipper<Lexer> > m_sModuleItemList;
    qi::rule<Iterator, intrusivePtr(void), qi::in_state_skipper<Lexer> > m_sParameter;
    qi::rule<Iterator, intrusivePtr(void), qi::in_state_skipper<Lexer> > m_sModuleItem;
    qi::rule<Iterator, type::typePtr(void), qi::in_state_skipper<Lexer> > m_sType;

    template<typename Tokens>
    moduleParser(const Tokens &_rTokens)
        :moduleParser::base_type(m_sStart)
    {   m_sPort = _rTokens.m_sIdentifier;
        m_sPortList %= m_sPort % _rTokens.m_sComma;
        m_sModulePortList %= _rTokens.m_sCharOP >> m_sPortList >> _rTokens.m_sCharCP;
        m_sModule = _rTokens.m_sKW_module;
        m_sType = _rTokens.m_sKW_real | _rTokens.m_sKW_integer | _rTokens.m_sKW_string;
        m_sParameter = _rTokens.m_sKW_parameter
            >> m_sType
            >> _rTokens.m_sIdentifier
        ;
        m_sModuleItem = m_sParameter;
        m_sModuleItemList %= *m_sModuleItem;
        m_sStart = (m_sModule
                >> _rTokens.m_sIdentifier
                >> m_sModulePortList
                >> m_sModuleItemList
                >> _rTokens.m_sKW_endmodule);
    }
};
template<typename Iterator, typename Lexer>
class fileParser:public qi::grammar<Iterator, symbol::symbolVector(void), qi::in_state_skipper<Lexer> >
{   public:
    disciplineParser<Iterator, Lexer> m_sDiscipline;
    natureParser<Iterator, Lexer> m_sNature;
    moduleParser<Iterator, Lexer> m_sModule;
    qi::rule<Iterator, symbol::symbolVector(void), qi::in_state_skipper<Lexer> > m_sStart;
    qi::rule<Iterator, symbol::symbolPtr(void), qi::in_state_skipper<Lexer> > m_sItem;
    //public:
    template<typename Tokens>
    fileParser(const Tokens &_rTokens)
        :fileParser::base_type(m_sStart),
        m_sNature(_rTokens),
        m_sDiscipline(_rTokens),
        m_sModule(_rTokens)
    {   m_sItem = m_sDiscipline | m_sNature | m_sModule;
        m_sStart = *m_sItem;
    }
};
}
int main()
{   std::string sInput = "\
nature Current;\n\
  units        = \"A\";\n\
  access       = I;\n\
  idt_nature   = Charge;\n\
  abstol       = 1e-12;\n\
endnature\n\
\n\
// Charge in coulombs\n\
nature Charge;\n\
  units      = \"coul\";\n\
  access     = Q;\n\
  ddt_nature = Current;\n\
  abstol     = 1e-14;\n\
endnature\n\
\n\
// Potential in volts\n\
nature Voltage;\n\
  units      = \"V\";\n\
  access     = V;\n\
  idt_nature = Flux;\n\
  abstol     = 1e-6;\n\
endnature\n\
\n\
discipline electrical;\n\
  potential    Voltage;\n\
  flow         Current;\n\
enddiscipline\n\
";
    typedef lex::lexertl::token<frank::myIterator, boost::mpl::vector<frank::type::typePtr, std::string, double, int> > token_type;
    typedef lex::lexertl::actor_lexer<token_type> lexer_type;
    typedef frank::lexer<lexer_type>::iterator_type iterator_type;
    typedef frank::fileParser<iterator_type, frank::lexer<lexer_type>::lexer_def> grammar_type;

    frank::lexer<lexer_type> sLexer;
    grammar_type sParser(sLexer);
    frank::symbol::push_scope sPush;
    auto pStringBegin = frank::myIterator(sInput);
    auto pBegin(sLexer.begin(pStringBegin, frank::myIterator(sInput, true)));
    const auto b = qi::phrase_parse(pBegin, sLexer.end(), sParser, qi::in_state("WS")[sLexer.self]); 
}

1 个答案:

答案 0 :(得分:0)

一种解决方案是在任何地方使用std :: string,并使用所需的一切定义boost :: variant,但不能直接在解析器或词法分析器中的任何位置使用它,而只能序列化和放大。将其反序列化为字符串。

这是boost :: spirit的创始人的意图吗?