boost-sprit-lex unifying multiple tokens into a single token in lex differentiated by the id

后端 未结 1 1922
悲哀的现实
悲哀的现实 2020-12-10 23:56

edit : I have ripped out the lexer as it does not cleanly integrate with Qi and just obfuscates grammars (see answer below).


My lexer looks as

1条回答
  •  温柔的废话
    2020-12-11 00:01

    From your questions relating to integrating lex into qi grammar, from the last few days. It seems you've identified multiple integration issues. At this point you should ask yourself why you are even trying to integrate a lexer into a PEG grammar. PEG grammars can neatly capture tokenization in situ, and so you don't really gain much from introducing lexer especially considering the lex->qi case where introducing a lexer has shown you that not only do you need hacks to do what is neat in qi in terms of expressing your grammar but also hacks for getting error handling and annotation working properly. Therefore I suggest removing Lex and sticking to Qi.

    Here is your grammar with the lexer removed. The ast is in a file of it's own.

    #include "ast.hpp"
    #define BOOST_SPIRIT_USE_PHOENIX_V3
    #include 
    #include 
    #include 
    #include 
    
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace px = boost::phoenix;
    
    template 
    struct skipper : qi::grammar
    {
        skipper() : skipper::base_type(start)
        {
            using boost::spirit::ascii::char_;
    
            start = ascii::space | qi::lit("//") >> *(ascii::char_ - qi::eol) >> qi::eol;
        }
    
        qi::rule start;
    };
    
    struct error_handler_
    {
        typedef void result_type;
        template
        void operator()(First f, Last l, ErrorPos e, What w) const
        {
            std::cout << "Expected : " << w << std::endl;
            std::cout << std::string(f,l) << std::endl;
            int i = std::distance(f,e);
            std::cout << std::string(i+1,' ') <<  "^---- here"  << std::endl;
        }
    };
    
    px::function error_handler;
    
    template
    struct annotation_state
    {
      typedef boost::iterator_range annotation_iterator;
      typedef std::vector annotation_iterators;
    
      annotation_iterators annotations;
    };
    
    template
    struct annotate_
    {
        typedef void result_type;
    
        annotation_state & as;
        annotate_(annotation_state & as) : as(as) {}
    
        template
        void operator()(Val v, First f, Last l) const
        {
          v.id = as.annotations.size();
          as.annotations.push_back(boost::make_iterator_range(f,l));
          std::cout << std::string(f,l) << std::endl;
        }
    };
    
    
    
    template 
    struct grammar : qi::grammar
    {
        grammar(annotation_state & as) 
            : grammar::base_type(namespace_descriptor_),
              annotation_state_(as),
              annotate(as)
    
        {
            using namespace qi;
    
            atomic_type.add
                ("int4", RBL_INT4)
                ("int8", RBL_INT8)
                ("string", RBL_STRING);
    
            event_entry_qualifier.add
                ("optional", ENTRY_OPTIONAL)
                ("required", ENTRY_REQUIRED)
                ("repeated", ENTRY_REPEATED);
    
            oid_ = ordinal  > ':' > identifier;
            ordinal = uint_parser();
            identifier = +(char_("a","z") | char_("A","Z") | char_('_'));
            type_descriptor_ = atomic_type_ | compound_type_;
            atomic_type_ = no_case[atomic_type] > attr("");
    
            compound_type_ = 
                no_case[lit("event")] 
                > attr(RBL_EVENT) 
                > '(' 
                > identifier  
                > ')';
    
            event_entry_ = 
                no_case[event_entry_qualifier] 
                > oid_ 
                > type_descriptor_ 
                > ';';
    
            event_descriptor_ = 
                no_case[lit("event")] 
                > oid_ 
                > '{' 
                > *(event_entry_) 
                > '}'; 
    
            namespace_descriptor_ = 
                no_case[lit("namespace")] 
                > identifier 
                > '{' 
                > * (event_descriptor_) 
                > '}'; 
    
            identifier.name("identifier");
            oid_.name("ordinal-identifier pair");
            ordinal.name("ordinal");
    
            on_error(namespace_descriptor_, ::error_handler(_1,_2,_3,_4));
            on_success(oid_, annotate(_val,_1,_3));
            on_success(type_descriptor_, annotate(_val,_1,_3));
            on_success(event_entry_, annotate(_val,_1,_3));
            on_success(event_descriptor_, annotate(_val,_1,_3));
        }
    
        annotation_state & annotation_state_;
        px::function > annotate;
    
        qi::rule< Iterator, oid()> oid_;
        qi::rule< Iterator, boost::uint32_t()> ordinal;
        qi::rule< Iterator, std::string()> identifier;
        qi::rule< Iterator, type_descriptor()> type_descriptor_;
        qi::rule< Iterator, type_descriptor()> atomic_type_;
        qi::rule< Iterator, type_descriptor()> compound_type_; 
    
        qi::rule< Iterator, event_entry(), Skipper> event_entry_;
        qi::rule< Iterator, event_descriptor(), Skipper> event_descriptor_;
        qi::rule< Iterator, namespace_descriptor(), Skipper> namespace_descriptor_;
    
        qi::symbols atomic_type;
        qi::symbols event_entry_qualifier;
    };
    
    int main()
    {
        std::string test = "namespace ns { event 1:sihan { OpTIONAL 1:hassan event(haSsan);} }";
        typedef std::string::iterator it;
    
        it beg = test.begin();
        it end = test.end();
    
        annotation_state as;
        skipper skip;
        grammar > g(as);
    
    
        bool r = qi::phrase_parse(beg,end,g,skip);
        if(r)
            ;
        else
        {
            std::cout << "parsing failed" << std::endl;
        }
    }
    

    0 讨论(0)
提交回复
热议问题