用正则表达式检测函数调用

时间:2017-07-02 02:07:45

标签: regex boost

我想知道是否可以使用正则表达式检测函数调用。基本情况很简单:有些功能(1,2);

但如果我有代码怎么办?

somefunction(someotherfunction(), someotherotherfunction());

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

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

在这种情况下,我需要匹配相同数量的开口括号和结束括号,以便我可以找到somefunction

的结束通话

有可能吗?

提前致谢。

1 个答案:

答案 0 :(得分:0)

您的问题具有误导性。它并不像你想象的那么简单。

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

其次,你问"检测功能调用"但是样本显示了匿名函数定义,这是一个完全不同的球类游戏。

这里是使用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上:

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;
};

样本

<强> Live On 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;}))