PEG 规则识别函数原型
PEG rule to identify function protoype
我正在尝试创建一个可以解析 C 代码的解析器。我的用例是解析可能包含函数原型的缓冲区。我想把这个函数名压入一个符号table。我是 Spirit 和 PEG 的新手,我正在尝试弄清楚如何编写可以识别函数原型的规则。
这是我当前的实现:
auto nameRule = x3::alpha >> *x3::alnum;
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = fcnPrototypeRule >> space >> x3::char_('(') >> -(nameRule % ',') >> x3::char_(');');
这是我的申请代码:
class Parser {
public:
std::string functionParser(const std::string& input) {
std::string output;
x3::phrase_parse(input.begin(), input.end(), fcnRule, space, output);
return output;
}
};
输入为="extern void myFunction();"
输出是一个空字符串。我想得到函数原型。
看起来 ');'
应该是 ");"?
此外,由于您有一个船长(x3::space
在对 phrase_parse
的调用中),因此没有多大意义:
- 还要在您的解析器表达式中指定
space
(它永远不会匹配)
- 不要将
nameRule
包装在 lexeme
或 noskip
指令中。另见 Boost spirit skipper issues
所以首先努力让它发挥作用:
std::string functionParser(const std::string& input) {
namespace x3 = boost::spirit::x3;
auto nameRule = x3::lexeme [x3::alpha >> *x3::alnum];
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = fcnPrototypeRule >> x3::char_('(') >> -(nameRule % ',') >> x3::char_(");");
std::string output;
x3::phrase_parse(input.begin(), input.end(), fcnRule, x3::space, output);
return output;
}
但是,您会注意到它 returns ndn()
(Live On Coliru).
我觉得主要是你的AS(std::string
)语法不太匹配造成的。我会说它看起来像你的意思是 "match" 而不是 "parse" 我会使用 x3::raw
来公开原始匹配:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>
std::string functionParser(const std::string& input) {
namespace x3 = boost::spirit::x3;
auto nameRule = x3::lexeme [x3::alpha >> *x3::alnum];
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = x3::raw[ fcnPrototypeRule >> '(' >> -(nameRule % ',') >> ')' >> ';' ];
std::string output;
x3::phrase_parse(input.begin(), input.end(), fcnRule, x3::space, output);
return output;
}
int main() {
for (auto s : {
"extern void myFunction();",
})
{
std::cout << std::quoted(s) << " -> " << std::quoted(functionParser(s)) << "\n";
}
}
我正在尝试创建一个可以解析 C 代码的解析器。我的用例是解析可能包含函数原型的缓冲区。我想把这个函数名压入一个符号table。我是 Spirit 和 PEG 的新手,我正在尝试弄清楚如何编写可以识别函数原型的规则。
这是我当前的实现:
auto nameRule = x3::alpha >> *x3::alnum;
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = fcnPrototypeRule >> space >> x3::char_('(') >> -(nameRule % ',') >> x3::char_(');');
这是我的申请代码:
class Parser {
public:
std::string functionParser(const std::string& input) {
std::string output;
x3::phrase_parse(input.begin(), input.end(), fcnRule, space, output);
return output;
}
};
输入为="extern void myFunction();" 输出是一个空字符串。我想得到函数原型。
看起来 ');'
应该是 ");"?
此外,由于您有一个船长(x3::space
在对 phrase_parse
的调用中),因此没有多大意义:
- 还要在您的解析器表达式中指定
space
(它永远不会匹配) - 不要将
nameRule
包装在lexeme
或noskip
指令中。另见 Boost spirit skipper issues
所以首先努力让它发挥作用:
std::string functionParser(const std::string& input) {
namespace x3 = boost::spirit::x3;
auto nameRule = x3::lexeme [x3::alpha >> *x3::alnum];
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = fcnPrototypeRule >> x3::char_('(') >> -(nameRule % ',') >> x3::char_(");");
std::string output;
x3::phrase_parse(input.begin(), input.end(), fcnRule, x3::space, output);
return output;
}
但是,您会注意到它 returns ndn()
(Live On Coliru).
我觉得主要是你的AS(std::string
)语法不太匹配造成的。我会说它看起来像你的意思是 "match" 而不是 "parse" 我会使用 x3::raw
来公开原始匹配:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>
std::string functionParser(const std::string& input) {
namespace x3 = boost::spirit::x3;
auto nameRule = x3::lexeme [x3::alpha >> *x3::alnum];
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = x3::raw[ fcnPrototypeRule >> '(' >> -(nameRule % ',') >> ')' >> ';' ];
std::string output;
x3::phrase_parse(input.begin(), input.end(), fcnRule, x3::space, output);
return output;
}
int main() {
for (auto s : {
"extern void myFunction();",
})
{
std::cout << std::quoted(s) << " -> " << std::quoted(functionParser(s)) << "\n";
}
}