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

时间:2014-05-12 20:25:31

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

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

下面是一个示例解析器(一种解析int的非常详细的方法)。问题是lex_int功能。如果令牌是qi::unused_type(没有词法分析器)&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_MYINTUSE_LEXER已定义&amp;未定义。目标是通过USE_AUTO_SELECT符号自动选择。

1 个答案:

答案 0 :(得分:2)

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

  

提示1:使用Spirit,行内的颜色

事实是你无法按价值真正返回基于Proto的表达模板,因为他们沉浸在对临时工具的引用中。这些意味着超出包含它们的完整表达式的结尾(这是典型的表达模板:它们是表达式,但它们可以包含在构造模板表达式期间以临时形式存在的文字,直到parser::compile())。

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

昨天看起来有点:)

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

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

请注意,您可能也想利用这个机会禁用Skipper,因为使用qi::space_type解析器作为队长通常对词法分析器没有意义。

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

  

提示2:如果不是为了灵活性,为什么[我们]使用Spirit?

如果我真的需要将语法转换为并且需要最终性能,我会使用像ANTLR或CoCo / R这样的解析器生成器,甚至手动解析我的解析器。