创建带有转义序列处理功能的带引号的字符串的boost :: spirit :: x3解析器

low_on_chromosomes

我需要为自定义语言的带引号的字符串创建一个解析器,该解析器还将正确处理转义序列,其中包括允许在字符串中使用转义引号。这是我当前的字符串解析器:

x3::lexeme[quote > *(x3::char_ - quote) > quote]

其中quote只是的常量表达式'"'它不进行任何转义序列处理。我知道boost::spirit::classic::lex_escape_ch_p,但是我不知道如何在boost::spirit::x3工具中使用它(或一般而言)。我如何创建执行此操作的解析器?解析器将不得不承认大多数转义序列,如像常见的'\n''\t'和像六角,华侨城,和ANSI转义序列更复杂的东西。

我很抱歉,如果这篇文章有什么问题,这是我第一次在SO上发表文章。

编辑:

这是我最终实现解析器的方式:

x3::lexeme[quote > *(
    ("\\\"" >> &x3::char_) >> x3::attr(quote) | ~x3::char_(quote)
    ) > quote]
[handle_escape_sequences];

handle_escape_sequencesLambda在哪里

auto handle_escape_sequences = [&](auto&& context) -> void {
    std::string& str = x3::_val(context);

    uint32_t i{};

    static auto replace = [&](const char replacement) -> void {
        str[i++] = replacement;
    };

    if (!classic::parse(std::begin(str), std::end(str), *classic::lex_escape_ch_p[replace]).full)
        throw Error{ "invalid literal" }; // invalid escape sequence most likely

    str.resize(i);
};

它执行完整的ANSI转义序列解析,这意味着您可以使用它来进行各种精美的终端操作,例如使用它来设置文本颜色,光标位置等。

这是规则的完整定义,以及它所依赖的所有内容(我只是从代码中挑选了与之相关的所有内容,因此结果看起来像适当的意大利面条),以防万一有人需要它:

#include <boost\spirit\home\x3.hpp>
#include <boost\spirit\include\classic_utility.hpp>

using namespace boost::spirit;

#define RULE_DECLARATION(rule_name, attribute_type)                            \
inline namespace Tag { class rule_name ## _tag; }                              \
x3::rule<Tag::rule_name ## _tag, attribute_type, true> rule_name = #rule_name; \

#define SIMPLE_RULE_DEFINITION(rule_name, attribute_type, definition) \
RULE_DECLARATION(rule_name, attribute_type)                           \
auto rule_name ## _def = definition;                                  \
BOOST_SPIRIT_DEFINE(rule_name);

constexpr char quote = '"';


template <class Base, class>
struct Access_base_s : Base {
    using Base::Base, Base::operator=;
};

template <class Base, class Tag>
using Unique_alias_for = Access_base_s<Base, Tag>;


using String_literal = Unique_alias_for<std::string, class String_literal_tag>;

SIMPLE_RULE_DEFINITION(string_literal, String_literal,
    x3::lexeme[quote > *(
        ("\\\"" >> &x3::char_) >> x3::attr(quote) | ~x3::char_(quote)
        ) > quote]
    [handle_escape_sequences];
);
看到

我在这个网站上有很多这样的例子¹

让met从简化您的表达开始(~charset可能比效率更高charset - exceptions):

x3::lexeme['"' > *~x3::char_('"')) > '"']

现在,为了允许转义,我们可以对它们进行即席解码:

auto qstring = x3::lexeme['"' > *(
         "\\n" >> x3::attr('\n')
       | "\\b" >> x3::attr('\b')
       | "\\f" >> x3::attr('\f')
       | "\\t" >> x3::attr('\t')
       | "\\v" >> x3::attr('\v')
       | "\\0" >> x3::attr('\0')
       | "\\r" >> x3::attr('\r')
       | "\\n" >> x3::attr('\n')
       | "\\"  >> x3::char_("\"\\")
       | ~x3::char_('"')
   ) > '"'];

另外,您可以使用符号方法,包括或不包括斜杠:

x3::symbols<char> escapes;
escapes.add
    ( "\\n", '\n')
    ( "\\b", '\b')
    ( "\\f", '\f')
    ( "\\t", '\t')
    ( "\\v", '\v')
    ( "\\0", '\0')
    ( "\\r", '\r')
    ( "\\n", '\n')
    ( "\\\\", '\\')
    ( "\\\"", '"');

auto qstring = x3::lexeme['"' > *(escapes | ~x3::char_('"')) > '"'];

也可以在Coliru上观看

我认为我更喜欢手动分支,因为它们使您可以灵活地执行例如他/八进制转义符(\0尽管要注意冲突):

       | "\\" >> x3::int_parser<char, 8, 1, 3>()
       | "\\x" >> x3::int_parser<char, 16, 2, 2>()

这也可以正常工作:

生活在Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>

int main() {
    namespace x3 = boost::spirit::x3;

    auto qstring = x3::lexeme['"' > *(
             "\\n" >> x3::attr('\n')
           | "\\b" >> x3::attr('\b')
           | "\\f" >> x3::attr('\f')
           | "\\t" >> x3::attr('\t')
           | "\\v" >> x3::attr('\v')
           | "\\r" >> x3::attr('\r')
           | "\\n" >> x3::attr('\n')
           | "\\"  >> x3::char_("\"\\")
           | "\\" >> x3::int_parser<char, 8, 1, 3>()
           | "\\x" >> x3::int_parser<char, 16, 2, 2>()
           | ~x3::char_('"')
       ) > '"'];

    for (std::string const input : { R"("\ttest\x41\x42\x43 \x031\x032\x033 \"hello\"\r\n")" }) {
        std::string output;
        auto f = begin(input), l = end(input);
        if (x3::phrase_parse(f, l, qstring, x3::blank, output)) {
            std::cout << "[" << output << "]\n";
        } else {
            std::cout << "Failed\n";
        }
        if (f != l) {
            std::cout << "Remaining unparsed: " << std::quoted(std::string(f,l)) << "\n";
        }
    }
}

