От вопросов, относящимся к интеграции lex
в qi
грамматики, за последние несколько дней , Кажется, вы определили несколько проблем интеграции. На этом этапе вы должны спросить себя, почему вы даже пытаетесь интегрировать лексер в грамматику ПЭГ. ПГГ-грамматики могут аккуратно захватывать токенизацию in situ, поэтому вы не получаете особого эффекта от введения lexer, особенно учитывая случай lex-> qi, когда введение lexer показало вам, что вам не только нужны хаки, чтобы делать то, что аккуратно в ци с точки зрения выражения вашей грамматики, но также и для обработки ошибок и обработки аннотаций. Поэтому я предлагаю удалить Лекса и придерживаться Ци.
Вот ваша грамматика с удаленным лексером. Аст находится в собственном файле.
#include "ast.hpp"
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/range/iterator_range.hpp>
#include <vector>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace px = boost::phoenix;
template <typename Iterator>
struct skipper : qi::grammar<Iterator>
{
skipper() : skipper::base_type(start)
{
using boost::spirit::ascii::char_;
start = ascii::space | qi::lit("//") >> *(ascii::char_ - qi::eol) >> qi::eol;
}
qi::rule<Iterator> start;
};
struct error_handler_
{
typedef void result_type;
template<typename First, typename Last, typename ErrorPos, typename What>
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_> error_handler;
template<typename Iterator>
struct annotation_state
{
typedef boost::iterator_range<Iterator> annotation_iterator;
typedef std::vector<annotation_iterator> annotation_iterators;
annotation_iterators annotations;
};
template<typename Iterator>
struct annotate_
{
typedef void result_type;
annotation_state<Iterator> & as;
annotate_(annotation_state<Iterator> & as) : as(as) {}
template<typename Val, typename First, typename Last>
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 <typename Iterator, typename Skipper>
struct grammar : qi::grammar<Iterator,namespace_descriptor(),Skipper>
{
grammar(annotation_state<Iterator> & 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<boost::uint32_t>();
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<fail>(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<Iterator> & annotation_state_;
px::function<annotate_<Iterator> > 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<char, int> atomic_type;
qi::symbols<char, int> 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<it> as;
skipper<it> skip;
grammar<it, skipper<it> > g(as);
bool r = qi::phrase_parse(beg,end,g,skip);
if(r)
;
else
{
std::cout << "parsing failed" << std::endl;
}
}
Я думаю, что вы можете назначить значение токена в семантических действиях Лекса, как и в Ци. (Не забудьте использовать модель actor_lexer <>, хотя и добавьте тип данных для «RBL_ *» в mpl :: vector <> возможных типов атрибутов токена) – sehe
hmm guess Я должен заразиться руками? : D –
Либо это или быть (очень) пациентом ...;) – sehe