Frage

guter Tag.

Ich habe in der Vergangenheit Auftrieb Geist klassisch benutze und jetzt versuche ich auf die neuere Version, auftrieb Geist 2.x. Stick könnte jemand so freundlich sein, mich in zeigen, wie man mit Keywords umgehen? zwischen „foo“ und „int“ unterscheiden, wo „foo“ Bezeichner und „int“ ist sagen wir, ich will, ist nur ein Stichwort. Ich mag meine Grammatik von falscher Analyse, sagen: „intfoo“.

schützen

in Ordnung, ich habe

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

und die ident Regel deklariert als:

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

und, sagen wir, eine Regel:

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

, wie es richtig zu schreiben, die besagt, dass „Leere“, „float“, etc sind Schlüsselwörter? Vielen Dank im Voraus.

War es hilfreich?

Lösung

Hmmm erklären nur die Regel zu sein:

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

Aufwendet auf Ihrem exemple sollten Sie so etwas wie dies am Ende haben:

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

Auch weiß ich nicht, welche Version Sie verwenden, aber ich verwendet, um die man im Boost 1,40 und es scheint, dass es ein Fehler ist wenn Operator% mit = gefolgt von nur ein Argument (der Parser würde analysieren nicht korrekt diese Regel). Ex:

ident_decl %= ident;

Sie hierzu stattdessen

ident_decl %= ident > eps;

, die gleichwertig sein sollte.

Hoffe, dass dies geholfen hat.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top