c – 重载精神语法以使用词法分析器或qi解析器

我正在尝试编写一个精灵语法组件,它与词法分析器(当一个更大的项目的一部分)一起工作时,或者只是用qi :: parsers(例如int_)进行测试.

下面是一个示例解析器(一种解析int的非常详细的方法).问题是lex_int函数.如果令牌是qi :: unused_type(没有lexer)&amp ;;我想第二次重载.提供词法分析器的第一个.我想我必须使用一些模板或MPL技术,因为tok.integer_是qi :: unused_type的编译错误.

顺便说一句,即使定义了USE_LEXER,它现在也会丢弃核心.使用预处理器定义代码定义工作正常,但这似乎是上个世纪.

谢谢.

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

#define USE_MYINT
#define USE_LEXER

// my grammar replacing int_
template<typename Iterator, typename Skipper=qi::space_type>
struct my_int : qi::grammar<Iterator, int(), Skipper>
{
    qi::rule<Iterator, int(), Skipper> start;

    template<typename TokenDef>
    my_int(TokenDef &tok): my_int::base_type(start)
    {
        start %= lex_int(tok);
        BOOST_SPIRIT_DEBUG_NODE(start);
    }

    // overload for lexer
    template<typename TokenDef>
    decltype(start) lex_int(TokenDef &tok)
    {
        return tok.integer_;
    }

    // overload for no lexer
    // template<typename TokenDef>
    decltype(start) lex_int(qi::unused_type)
    {
        return qi::int_;
    }

};

完整(可编译)示例位于dual_grammar.cc该示例适用于USE_MYINT和USE_LEXER定义&未定义.目标是通过USE_AUTO_SELECT符号自动选择.

最佳答案 做有用的,不是花哨的.相信我,这会比你预期的更伤害你(包括在你的应用程序在生产中崩溃之前不会出现的可怕类错误).

Tip 1: With Spirit, colour within the lines

事实上,你不能真正按价值返回基于Proto的表达模板,因为它们沉浸在对临时工具的引用中.这些并不意味着超出包含它们的完整表达式的结束(这是典型的表达模板:它们是伪表达式,但它们可以包含在构造模板表达式时作为临时表现的文字,并且正确直到parser :: compile()).

出于这个原因,任何使用运行时工厂的尝试(如lex_int)都会导致痛苦.

它看起来有点昨天:)

为了缓解这些问题,你可以把所有的决定都转移到编译时间(我知道你试过了,但是你仍然按值传递规则,这不是静态的,因为Spirit V2不是在一切都可能是constexpr的时候写的.如果你看起来吃了Proto-0x,你会发现那是图书馆的未来.

所以,实际上你可以专门研究检测Iterator是一个令牌迭代器的特征上的语法.

请注意,您可能也希望借此机会禁用Skipper,因为使用qi :: space_type解析器作为跳过器通常对词法分析器没有意义.

老实说,我只是编写单独的解析器.或者更好的是,承诺一个.我倾向于使用Qi-only解析器,因为它可以带来更大的灵活性.

Tip 2: If not for flexibility, why [do we] use Spirit?

如果我真的需要将语法付诸实践并且需要最终的性能,我会使用像ANTLR或CoCo / R这样的解析器生成器,甚至手动翻译我的解析器.

点赞