如何使用boost::spirit像regex那样修改字符串?

如何使用boost::spirit像regex那样修改字符串?,boost,boost-spirit,Boost,Boost Spirit,我正在为我的程序编写一种特定于域的语言,用作脚本引擎。这将字符串作为输入,然后对其进行解析,但我需要对字符串进行一些预处理,以使其从DSL适应JavaScript。预处理主要包括将一些术语包装到函数中,并将对象名称放在函数前面。例如,我想做这样的事情: 采取一些特殊的字符串输入“~/1/2” 将其包装在函数中:“find(~/1/2”)” 然后将一个对象附加到它:“someObject.find(“~/1/2”)”(对象名称必须是一个变量) 我一直在为此使用正则表达式(现在我有两个问题…)。正则

我正在为我的程序编写一种特定于域的语言,用作脚本引擎。这将字符串作为输入,然后对其进行解析,但我需要对字符串进行一些预处理,以使其从DSL适应JavaScript。预处理主要包括将一些术语包装到函数中,并将对象名称放在函数前面。例如,我想做这样的事情:

采取一些特殊的字符串输入
“~/1/2”

将其包装在函数中:
“find(~/1/2”)”

然后将一个对象附加到它:
“someObject.find(“~/1/2”)”
(对象名称必须是一个变量)

我一直在为此使用正则表达式(现在我有两个问题…)。正则表达式变得越来越复杂和不可读,并且缺少很多特殊情况。因为我所做的是语法上的,所以我想我应该从正则表达式升级到一个合适的解析器(现在我有三个问题…)。经过大量的研究,我选择了Boost.Spirit。我一直在看文档,但它没有把我带向正确的方向。有人能建议我如何使用这个库以我正在寻找的方式操作字符串吗?考虑到我只是试图操作一个字符串,而对存储解析后的数据不感兴趣,我是否需要使用
karma
进行输出,或者在解析过程中可以使用
qi
x3
输出字符串


如果我在这里走错了路,请随时重新指引我。

这似乎太宽泛了,无法回答

您所做的是解析输入,并将其转换为其他内容。您没有做的是查找/替换(否则您可以使用正则表达式)

当然,您可以做正则表达式所做的事情,但我不确定它能为您带来什么:

template <typename It, typename Out>
Out preprocess(It f, It l, Out out) {
    namespace qi = boost::spirit::qi;
    using boost::spirit::repository::qi::seek;

    auto passthrough = [&out](boost::iterator_range<It> ignored, auto&&...) {
        for (auto ch : ignored) *out++ = ch;
    };
    auto transform = [&out](std::string const& literal, auto&&...) {
        for (auto ch : "someObject.find(\"~"s) *out++ = ch;
        for (auto ch : literal) *out++ = ch;
        for (auto ch : "\")"s) *out++ = ch;
    };

    auto pattern = qi::copy("\"~" >> (*~qi::char_('"')) >> '"');
    qi::rule<It> ignore = qi::raw[+(!pattern >> qi::char_)] [passthrough];
    qi::parse(f, l, -qi::as_string[pattern][transform] % ignore);
    return out;
}
但这是非常有限的,因为如果这些事情是评论或其他的一部分,它甚至不会做正确的事情

因此,您可能需要一个专门的库,知道如何解析javascript,并使用它进行转换,例如(谷歌搜索时的第一个点击之一):

for (std::string const input : {
    R"(function foo(a, b) { var path = "~/1/2"; })",
})
{
    std::cout << "Input: " << input << "\n";

    std::string result;
    preprocess(begin(input), end(input), back_inserter(result));

    std::cout << "Result: " << result << "\n";
}

std::cout << "\n -- Or directly transformed stdin to stdout:\n";
preprocess(
    boost::spirit::istream_iterator(std::cin >> std::noskipws), {},
    std::ostreambuf_iterator<char>(std::cout));
Input: function foo(a, b) { var path = "~/1/2"; }
Result: function foo(a, b) { var path = someObject.find("~/1/2"); }

 -- Or directly transformed stdin to stdout:
function bar(c, d) { var path = someObject.find("~/1/42"); }