Parsing 如何正确解析boost-spirit中的保留词

Parsing 如何正确解析boost-spirit中的保留词,parsing,boost,boost-spirit,boost-spirit-qi,Parsing,Boost,Boost Spirit,Boost Spirit Qi,我试图解析一系列语法:。例如: in float foo 其中方向可以是in、out或in\U out。通过使用qi::symbols类将方向关键字转换为枚举,我成功地解析了正确的文本 然而,当我没有正确的文本时,问题就出现了。例如: int foo 符号表解析器将删除“int”类型的“in”部分,因此结果将为: direction: in type: t name: foo 并且没有检测到错误。解析in、out和in_out保留字并确保后跟非标识符字符以使前一个文本的“int”部分失败的

我试图解析一系列语法:。例如:

in float foo
其中方向可以是inoutin\U out。通过使用qi::symbols类将方向关键字转换为枚举,我成功地解析了正确的文本

然而,当我没有正确的文本时,问题就出现了。例如:

int foo
符号表解析器将删除“int”类型的“in”部分,因此结果将为:

direction: in
type: t
name: foo
并且没有检测到错误。解析in、out和in_out保留字并确保后跟非标识符字符以使前一个文本的“int”部分失败的最佳方法是什么


谢谢

您可以使用and谓词或not谓词解析器,具体取决于您想要表达的内容。谓词解析器只检查下一个符号,但不使用它们

也就是说,您希望之后出现空白(空格或选项卡):

rule = symbol_parser >> &qi::blank;
rule = symbol_parser >> !(qi::alnum | qi::lit("_"));
也就是说,您不希望在后面有字母、数字或下划线:

rule = symbol_parser >> &qi::blank;
rule = symbol_parser >> !(qi::alnum | qi::lit("_"));
除了Mike建议的“手动”方法外,您还可以

  • 使用方便的包装规则
  • 使用Spirit存储库中的
    distinct
    解析器目录
  • 1.使用方便的包装 我刚想起来,有一次我想出了一个又快又脏的帮手:

    static const qi::rule<It, qi::unused_type(const char*)> kw 
          = qi::lit(qi::_r1) >> !qi::alnum;
    
    你可以使它更方便

    template <std::size_t N>
    static auto kw(char const (&keyword)[N]) -> qi::rule<Iterator> {
        // qi::lit has problems with char arrays, use pointer instead.
        return qi::lit(+keyword) >> !qi::alnum;
    }
    
    2.使用Spirit存储库中的
    distinct
    指令 除了Mike建议的“手动”方法外,您还可以使用Spirit存储库中的
    distinct
    解析器指令:

    intmain()
    {
    采用单因素检验;
    使用名称空间boost::spirit;
    {
    使用名称空间boost::spirit::ascii;
    qi:规则r;
    r=distinct::关键字[“description”]>>-lit(“:”)>>distinct::关键字[“ident”];
    增压测试(测试(“描述识别”,r,空格));
    增压测试(测试(“描述:识别”,r,空格));
    增压测试(测试(“描述:识别”,r,空格));
    BOOST_测试(!TEST(“descriptionindent”,r,space));
    }
    返回boost::报告_错误();
    }
    
    +1而且有一些方法(在Spirit代码库中)可以实现自动化,谢谢您的回复!但我更愿意使用符号表将关键字映射到值(我将其存储为AST中的枚举)。这个方法需要我在每次检查时都编写动作语义?我可以用distinct::关键字包装符号表解析器吗?当然可以!你试过吗?而且,为了好玩,这里是
    kw()
    符号解析器的
    symbols
    方法:谢谢你的评论-我现在正忙于其他事情,但我会测试一下,然后再给你回复!
    int main()
    {
        using namespace spirit_test;
        using namespace boost::spirit;
    
        {
            using namespace boost::spirit::ascii;
    
            qi::rule<char const*, space_type> r;
            r = distinct::keyword["description"] >> -lit(':') >> distinct::keyword["ident"];
    
            BOOST_TEST(test("description ident", r, space));
            BOOST_TEST(test("description:ident", r, space));
            BOOST_TEST(test("description: ident", r, space));
            BOOST_TEST(!test("descriptionident", r, space));
        }
    
        return boost::report_errors();
    }