Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.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 x3--使用其他解析器参数化解析器_C++_Parsing_Boost_Boost Spirit X3 - Fatal编程技术网

C++ Boost Spirit x3--使用其他解析器参数化解析器

C++ Boost Spirit x3--使用其他解析器参数化解析器,c++,parsing,boost,boost-spirit-x3,C++,Parsing,Boost,Boost Spirit X3,我没有太多的代码要显示,因为我还没有找到任何可以工作的东西,但高层次的问题是,我正在尝试为一系列相关语言创建一系列解析器。我的意思是,这两种语言将共享许多相同的结构,但不会完全重叠。作为一个简单的例子,假设我有一个AST,它由一些(在本例中完全是人为设计的)“叶”类型参数化: template <typename t> struct fooT { std::string name; t leaf; }; 模板 结构脚{ std::字符串名; t叶; }; 一种语言可以将t

我没有太多的代码要显示,因为我还没有找到任何可以工作的东西,但高层次的问题是,我正在尝试为一系列相关语言创建一系列解析器。我的意思是,这两种语言将共享许多相同的结构,但不会完全重叠。作为一个简单的例子,假设我有一个AST,它由一些(在本例中完全是人为设计的)“叶”类型参数化:

template <typename t>
struct fooT {
  std::string name;
  t leaf;
};
模板
结构脚{
std::字符串名;
t叶;
};
一种语言可以将
t
实例化为
int
,另一种语言可以实例化为
double
。我想做的是创建一个模板类或一些我可以用不同的
t
和相应的解析器规则实例化的东西,以便生成一系列组合的解析器

在我的真实示例中,我有一组嵌套结构,这些结构在不同的语言中是相同的,但在AST的边缘只有几个小的变化,因此如果我不能以良好的方式组合解析器,我将复制一组解析规则,AST节点,实际上,我没有把它放在一个类中,只是非常仔细地安排了我的头文件和导入,这样我就可以用特殊的名称来组装“悬空”解析器规则。这样做的一个大缺点是,我不能在同一个程序中包含多个不同语言的解析器——正是因为名称冲突


有人知道我如何处理这个问题吗?

X3的好处是,您可以像最初定义解析器一样轻松地生成解析器

例如

先进的
对于高级场景(在这些场景中,规则声明和定义在不同的分析单元之间分离,并且/或者需要动态切换),您可以使用
x3::any_rule
holder。

我确实将其在不同的翻译单元之间分离,因此我将研究任何_规则。这正是我需要的。我试图融入一个班级,但一切都很糟糕。非常感谢。再次感谢您的回答!我确实设法让我的解析器重构以使用这种风格。不幸的是,编译时间已经过了极限!现在编译解析器大约需要5分钟和10GB内存。这里有人知道有没有好办法解决这个问题吗?我的特定语言有一个很大的递归变体,其中几个组件使用上述模板功能。是的。通常的修复方法是重新引入BOOST_SPIRIT_DEFINE用法。如果没有,上下文类型似乎会被整个解析器表达式所阻塞。这可能会导致不同上下文类型的实例化激增,尤其是递归和/或跳过器更改。如果您以某种方式显示代码,或许我可以尝试将其作为~exocrism~练习。总有一天我要学会穿那根针。我可以试着给你编码。我不确定技术上是否允许我发布它,而且它也被分割成大量文件。我确实在其他帖子中看到了你的一些评论,并尽可能添加了BOOST_SPIRIT_DEFINE调用,但没有太大区别。问题是,对于所有的模板解析器,我不知道如何用BOOST\u-SPIRIT\u-define定义它们。我必须承认我不是一个非常先进的C++开发人员。
template <typename T> struct AstNode {
    std::string name;
    T leaf;
};
namespace Generic {
    template <typename T> auto leaf = x3::eps(false);

    template <> auto leaf<int>
        = "0x" >> x3::int_parser<uintmax_t, 16>{};
    template <> auto leaf<std::string>
        = x3::lexeme['"' >> *~x3::char_('"') >> '"'];

