从你最近几天关于融入语法的问题lex
开始。qi
您似乎发现了多个集成问题。在这一点上,您应该问自己为什么要尝试将词法分析器集成到 PEG 语法中。PEG 语法可以巧妙地原位捕获标记化,因此您不会从引入词法分析器中获得太多收益,特别是考虑到 lex->qi 案例,其中引入词法分析器向您表明,您不仅需要 hack 来完成 qi 中的整洁操作在表达你的语法方面,还有让错误处理和注释正常工作的技巧。因此,我建议移除 Lex 并坚持使用 Qi。
这是删除词法分析器的语法。ast 在它自己的文件中。
#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;
}
}