Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将Boost Spirit Lex语义动作转换为Phoenix-如何访问_val?_C++_Boost_Boost Spirit_Boost Phoenix_Boost Spirit Lex - Fatal编程技术网

C++ 将Boost Spirit Lex语义动作转换为Phoenix-如何访问_val?

C++ 将Boost Spirit Lex语义动作转换为Phoenix-如何访问_val?,c++,boost,boost-spirit,boost-phoenix,boost-spirit-lex,C++,Boost,Boost Spirit,Boost Phoenix,Boost Spirit Lex,我为我的Boost Spirit Lexer编写了一个语义动作,将字符串中的转义序列转换为它们所代表的内容。它工作得非常完美,我想将其转换为Boost Phoenix表达式,但无法编译该表达式 以下是有效的方法: // the semantic action struct ConvertEscapes { template <typename ItT, typename IdT, typename CtxT> void operator () (ItT& st

我为我的Boost Spirit Lexer编写了一个语义动作,将字符串中的转义序列转换为它们所代表的内容。它工作得非常完美,我想将其转换为Boost Phoenix表达式,但无法编译该表达式

以下是有效的方法:

// the semantic action
struct ConvertEscapes
{
    template <typename ItT, typename IdT, typename CtxT>
    void operator () (ItT& start, ItT& end, lex::pass_flags& matched, IdT& id, CtxT& ctx)
    {
        static boost::wregex escapeRgx(L"(\\\\r)|(\\\\n)|(\\\\t)|(\\\\\\\\)|(\\\\\")");
        static std::wstring escapeRepl = L"(?1\r)(?2\n)(?3\t)(?4\\\\)(?5\")";
        static std::wstring wval; // static b/c set_value doesn't seem to copy

        auto const& val = ctx.get_value();
        wval.assign(val.begin(), val.end());
        wval = boost::regex_replace(wval, 
                                    escapeRgx, 
                                    escapeRepl, 
                                    boost::match_default | boost::format_all);
        ctx.set_value(wval);
    }
};

// the token declaration
lex::token_def<std::wstring, wchar_t> literal_str;

// the token definition
literal_str  = L"\\\"([^\\\\\"]|(\\\\.))*\\\""; // string with escapes

// adding it to the lexer
this->self += literal_str [ ConvertEscapes() ];
无法从
\u val
构造
wstring
<代码>\u val也没有
begin()
end()
,应该如何使用它

这个
std::wstring(lex::_start,lex::_end)
也会失败,因为这些参数无法识别为迭代器

在中,我找到了
phoenix::construct(lex::\u start,lex::\u end)
,但这也不会真正产生
wstring


如何为当前令牌获取一个字符串或一对
wchar\u t
迭代器?

我将高呼常听的“为什么”

这一次,有充分的理由

通常,避免语义操作:

菲尼克斯的演员不必要地比专门的函子更复杂。它们有一个优点(主要是简单的赋值或内置操作)。但是,如果参与者是任何一种非平凡的人,那么您将看到复杂性迅速上升,不仅对人类如此,对编译器也是如此。这导致了

  • 慢编译
  • 次优发射码
  • 更难维护源代码
  • 新的错误类别(例如,当表达式模板包含对局部变量/临时变量的引用时,一些增强Proto(因此Phoenix)的东西不会阻止或发出信号。事实上,它通过假设所有模板表达式都是短暂的来鼓励它,但我离题了)
有趣的是:精神X3完全抛弃了凤凰,尽管凤凰曾经是精神X3的大脑之子

新样式使用了c++14多态lambda,它看起来90%像原始代码中的helper函数对象,但内联为lambda

本案 不行。一点也不

问题在于,您将延迟/延迟的参与者与直接调用混合在一起。那是行不通的。
phoenix::construct(lex::_start,lex::_end)
的类型不应该是
std::wstring
。当然它应该是一个懒惰的参与者,可以在以后的某个时候用来创建
std::wstring

既然我们知道(以及为什么)
phoenix::construct(lex::_start,lex::_end)
是一种演员类型,那么就应该清楚为什么在它上面调用
boost::regex\u replace
是完全虚假的。你不妨说

struct implementation_defined {} bogus;
boost::regex_replace(bogus, re, fmt, boost::match_default | boost::format_all);
想知道为什么它不能编译

总结: 你应该有专门的函子。当然,Phoenix可以调整所需的正则表达式函数,但它所做的只是将复杂度税转移到一些语法糖上