    auto no_comment = x3::space;
    auto hash_comments = x3::space |
        x3::lexeme['#' >> *(x3::char_ - x3::eol)] >> (x3::eol | x3::eoi);
    auto c_style_comments = x3::space |
        "/*" >> x3::lexeme[*(x3::char_ - "*/")] >> "*/";
    auto cxx_style_comments = c_style_comments |
        x3::lexeme["//" >> *(x3::char_ - x3::eol)] >> (x3::eol | x3::eoi);

    auto name = leaf<std::string>;

    template <typename T> auto parseNode(auto heading, auto skipper) {
        return x3::skip(skipper)[
            x3::as_parser(heading) >> name >> ":" >> leaf<T>
        ];
    }
}
namespace Language1 {
    static auto const grammar =
        Generic::parseNode<int>("value", Generic::no_comment);
}

namespace Language2 {
    static auto const grammar =
        Generic::parseNode<std::string>("line", Generic::cxx_style_comments);
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted.hpp>
#include <iomanip>
namespace x3 = boost::spirit::x3;

template <typename T> struct AstNode {
    std::string name;
    T leaf;
};

BOOST_FUSION_ADAPT_TPL_STRUCT((T), (AstNode)(T), name, leaf)

namespace Generic {
    template <typename T> auto leaf = x3::eps(false);

    template <> auto leaf<int>
        = "0x" >> x3::uint_parser<uintmax_t, 16>{};
    template <> auto leaf<std::string>
        = x3::lexeme['"' >> *~x3::char_('"') >> '"'];

    auto no_comment = x3::space;
    auto hash_comments = x3::space |
        x3::lexeme['#' >> *(x3::char_ - x3::eol)] >> (x3::eol | x3::eoi);
    auto c_style_comments = x3::space |
        "/*" >> x3::lexeme[*(x3::char_ - "*/")] >> "*/";
    auto cxx_style_comments = c_style_comments |
        x3::lexeme["//" >> *(x3::char_ - x3::eol)] >> (x3::eol | x3::eoi);

    auto name = leaf<std::string>;

    template <typename T> auto parseNode(auto heading, auto skipper) {
        return x3::skip(skipper)[
            x3::as_parser(heading) >> name >> ":" >> leaf<T>
        ];
    }
}

namespace Language1 {
    static auto const grammar =
        Generic::parseNode<int>("value", Generic::no_comment);
}

namespace Language2 {
    static auto const grammar =
        Generic::parseNode<std::string>("line", Generic::cxx_style_comments);
}

void test(auto const& grammar, std::string_view text, auto ast) {
    auto f = text.begin(), l = text.end();
    std::cout << "\nParsing: " << std::quoted(text, '\'') << "\n";
    if (parse(f, l, grammar, ast)) {
        std::cout << " -> {name:" << ast.name << ",value:" << ast.leaf << "}\n";
    } else {
        std::cout << " -- Failed " << std::quoted(text, '\'') << "\n";
    }
}

int main() {
    test(Language1::grammar, R"(value "one": 0x01)", AstNode<int>{});
    test(
        Language2::grammar,
        R"(line "Hamlet": "There is nothing either good or bad, but thinking makes it so.")",
        AstNode<std::string>{});

    test(
        Language2::grammar,
        R"(line // rejected: "Hamlet": "To be ..."
        "King Lear": /*hopefully less trite:*/"As flies to wanton boys are we to the gods")",
        AstNode<std::string>{});
}
Parsing: 'value "one": 0x01'
 -> {name:one,value:1}

Parsing: 'line "Hamlet": "There is nothing either good or bad, but thinking makes it so."'
 -> {name:Hamlet,value:There is nothing either good or bad, but thinking makes it so.}

Parsing: 'line // rejected: "Hamlet": "To be ..."
        "King Lear": /*hopefully less trite:*/"As flies to wanton boys are we to the gods"'
 -> {name:King Lear,value:As flies to wanton boys are we to the gods}