تعزيز روح الإصدار 2.x: كيفية التعامل مع الكلمات الرئيسية ومعرفات؟

StackOverflow https://stackoverflow.com/questions/1630709

  •  06-07-2019
  •  | 
  •  

سؤال

ويوم جيد.

ولقد تم استخدام دفعة روح الكلاسيكية في الماضي والآن أنا أحاول التمسك أحدث واحد، 2.X. دفعة روح يمكن أن يكون شخص ما لطفاء جدا للي نقطة في كيفية التعامل مع الكلمات الرئيسية؟ ويقول، أريد أن نميز بين "فو" و "الباحث" حيث "فو" هو معرف و "كثافة" هو مجرد الكلمة. أريد أن حماية بلدي قواعد اللغة من الاعراب غير صحيح، ويقول، "intfoo".

حسنا، لدي

struct my_keywords : boost::spirit::qi::symbols<char, std::string> {
                my_keywords() {
                    add
                    ("void")
                    ("string")
                    ("float")
                    ("int")
                    ("bool")
                    //TODO: add others
                    ;
                }
            } keywords_table_;

ووسيادة الرمز أعلن على النحو التالي:

boost::spirit::qi::rule<Iterator, std::string(),  ascii::space_type> ident;
ident = raw[lexeme[((alpha | char_('_')) >> *(alnum | char_('_'))) - keywords_table_]];

وو، مثلا، بعض الحكم:

boost::spirit::qi::rule<Iterator, ident_decl_node(),  ascii::space_type> ident_decl;
ident_decl = ("void" | "float" | "string" | "bool") >> ident;

وكيفية كتابتها بشكل صحيح، مشيرا إلى أن "الفراغ"، "تعويم"، وما هي الكلمات الرئيسية؟ يرجع الفضل في ذلك مسبقا.

هل كانت مفيدة؟

المحلول

وهممم مجرد اعلان القاعدة أن:

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

وإنفاق على exemple الخاصة بك ينبغي أن يكون لديك شيء من هذا القبيل في النهاية:

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

و// ...

class ident_decl_node
{
   //this will  enable fusion_adapt_struct to access your private members
   template < typename, int>
   friend struct boost::fusion::extension::struct_member;
   //new version of spirit use:
   //friend struct boost::fusion::extension::access::struct_member;

   int type;
   std::string ident;
};

BOOST_FUSION_ADAPT_STRUCT(
   ident_decl_node,
   (int, type)
   (std::string, ident)
)

و// ...

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

وأيضا أنا لا أعرف أي إصدار استخدام ولكن كنت واحد في دفعة 1.40، ويبدو أن هناك خلل عند استخدام المشغل٪ = تليها حجة واحدة فقط (ان محلل يتم تحليل هذه القاعدة بشكل صحيح). مثال:

ident_decl %= ident;

وقيام بذلك بدلا

ident_decl %= ident > eps;

والذي ينبغي أن يكون ما يعادلها.

والأمل ساعد هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top