正则表达式在boost中提取信息

时间:2014-12-25 10:42:46

标签: c++ regex parsing boost

我想使用正则表达式来表达以下表达式。

Execute stmtname
and
Execute stmtname using @a,@b;

我想提取stmtname和变量列表。 我尝试了以下内容。

^execute[\s\t]+(\w+)[\s\t]+(using[\s\t]*(.+))?

但只能解析第二个语句。 有人帮我解决这个问题。

1 个答案:

答案 0 :(得分:3)

我可能不会尝试用正则表达式“解析”语法。既然你已经在使用Boost,为什么不用Boost Spirit冒险进入解析器生成器国家?

std::string statement_name;
std::vector<std::string> parameters;

bool ok = qi::phrase_parse(
    first, last,
    qi::no_case[ 
        sr::distinct(qi::graph) ["execute"] 
        >> ident_ 
        >> -(sr::distinct(qi::graph) ["using"] >> 
                ('@' >> ident_) % ','
            )
        >> -qi::lit(';') >> qi::eoi
    ],
    qi::space,
    statement_name,
    parameters
);

大部分的复杂性只是因为我试图非常细致

  • 分隔标识符令牌(以便例如execute_only不会解析为execute _only),并且
  • 接受空白
  • 在最后接受可选的;(您的示例在这方面存在冲突)

测试程序打印:

-----------------------------------------
Parsing 'Execute no_parameter_statement'
Parse success
statement_name: no_parameter_statement
0 parameters:
-----------------------------------------
Parsing 'Execute stmtname using @a,@b;'
Parse success
statement_name: stmtname
2 parameters:
    @a
    @b

<强> Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_distinct.hpp>

namespace qi = boost::spirit::qi;
namespace sr = boost::spirit::repository::qi;

typedef std::string::const_iterator It;
qi::rule<It, std::string()> ident_ = sr::distinct(qi::char_("a-z0-9_")) [ qi::alpha >> *(qi::char_("a-z0-9_")) ];

int main() {
    for(std::string const input : {
            "Execute no_parameter_statement",
            "Execute stmtname using @a,@b;"
            })
    {
        std::cout << "-----------------------------------------\n";
        std::cout << "Parsing '" << input << "'\n";

        std::string statement_name;
        std::vector<std::string> parameters;

        auto f(input.begin()), l(input.end());
        bool ok = qi::phrase_parse(f,l,qi::no_case[ 
                sr::distinct(qi::graph) ["execute"] 
                >> ident_ 
                >> -(sr::distinct(qi::graph) ["using"] >> 
                        ('@' >> ident_) % ','
                    )
                >> -qi::lit(';') >> qi::eoi
            ],
            qi::space,
            statement_name,
            parameters
        );

        if (ok) {
            std::cout << "Parse success\n";

            std::cout << "statement_name: " << statement_name << "\n";
            std::cout << parameters.size() << " parameters:\n";
            for(auto const& p : parameters)
                std::cout << "\t@" << p << "\n";
        } else {
            std::cout << "Parse failed\n"; 
        }

        if (f!=l)
            std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
    }
}