版画

[   testABC 123 "hello"
]

¹看看这些

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Boost Spirit X3跳过解析器实现?

来自分类Dev

Boost Spirit X3跳过解析器实现?

来自分类Dev

从Boost Spirit X3解析器返回的向量中的空字符串

来自分类Dev

如何从Boost Spirit X3 lexeme解析器中获取字符串?

来自分类Dev

从Boost Spirit X3解析器返回的向量中的空字符串

来自分类Dev

boost :: spirit :: x3中的通用解析器生成器

来自分类Dev

无法使用lambda参数编译boost :: spirit :: x3解析器

来自分类Dev

Boost Spirit X3:跳过无能为力的解析器

来自分类Dev

boost spirit X3解析器,可将偏移量转换为原始字符串

来自分类Dev

boost spirit X3解析器,可将偏移量转换为原始字符串

来自分类Dev

如何捕获由boost :: spirit :: x3解析器解析的值以在语义动作的主体内使用?

来自分类Dev

Boost Spirit x3解析器的属性类型为std :: vector <boost :: variant <char,char >>,而不是std :: string

来自分类Dev

Boost Spirit x3条件(三元)运算符解析器(后续问题)

来自分类Dev

Spirit X3解析器的启动状态?

来自分类Dev

Boost Spirit x3-惰性解析器

来自分类Dev

您如何实现带有Boost Spirit x3的自定义解析器对象,使其与船长配合得很好?

来自分类Dev

使用 Boost Spirit X3 解析变体图

来自分类Dev

了解Boost.spirit的字符串解析器

来自分类Dev

使用Boost Spirit x3将数字解析为字符串

来自分类Dev

使用Boost Spirit x3将数字解析为字符串

来自分类Dev

将Boost.Spirit.X3解析器拆分为几个TU

来自分类Dev

尝试解析带引号的字符串文字时,Boost :: Spirit无法编译

来自分类Dev

尝试解析带引号的字符串文字时,Boost :: Spirit无法编译

来自分类Dev

解析字符串列表,然后解析带有Spirit x3的字符串列表

来自分类Dev

使用Boost Spirit X3解析具有交替标记的Selector结构

来自分类Dev

使用Boost Spirit Qi解析器解析枚举

来自分类Dev

使用boost :: spirit :: x3从std :: string解析为boost :: string_view

来自分类Dev

使用boost :: spirit :: x3解析为vector <boost :: string_view>

来自分类Dev

使用boost :: spirit :: x3从std :: string解析为boost :: string_view

Related 相关文章

  1. 1

    Boost Spirit X3跳过解析器实现?

  2. 2

    Boost Spirit X3跳过解析器实现?

  3. 3

    从Boost Spirit X3解析器返回的向量中的空字符串

  4. 4

    如何从Boost Spirit X3 lexeme解析器中获取字符串?

  5. 5

    从Boost Spirit X3解析器返回的向量中的空字符串

  6. 6

    boost :: spirit :: x3中的通用解析器生成器

  7. 7

    无法使用lambda参数编译boost :: spirit :: x3解析器

  8. 8

    Boost Spirit X3:跳过无能为力的解析器

  9. 9

    boost spirit X3解析器,可将偏移量转换为原始字符串

  10. 10

    boost spirit X3解析器,可将偏移量转换为原始字符串

  11. 11

    如何捕获由boost :: spirit :: x3解析器解析的值以在语义动作的主体内使用?

  12. 12

    Boost Spirit x3解析器的属性类型为std :: vector <boost :: variant <char,char >>,而不是std :: string

  13. 13

    Boost Spirit x3条件(三元)运算符解析器(后续问题)

  14. 14

    Spirit X3解析器的启动状态?

  15. 15

    Boost Spirit x3-惰性解析器

  16. 16

    您如何实现带有Boost Spirit x3的自定义解析器对象,使其与船长配合得很好?

  17. 17

    使用 Boost Spirit X3 解析变体图

  18. 18

    了解Boost.spirit的字符串解析器

  19. 19

    使用Boost Spirit x3将数字解析为字符串

  20. 20

    使用Boost Spirit x3将数字解析为字符串

  21. 21

    将Boost.Spirit.X3解析器拆分为几个TU

  22. 22

    尝试解析带引号的字符串文字时,Boost :: Spirit无法编译

  23. 23

    尝试解析带引号的字符串文字时,Boost :: Spirit无法编译

  24. 24

    解析字符串列表,然后解析带有Spirit x3的字符串列表

  25. 25

    使用Boost Spirit X3解析具有交替标记的Selector结构

  26. 26

    使用Boost Spirit Qi解析器解析枚举

  27. 27

    使用boost :: spirit :: x3从std :: string解析为boost :: string_view

  28. 28

    使用boost :: spirit :: x3解析为vector <boost :: string_view>

  29. 29

    使用boost :: spirit :: x3从std :: string解析为boost :: string_view

热门标签

归档