C++ boost spirit 2.x:如何处理关键字和标识符?

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

你好

我过去一直在使用boost spirit classic,现在我尝试使用更新的版本boost spirit 2.x。有人能告诉我如何处理关键词吗?比如说,我想区分“foo”和“int”,其中“foo”是标识符,“int”只是一个关键字。我想保护我的语法不被错误的解析,比如说“intfoo”

好的,我有

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;