【问题标题】:detecting function call with regex使用正则表达式检测函数调用
【发布时间】:2017-07-02 02:07:44
【问题描述】:

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

但是如果我有代码呢:

somefunction(someotherfunction(), someotherotherfunction());

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

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

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

有可能吗?

提前致谢。

【问题讨论】:

  • 你不能用正则表达式可靠地做到这一点。你需要做一些句法分析。至少算括号和大括号。

标签: regex boost


【解决方案1】:

您的问题具有误导性。没有你想的那么简单。

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

其次,您询问“检测函数调用”,但示例显示匿名函数定义,完全不同的球赛。

这是使用 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;}))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多