C++ 交叉递归规则的声明

C++ 交叉递归规则的声明,c++,recursion,static,boost-spirit,forward-declaration,C++,Recursion,Static,Boost Spirit,Forward Declaration,我将语法规则声明为静态常量。在我尝试使用交叉递归规则(rule1是使用rule2定义的,而rule2是使用rule1定义的)之前,这一切都很好。源代码仍然可以构建,但是在解析包含这种交叉递归情况的源代码时会出错。 以下是简化的语法代码: template < typename Iterator > class Skipper : public qi::grammar<Iterator> { public: Skipper ( ) : Skipper::base_t

我将语法规则声明为静态常量。在我尝试使用交叉递归规则(rule1是使用rule2定义的,而rule2是使用rule1定义的)之前,这一切都很好。源代码仍然可以构建,但是在解析包含这种交叉递归情况的源代码时会出错。 以下是简化的语法代码:

template < typename Iterator >
class Skipper : public qi::grammar<Iterator> {
public:
    Skipper ( ) : Skipper::base_type(_skip_rule) { }
private:
    static qi::rule<Iterator> const
        _comment,
        _skip_rule;
};

template < typename Iterator >
typename qi::rule<Iterator> const
    Skipper<Iterator>::_comment(
        boost::spirit::repository::confix("/*", "*/")[*(qi::char_ - "*/")]          // Multi-line
        | boost::spirit::repository::confix("//", qi::eol)[*(qi::char_ - qi::eol)]   // Single-line
    );

template < typename Iterator >
typename qi::rule<Iterator> const
     Skipper<Iterator>::_skip_rule(qi::ascii::space | _comment);

template < typename Iterator, typename Skipper >
class Grammar : public qi::grammar<Iterator, Skipper > {
public:
    Grammar ( ) : Grammar::base_type(expression) { }
private:
    static qi::rule<Iterator, Skipper> const
        // Tokens
        scalar_literal,
        identifier,
        // Rules
        operand,
        expression;
};

template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
    Grammar<Iterator, Skipper>::scalar_literal(qi::uint_ | qi::int_);

template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
    Grammar<Iterator, Skipper>::identifier(qi::lexeme[(qi::alpha | '_') >> *(qi::alnum | '_')]);

template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
    Grammar<Iterator, Skipper>::operand((scalar_literal | identifier | ('(' >> expression >> ')')));

template < typename Iterator, typename Skipper >
typename qi::rule<Iterator, Skipper> const
    Grammar<Iterator, Skipper>::expression(operand);
template
课堂队长:公共qi::语法{
公众:
Skipper():Skipper::base_type(_skip_rule){}
私人:
静态qi::规则常量
_评论,,
_跳转规则;
};
模板
typename qi::规则常量
船长::_评论(
boost::spirit::repository::confix(“//*”,“*/”[*(qi::char_-“*/”)//多行
|boost::spirit::repository::confix(“//”,qi::eol)[*(qi::char\uqi::eol)]//单行
);
模板
typename qi::规则常量
Skipper::_skip_规则(qi::ascii::space |_注释);
模板
类语法:公共qi::语法{
公众:
Grammar():Grammar::base_类型(表达式){}
私人:
静态qi::规则常量
//代币
标量文字,
标识符,
//规则
操作数,
表达方式;
};
模板
typename qi::规则常量
语法:标量文字(qi::uint|qi::int|);
模板
typename qi::规则常量
语法::标识符(qi::词素[(qi::alpha |'')>>*(qi::alnum |''));
模板
typename qi::规则常量
语法::操作数((标量|文字|标识符|)('('>>表达式>>')));
模板
typename qi::规则常量
语法::表达式(操作数);
(表达式规则与操作数相同,以使代码更易于理解;当然,它应该更复杂,但基于操作数)。操作数声明使用表达式1,反之亦然。例如(123),当试图解析_短语时会出现错误。我想这是因为表达的“向前”使用;如果将表达式声明放在操作数1之前,也会发生同样的情况。那么,应该以何种方式声明这些规则以避免运行时错误呢

  • 首先,静电与之无关:

    同样严重地失败:

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/repository/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    template <typename Iterator>
    struct Skipper : qi::grammar<Iterator> {
        Skipper() : Skipper::base_type(_skip_rule) { }
    private:
        qi::rule<Iterator> const
            _comment { 
                boost::spirit::repository::confix("/*", "*/")    [*(qi::char_ - "*/")]     // Multi-line
            | boost::spirit::repository::confix("//", qi::eol) [*(qi::char_ - qi::eol)]  // Single-line
            },
            _skip_rule {
                qi::ascii::space | _comment
            };
    };
    
    template <typename Iterator, typename Skipper>
    struct Grammar : qi::grammar<Iterator, Skipper> {
        Grammar() : Grammar::base_type(expression) { }
    private:
        qi::rule<Iterator, Skipper> const
            // Tokens
            scalar_literal { qi::uint_ | qi::int_ },
            identifier     { qi::lexeme[(qi::alpha | '_') >> *(qi::alnum | '_')] },
            // Rules
            operand        { (scalar_literal | identifier | ('(' >> expression >> ')')) },
            expression     { operand };
    };
    
    int main() {
        using It = std::string::const_iterator;
        Skipper<It> s;
        Grammar<It, Skipper<It> > p;
        std::string const input = "(123)";
    
        It f = input.begin(), l = input.end();
    
        bool ok = qi::phrase_parse(f,l,p,s);
    
        if (ok)   std::cout << "Parse success\n";
        else      std::cout << "Parse failed\n";
        if (f!=l) std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
    
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/repository/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    template <typename Iterator, typename Skipper = qi::ascii::space_type>
    struct Grammar : qi::grammar<Iterator, Skipper> {
        Grammar() : Grammar::base_type(expression) { }
    private:
        qi::rule<Iterator, Skipper> const
            // Tokens
            scalar_literal { qi::uint_ | qi::int_ },
            identifier     { qi::lexeme[(qi::alpha | '_') >> *(qi::alnum | '_')] },
            // Rules
            operand        { (scalar_literal | identifier | ('(' >> expression >> ')')) },
            expression     { operand };
    };
    
    int main() {
        using It = std::string::const_iterator;
        Grammar<It> p;
        std::string const input = "(123)";
    
        It f = input.begin(), l = input.end();
    
        bool ok = qi::phrase_parse(f,l,p,qi::ascii::space);
    
        if (ok)   std::cout << "Parse success\n";
        else      std::cout << "Parse failed\n";
        if (f!=l) std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
    
  • 最后,你可以吃下所有的蛋糕:

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/repository/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    namespace parsing {
        namespace detail {
            template <typename Iterator>
            struct Skipper : qi::grammar<Iterator> {
                Skipper() : Skipper::base_type(_skip_rule) {
                    _comment  = boost::spirit::repository::confix("/*", "*/")    [*(qi::char_ - "*/")]     // Multi-line
                            | boost::spirit::repository::confix("//", qi::eol) [*(qi::char_ - qi::eol)]  // Single-line
                            ;
    
                    _skip_rule = qi::ascii::space | _comment;
                }
            private:
                qi::rule<Iterator> _comment, _skip_rule;
            };
    
            template <typename Iterator, typename Skipper = Skipper<Iterator> >
            struct Grammar : qi::grammar<Iterator, Skipper> {
                Grammar() : Grammar::base_type(expression) {
                    scalar_literal = qi::uint_ | qi::int_;
                    identifier     = (qi::alpha | '_') >> *(qi::alnum | '_');
                    // Rules
                    operand        = (scalar_literal | identifier | ('(' >> expression >> ')'));
                    expression     = operand;
                }
            private:
                qi::rule<Iterator>          scalar_literal, identifier; // Tokens
                qi::rule<Iterator, Skipper> operand,        expression; // Rules
            };
        }
    
        template <typename Iterator, typename Skipper = detail::Skipper<Iterator> >
        struct facade {
            template <typename Range> static bool parse(Range const& input) {
                Iterator f = boost::begin(input), l = boost::end(input);
                bool ok = qi::phrase_parse(f, l, _parser, _skipper);
    
                if (f!=l)
                    std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    
                return ok;
            }
    
        private:
            static const detail::Skipper<Iterator>          _skipper;
            static const detail::Grammar<Iterator, Skipper> _parser;
        };
    
        template <class I, class S> const detail::Skipper<I>    facade<I,S>::_skipper = {};
        template <class I, class S> const detail::Grammar<I, S> facade<I,S>::_parser  = {};
    }
    
    int main() {
        using It = std::string::const_iterator;
        std::string const input = "(123)";
    
        bool ok = parsing::facade<It>::parse(input);
    
        if (ok)   std::cout << "Parse success\n";
        else      std::cout << "Parse failed\n";
    }
    
    #包括
    #包括
    名称空间qi=boost::spirit::qi;
    名称空间解析{
    名称空间详细信息{
    模板
    结构跳过程序:qi::grammar{
    Skipper():Skipper::基本类型(\u skip\u规则){
    _comment=boost::spirit::repository::confix(“/*”,“*/”[*(qi::char_-“*/”)//多行
    |boost::spirit::repository::confix(“//”,qi::eol)[*(qi::char\uqi::eol)]//单行
    ;
    _跳过规则=qi::ascii::空格| |注释;
    }
    私人:
    qi::规则_注释,_跳过_规则;
    };
    模板
    结构语法:qi::Grammar{
    语法():语法::基本类型(表达式){
    标量文字=qi::uint|qi::int;
    标识符=(qi::alpha |'')>>*(qi::alnum |'');
    //规则
    操作数=(标量文字标识符('('>>表达式>>));
    表达式=操作数;
    }
    私人:
    qi::规则标量_文字,标识符;//标记
    qi::规则操作数,表达式;//规则
    };
    }
    模板
    结构立面{
    模板静态布尔解析(范围常量和输入){
    迭代器f=boost::begin(输入),l=boost::end(输入);
    bool ok=qi::短语解析(f,l,_解析器,_跳过器);
    如果(f!=l)
    
    std::cout非常感谢!但还有一个问题:如果我尝试在构造函数主体之外初始化规则:
    Grammar():标量文字(qi::uint|qi::int|)、标识符((qi::alpha |'|')>*(qi::alnum |'|')、操作数((标量文字|标识符|('('>>表达式>>)))、表达式(操作数)、语法::基本类型(表达式)
    我收到一条警告,在base\u类型调用之后,表达式将被初始化。然后解析失败。因此,必须只在构造函数的主体内分配规则?或者是否有方法更改初始化顺序?与基无关:和。我认为真正的原因是分配和(复制)之间的差异初始化。虽然我没有动力去找出区别:)只需坚持常见的习惯用法。内部常量在任何方面都不是很有用。明白了。非常感谢,你的回答真的帮助了我。
    Parse success
    
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/repository/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    namespace parsing {
        namespace detail {
            template <typename Iterator>
            struct Skipper : qi::grammar<Iterator> {
                Skipper() : Skipper::base_type(_skip_rule) {
                    _comment  = boost::spirit::repository::confix("/*", "*/")    [*(qi::char_ - "*/")]     // Multi-line
                            | boost::spirit::repository::confix("//", qi::eol) [*(qi::char_ - qi::eol)]  // Single-line
                            ;
    
                    _skip_rule = qi::ascii::space | _comment;
                }
            private:
                qi::rule<Iterator> _comment, _skip_rule;
            };
    
            template <typename Iterator, typename Skipper = Skipper<Iterator> >
            struct Grammar : qi::grammar<Iterator, Skipper> {
                Grammar() : Grammar::base_type(expression) {
                    scalar_literal = qi::uint_ | qi::int_;
                    identifier     = (qi::alpha | '_') >> *(qi::alnum | '_');
                    // Rules
                    operand        = (scalar_literal | identifier | ('(' >> expression >> ')'));
                    expression     = operand;
                }
            private:
                qi::rule<Iterator>          scalar_literal, identifier; // Tokens
                qi::rule<Iterator, Skipper> operand,        expression; // Rules
            };
        }
    
        template <typename Iterator, typename Skipper = detail::Skipper<Iterator> >
        struct facade {
            template <typename Range> static bool parse(Range const& input) {
                Iterator f = boost::begin(input), l = boost::end(input);
                bool ok = qi::phrase_parse(f, l, _parser, _skipper);
    
                if (f!=l)
                    std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    
                return ok;
            }
    
        private:
            static const detail::Skipper<Iterator>          _skipper;
            static const detail::Grammar<Iterator, Skipper> _parser;
        };
    
        template <class I, class S> const detail::Skipper<I>    facade<I,S>::_skipper = {};
        template <class I, class S> const detail::Grammar<I, S> facade<I,S>::_parser  = {};
    }
    
    int main() {
        using It = std::string::const_iterator;
        std::string const input = "(123)";
    
        bool ok = parsing::facade<It>::parse(input);
    
        if (ok)   std::cout << "Parse success\n";
        else      std::cout << "Parse failed\n";
    }