我总是选择一个更天真的方法,这对于一个经验丰富的C++程序员来说是更容易理解的,并且避免了用高线行为产生的陷阱。

然而,如果你好奇,这里有一个指针:

#include <iostream>
#include <boost/regex.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/lex_lexer.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/lex.hpp>

namespace lex = boost::spirit::lex;

BOOST_PHOENIX_ADAPT_FUNCTION(std::wstring, regex_replace_, boost::regex_replace, 4)

template <typename... T>
struct Lexer : lex::lexer<T...> {
    Lexer() {
        // the token definition
        literal_str  = L"\\\"([^\\\\\"]|(\\\\.))*\\\""; // string with escapes

        // adding it to the lexer
        this->self += literal_str [
            lex::_val = regex_replace_(lex::_val,
                 boost::wregex(L"(\\\\r)|(\\\\n)|(\\\\t)|(\\\\\\\\)|(\\\\\")"), 
                 L"(?1\r)(?2\n)(?3\t)(?4\\\\)(?5\")", 
                 boost::match_default | boost::format_all) 

        ];
    }

    // the token declaration
    lex::token_def<std::wstring, wchar_t> literal_str;
};

int main() {
    typedef lex::lexertl::token<std::wstring::const_iterator, boost::mpl::vector<std::wstring, wchar_t>> token_type;
    typedef Lexer<lex::lexertl::actor_lexer<token_type>> lexer_type;
    typedef lexer_type::iterator_type lexer_iterator_type;
}
#包括
#包括
#包括
#包括
#包括
#包括
名称空间lex=boost::spirit::lex;
BOOST_PHOENIX_ADAPT_函数(std::wstring,regex_replace,BOOST::regex_replace,4)
模板
结构Lexer:lex::Lexer{
Lexer(){
//令牌定义
literal\u str=L“\\\\”([^\\\\\”](\\\\)*\\“”//带转义符的字符串
//将其添加到lexer
这个->自我+=文字[
lex::_val=regex\u replace,
boost::wregex(L)(\\\\r)(\\\\n)(\\\\t)(\\\\\t)(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\,
L“(?1\r)(?2\n)(?3\t)(?4\\\\)(?5\””,
boost::match_default | boost::format_all)
];
}
//令牌声明
lex::token_def literal_str;
};
int main(){
typedef lex::lexertl::token token_type;
typedef Lexer lexeru类型;
typedef lexer_type::iterator_type lexer_iterator_type;
}

imk_考虑可在以后调用的组合函数对象

²如果您将其设计为EDSL供非专家进一步配置,则平衡可能会出现问题,但您将承担额外的责任,记录您的EDSL及其可使用的约束条件


我们应该说,大脑的灵魂之子吗?

为什么……我读了“”(谢谢你的澄清。)我计划继续使用functor,因为其中的正则表达式是静态的,但我想学习。感谢你提供了这么多的细节,我从你那里读到了很多关于Spirit的有用答案,这是另一个。干杯。我想这两个建议都是正确的。尽可能使用Phoenix,我通常会说在做任何事情之前三思而后行矿石:)
#include <iostream>
#include <boost/regex.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/lex_lexer.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/lex.hpp>

namespace lex = boost::spirit::lex;

BOOST_PHOENIX_ADAPT_FUNCTION(std::wstring, regex_replace_, boost::regex_replace, 4)

template <typename... T>
struct Lexer : lex::lexer<T...> {
    Lexer() {
        // the token definition
        literal_str  = L"\\\"([^\\\\\"]|(\\\\.))*\\\""; // string with escapes

        // adding it to the lexer
        this->self += literal_str [
            lex::_val = regex_replace_(lex::_val,
                 boost::wregex(L"(\\\\r)|(\\\\n)|(\\\\t)|(\\\\\\\\)|(\\\\\")"), 
                 L"(?1\r)(?2\n)(?3\t)(?4\\\\)(?5\")", 
                 boost::match_default | boost::format_all) 

        ];
    }

    // the token declaration
    lex::token_def<std::wstring, wchar_t> literal_str;
};

int main() {
    typedef lex::lexertl::token<std::wstring::const_iterator, boost::mpl::vector<std::wstring, wchar_t>> token_type;
    typedef Lexer<lex::lexertl::actor_lexer<token_type>> lexer_type;
    typedef lexer_type::iterator_type lexer_iterator_type;
}