C++ boost spirit 2.x:如何处理关键字和标识符?
你好 我过去一直在使用boost spirit classic,现在我尝试使用更新的版本boost spirit 2.x。有人能告诉我如何处理关键词吗?比如说,我想区分“foo”和“int”,其中“foo”是标识符,“int”只是一个关键字。我想保护我的语法不被错误的解析,比如说“intfoo” 好的,我有C++ boost spirit 2.x:如何处理关键字和标识符?,c++,boost-spirit,C++,Boost Spirit,你好 我过去一直在使用boost spirit classic,现在我尝试使用更新的版本boost spirit 2.x。有人能告诉我如何处理关键词吗?比如说,我想区分“foo”和“int”,其中“foo”是标识符,“int”只是一个关键字。我想保护我的语法不被错误的解析,比如说“intfoo” 好的,我有 struct my_keywords : boost::spirit::qi::symbols<char, std::string> { my_k
struct my_keywords : boost::spirit::qi::symbols<char, std::string> {
my_keywords() {
add
("void")
("string")
("float")
("int")
("bool")
//TODO: add others
;
}
} keywords_table_;
struct my_关键字:boost::spirit::qi::symbols{
我的_关键字(){
添加
(“无效”)
(“字符串”)
(“浮动”)
(“int”)
(“布尔”)
//TODO:添加其他
;
}
}关键词表;
而ident规则声明为:
boost::spirit::qi::rule<Iterator, std::string(), ascii::space_type> ident;
ident = raw[lexeme[((alpha | char_('_')) >> *(alnum | char_('_'))) - keywords_table_]];
boost::spirit::qi::规则标识;
ident=raw[lexeme[((alpha | char(uu'))>>*(alnum | char(uu'))-关键字(u table)];
比如说,一些规则:
boost::spirit::qi::rule<Iterator, ident_decl_node(), ascii::space_type> ident_decl;
ident_decl = ("void" | "float" | "string" | "bool") >> ident;
boost::spirit::qi::rule ident_decl;
ident|u decl=(“void”|“float”|“string”|“bool”)>>ident;
如何正确书写,说明“void”、“float”等是关键词?
提前谢谢。Hmmm请声明您的规则为:
//the > operator say that your keyword MUST be followed by an ident
//instead of just may (if I understood spirit right the >> operator will
//make the parser consider other rules if it fail which might or not be
//what you want.
ident_decl = keyword_table_ > ident;
在你的例子上,你应该在最后有这样的东西:
struct my_keywords : boost::spirit::qi::symbols<char, int> {
my_keywords() {
add
("void", TYPE_VOID)
("string", TYPE_STRING)
("float", TYPE_FLOAT)
("int", TYPE_INT)
("bool", TYPE_BOOL)
//TODO: add others
;
}
} keywords_table_;
改为这样做
ident_decl %= ident > eps;
这应该是等效的
希望这能有所帮助。您可以在Spirit邮件列表中询问:谢谢您的尝试,但它对我不起作用。我有很多错误,例如:错误:调用'boost::fusion::vector_data1'时没有匹配的函数。您能告诉我错误似乎发生在哪一行吗?您可能需要滚动大量文本,但最终应该找到代码中发生错误的行。当我有时间的时候,我可以试着用boost 1.39给你一个最小的可编译(这是一个未经测试的)例子。让我继续关注您的进度。真正的问题是:boost/fusion/container/vector/detail/vector|n.hpp | 68 |错误:调用“boost::fusion::vector|u data1::vector|u data1(int&)”时没有匹配的函数| boost/fusion/container/vector/detail/vector|n.hppwow!我已经解决了!您关于在规则末尾添加“>>eps”的说明是问题的原因!在任何情况下,规则为:start%=ident_decl;汇编得很好。很好,现在我有了一个玩具可编译语法。非常感谢。嗯,奇怪,eps不应该做任何事情。如果在使用操作符%=时没有>>eps,我在运行时会遇到问题。如果您的程序在运行时断言了一些关于侵入性的内容,请注意。但是你没有使用和我相同的版本,所以我不知道。为解决你的问题干杯,瓦尼!
struct MyErrorHandler
{
template <typename, typename, typename, typename>
struct result { typedef void type; };
template <typename Iterator>
void operator()(Iterator first, Iterator last, Iterator error_pos, std::string const& what) const
{
using boost::phoenix::construct;
std::string error_msg = "Error! Expecting ";
error_msg += what; // what failed?
error_msg += " here: \"";
error_msg += std::string(error_pos, last); // iterators to error-pos, end
error_msg += "\"";
//put a breakpoint here if you don't have std::cout for the console or change
//this line for something else.
std::cout << error_msg;
}
};
using boost::spirit::qi::grammar;
using boost::spirit::ascii::space_type;
typedef std::vector<boost::variant<ident_decl_node, some_other_node> ScriptNodes;
template <typename Iterator>
struct NodeGrammar: public grammar<Iterator, ScriptNodes(), space_type>
{
using boost::spirit::arg_names; //edit1
NodeGrammar: NodeGrammar::base_type(start)
{
//I had problem if I didn't add the eps rule (which do nothing) so you might
//want to leave it
start %= ident_decl | some_other_node_decl >> eps;
ident_decl %= keyword_table > ident;
//I'm not sure if the %= operator will work correctly on this, you might have to do
//the push_back manually but I think it should work
ident %= raw[lexeme[((alpha | char_('_')) >> *(alnum | char_('_'))) - keywords_table_]];
on_error<fail>(start, error_handler(_1, _2, _3, _4)); //edit1
}
my_keywords keyword_table_;
boost::spirit::qi::rule<Iterator, ScriptNodes(), ascii::space_type> start;
boost::spirit::qi::rule<Iterator, ident_decl_node(), ascii::space_type> ident_decl;
boost::spirit::qi::rule<Iterator, some_other_node(), ascii::space_type> ident_decl;
boost::spirit::qi::rule<Iterator, std::string(), ascii::space_type> ident;
boost::phoenix::function<MyErrorHandler> error_handler; //edit1
};
ident_decl %= ident;
ident_decl %= ident > eps;