用正则表达式检测函数调用 [英] detecting function call with regex

查看:179
本文介绍了用正则表达式检测函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想确定我是否可以使用正则表达式检测函数调用.基本情况很简单:somefunction(1、2);

I want to find out whether I can detect function call using regex. The basic case is easy: somefunction(1, 2);

但是如果我有代码怎么办?

But what if I had code:

somefunction(someotherfunction(), someotherotherfunction());

somefunction(function () { return 1; }, function() {return 2;});

caller_function(somefunction(function () { return 1; }, function() {return 2;}))

在这种情况下,我需要匹配相同数量的左括号和右括号,以便可以找到对somefunction

In this case I need to match same number of opening braces and closing braces so that I can find end of call to somefunction

有可能吗?

谢谢.

推荐答案

您的问题具有误导性.这并不像您想的那么简单.

Your question is misleading. It's not as simple as you think.

首先,语法不规则.正则表达式不是正确的工具.

First, the grammar isn't regular. Regular expressions are not the right tool.

第二,您要求检测函数调用",但是示例显示了匿名函数定义,这是完全不同的球类游戏.

Second, you ask "detecting function call" but the samples show anonymous function definitions, a totally different ball game.

这是使用Boost Spirit的开始:

Here's a start using Boost Spirit:

start   = skip(space) [ fcall ];
fcall   = ident >> '(' >> -args >> ')';
args    = arg % ',';
arg     = fdef | fcall;
fdef    = lexeme["function"] >> '(' >> -formals >> ')' >> body;
formals = ident % ',';

identch = alpha | char_("_");
ident   = identch >> *(identch|digit);
body    = '{' >> *~char_('}') >> '}';

将哪个映射到AST上,如:

Which would map onto an AST like:

struct function_definition {
    std::vector<std::string> formal_arguments;
    std::string body;
};

struct function_call;

using argument = boost::variant<
    function_definition,
    boost::recursive_wrapper<function_call>
>;

struct function_call {
    std::string name;
    std::vector<argument> args;
};

演示

在Coliru上直播

// #define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/adapted/struct.hpp>

struct function_definition {
    std::vector<std::string> formal_arguments;
    std::string body;
};

struct function_call;

using argument = boost::variant<
    function_definition,
    boost::recursive_wrapper<function_call>
>;

struct function_call {
    std::string name;
    std::vector<argument> args;
};

BOOST_FUSION_ADAPT_STRUCT(function_call, name, args)
BOOST_FUSION_ADAPT_STRUCT(function_definition, formal_arguments, body)

namespace qi = boost::spirit::qi;

template <typename It>
struct Parser : qi::grammar<It, function_call()> {
    Parser() : Parser::base_type(start) {
        using namespace qi;

        start   = skip(space) [ fcall ];
        fcall   = ident >> '(' >> -args >> ')';
        args    = arg % ',';
        arg     = fdef | fcall;
        fdef    = lexeme["function"] >> '(' >> -formals >> ')' >> body;
        formals = ident % ',';

        identch = alpha | char_("_");
        ident   = identch >> *(identch|digit);
        body    = '{' >> *~char_('}') >> '}';

        BOOST_SPIRIT_DEBUG_NODES((start)(fcall)(args)(arg)(fdef)(formals)(ident)(body))
    }
  private:
    using Skipper = qi::space_type;
    qi::rule<It, function_call()> start;
    qi::rule<It, function_call(), Skipper> fcall;
    qi::rule<It, argument(), Skipper> arg;
    qi::rule<It, std::vector<argument>(), Skipper> args;
    qi::rule<It, function_definition(), Skipper> fdef;
    qi::rule<It, std::vector<std::string>(), Skipper> formals;

    qi::rule<It, char()> identch;
    qi::rule<It, std::string()> ident, body;
};

// for debug:
#include <experimental/iterator>
static inline std::ostream& operator<<(std::ostream& os, function_definition const& v) {
    os << "function(";
    std::copy(v.formal_arguments.begin(), v.formal_arguments.end(), std::experimental::make_ostream_joiner(os, ", "));
    return os << ") {" << v.body << "}";
}

static inline std::ostream& operator<<(std::ostream& os, function_call const& v) {
    os << v.name << "(";
    std::copy(v.args.begin(), v.args.end(), std::experimental::make_ostream_joiner(os, ", "));
    return os << ")";
}

int main() {
    std::string const input = "caller_function(somefunction(function () { return 1; }, function() {return 2;}))";
    using It = std::string::const_iterator;
    Parser<It> const p;

    It f = input.begin(), l = input.end();
    function_call parsed;
    bool ok = parse(f, l, p, parsed);
    if (ok) {
        std::cout << "Parsed ok: " << parsed << "\n";
    } else {
        std::cout << "Parse failed\n";
    }

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

打印

Parsed ok: caller_function(somefunction(function() { return 1; }, function() {return 2;}))

这篇关于用正则表达式检测函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