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

问题描述 投票:4回答:1

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

下面是一个示例解析器(一种解析int的非常详细的方法)。问题是lex_int功能。如果令牌是qi::unused_type(没有词法分析器)并且第一个提供词法分析器,我想第二次重载。我想我必须使用一些模板或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_MYINTUSE_LEXER定义和未定义。目标是通过USE_AUTO_SELECT符号自动选择。

c++ boost-spirit boost-spirit-qi
1个回答
2
投票

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

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这样的解析器生成器,甚至手动我的解析器。

© www.soinside.com 2019 - 2024. All rights reserved.