C++ 如何使boost::spirit解析器和lexer能够处理包含文件
这是一个不做任何事情的词法分析器&它返回读取的字符串。 我希望扩展它,以便能够处理类似C++的include语句。 我可以想象如何做到这一点——但我想知道是否有更简单或已经可用的方法。 如果必须这样做,我将实现自己的迭代器(传递给lexer)。这个迭代器将包含C++ 如何使boost::spirit解析器和lexer能够处理包含文件,c++,boost-spirit,C++,Boost Spirit,这是一个不做任何事情的词法分析器&它返回读取的字符串。 我希望扩展它,以便能够处理类似C++的include语句。 我可以想象如何做到这一点——但我想知道是否有更简单或已经可用的方法。 如果必须这样做,我将实现自己的迭代器(传递给lexer)。这个迭代器将包含 字符串的索引(可能使用-1表示end()迭代器) 指向此字符串的指针 lexer遇到某个include语句时会将文件插入当前位置的字符串中,覆盖include语句。 你会怎么做 下面是我的不做任何事情的词法分析器/解析器: #incl
- 字符串的索引(可能使用-1表示end()迭代器)
- 指向此字符串的指针
#include <boost/phoenix.hpp>
#include <boost/bind.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <algorithm>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
namespace lex = boost::spirit::lex;
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
template<typename Lexer>
class lexer:public lex::lexer<Lexer>
{ public:
typedef lex::token_def<char> char_token_type;
char_token_type m_sChar;
//lex::token_def<lex::omit> m_sInclude;
lexer(void)
: m_sChar(".")//,
//m_sInclude("^#include \"[^\"]*\"")
{ this->self += m_sChar;
}
};
template<typename Iterator>
class grammar : public qi::grammar<Iterator, std::string()>
{ public:
qi::rule<Iterator, std::string()> m_sStart;
template<typename Tokens>
explicit grammar(Tokens const& tokens)
: grammar::base_type(m_sStart)
{ m_sStart %= *tokens.m_sChar >> qi::eoi;
}
};
int main(int, char**)
{
typedef lex::lexertl::token<std::string::const_iterator, boost::mpl::vector<char> > token_type;
typedef lexer<lex::lexertl::actor_lexer<token_type> > expression_lexer_type;
typedef expression_lexer_type::iterator_type expression_lexer_iterator_type;
typedef grammar<expression_lexer_iterator_type> expression_grammar_type;
expression_lexer_type lexer;
expression_grammar_type grammar(lexer);
const std::string s_ac = "this is a test\n\
#include \"test.dat\"\n\
";
std::string s;
auto pBegin = std::begin(s_ac);
lex::tokenize_and_parse(pBegin, std::end(s_ac), lexer, grammar, s);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间lex=boost::spirit::lex;
名称空间qi=boost::spirit::qi;
名称空间phoenix=boost::phoenix;
模板
类lexer:public lex::lexer
{公众:
typedef lex::token_def char_token_type;
char_token_类型m_sChar;
//lex::token_def m_sInclude;
lexer(无效)
:m_sChar(“.”/,
//m#u sInclude(“^#include\”[^\“]*\”)
{this->self+=m_sChar;
}
};
模板
类语法:公共qi::语法
{公众:
qi::规则m_sStart;
模板
显式语法(令牌常量和令牌)
:语法::基本类型(m\u sStart)
{m_sStart%=*tokens.m_sChar>>qi::eoi;
}
};
int main(int,char**)
{
typedef lex::lexertl::token token_type;
typedef lexer表达式\u lexer\u类型;
typedef expression_lexer_type::迭代器_type expression_lexer_iterator_type;
typedef语法表达式\ u语法\ u类型;
表达式\ lexer \类型lexer;
表达式语法类型语法(lexer);
const std::string s_ac=“这是一个测试\n\
#包括\“test.dat\”\n\
";
std::字符串s;
auto pBegin=std::begin(s_ac);
lex::tokenize_和_parse(pBegin,std::end(s_ac),lexer,grammar,s);
}
首先,存在一个基于Spirit的预处理器:(另请参见)
其次,“将include文件的内容插入字符串值”既没有用处(用于词法分析),又效率极低:
- 这是无用的,因为include文件将形成一个标记(!?),这意味着您的解析器无法对包含的内容进行操作
- 它不是泛型的,因为嵌套包含不会以这种方式发生
- 即使目标只是将include文件逐字复制到一个等效的输出流中,但将内容完全复制到内存中,通过lexer将其复制到解析器中,然后将其流出来,这样做的效率也非常低。您只需以最小的分配将输入流虹吸到输出流中即可李>
- 单独关注点:不要将解析和解释混为一谈。所以,若要解析include指令,您将返回include语句的表示形式,然后可以将其传递给解释它的代码
- 关注点分离的一个特殊、更强的例子是将包含处理移动到预处理阶段。事实上,自定义迭代器类型可以做到这一点,但我会在其上构建lexer,因此lexer不必知道包含,而只需对源进行lexer,而不必知道确切的来源
- 下面的代码将include语句替换为“abcd”--这应该是文件的内容
#include <boost/phoenix.hpp>
#include <boost/bind.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/phoenix/object.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/mpl/index_of.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <algorithm>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <iterator>
namespace lex = boost::spirit::lex;
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
struct myIterator:std::iterator<std::random_access_iterator_tag, char>
{ std::string *m_p;
std::size_t m_iPos;
myIterator(void)
:m_p(nullptr),
m_iPos(~std::size_t(0))
{
}
myIterator(std::string &_r, const bool _bEnd = false)
:m_p(&_r),
m_iPos(_bEnd ? ~std::size_t(0) : 0)
{
}
myIterator(const myIterator &_r)
:m_p(_r.m_p),
m_iPos(_r.m_iPos)
{
}
myIterator &operator=(const myIterator &_r)
{ if (this != &_r)
{ m_p = _r.m_p;
m_iPos = _r.m_iPos;
}
return *this;
}
const char &operator*(void) const
{ return m_p->at(m_iPos);
}
bool operator==(const myIterator &_r) const
{ return m_p == _r.m_p && m_iPos == _r.m_iPos;
}
bool operator!=(const myIterator &_r) const
{ return m_p != _r.m_p || m_iPos != _r.m_iPos;
}
myIterator &operator++(void)
{ ++m_iPos;
if (m_iPos == m_p->size())
m_iPos = ~std::size_t(0);
return *this;
}
myIterator operator++(int)
{ const myIterator s(*this);
operator++();
return s;
}
};
struct include
{ auto operator()(myIterator &_rStart, myIterator &_rEnd) const
{ // erase what has been matched (the include statement)
_rStart.m_p->erase(_rStart.m_iPos, _rEnd.m_iPos - _rStart.m_iPos);
// and insert the contents of the file
_rStart.m_p->insert(_rStart.m_iPos, "abcd");
_rEnd = _rStart;
return lex::pass_flags::pass_ignore;
//lex::_pass = lex::pass_flags::pass_ignore
}
};
template<typename Lexer>
class lexer:public lex::lexer<Lexer>
{ public:
typedef lex::token_def<char> char_token_type;
char_token_type m_sChar;
lex::token_def<lex::omit> m_sInclude;
lexer(void)
: m_sChar("."),
m_sInclude("#include [\"][^\"]*[\"]")
{ this->self += m_sInclude[lex::_pass = boost::phoenix::bind(include(), lex::_start, lex::_end)]
| m_sChar;
}
};
template<typename Iterator>
class grammar : public qi::grammar<Iterator, std::string()>
{ public:
qi::rule<Iterator, std::string()> m_sStart;
template<typename Tokens>
explicit grammar(Tokens const& tokens)
: grammar::base_type(m_sStart)
{ m_sStart %= *tokens.m_sChar >> qi::eoi;
}
};
int main(int, char**)
{
typedef lex::lexertl::token<myIterator, boost::mpl::vector<char> > token_type;
typedef lexer<lex::lexertl::actor_lexer<token_type> > expression_lexer_type;
typedef expression_lexer_type::iterator_type expression_lexer_iterator_type;
typedef grammar<expression_lexer_iterator_type> expression_grammar_type;
expression_lexer_type lexer;
expression_grammar_type grammar(lexer);
std::string s_ac = "this is a test\n\
#include \"test.dat\"\n\
";
std::string s;
myIterator pBegin(s_ac);
lex::tokenize_and_parse(pBegin, myIterator(s_ac, true), lexer, grammar, s);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间lex=boost::spirit::lex;
名称空间qi=boost::spirit::qi;
名称空间phoenix=boost::phoenix;
结构myIterator:std::iterator
{std::string*m_p;
标准:首次公开募股的规模;
My迭代器(void)
:m_p(nullptr),
m_IPO(~std::size_t(0))
{
}
My迭代器(std::string&\u r,const bool\u bEnd=false)
:m_p(&u r),
m_IPO(_bEnd?~std::size_t(0):0)
{
}
myIterator(常量myIterator&\r)
:m_p(_r.m_p),
m_IPO(_r.m_IPO)
{
}
myIterator&运算符=(常量myIterator&\u r)
{如果(这个!=&\r)
{m_p=\u r.m_p;
m_IPO=_r.m_IPO;
}
归还*这个;
}
常量字符和运算符*(无效)常量
{返回m_p->at(m_IPO);
}
布尔运算符==(常量myIterator&_r)常量
{return m_p===u r.m_p&&m_ipo===u r.m_ipo;
}
布尔运算符!=(常量myIterator&_r)常量
{返回m|p!=|r.m|p | m|U IPO!=|r.m|U IPO;
}
My迭代器和运算符++(void)
{++m_IPO;
如果(m_IPO==m_p->size())
m_iPos=~std::size_t(0);
归还*这个;
}
myIterator运算符++(int)
{const myIterator s(*this);
运算符++();
返回s;
}
};
结构包括
{auto operator()(myIterator&\u rStart,myIterator&\u rEnd)常量
{//删除已匹配的内容(include语句)
_rStart.m\u p->erase(\u rStart.m\u iPos,\u rEnd.m\u iPos-\u rStart.m\u iPos);
//并插入文件的内容
_rStart.m_p->insert(rStart.m_ipo,“abcd”);
_rEnd=_rStart;
返回lex::pass\u flags::pass\u ignore;
//lex::_pass=lex::pass\u标志::pass\u忽略
}
};
模板
类lexer:public lex::lexer
{公众:
typedef lex::token_def char_token_type;
char_token_类型m_sChar;
lex::token_def m_sInclude;
lexer(无效)
:m_sChar(“.”),
m#u包括(“#include[\”][^\“]*[\”]”)
{this->self+=m_sInclude[lex::_pass=boost::phoenix::bind(include(),lex::_start,lex:_end)]
|穆沙尔;
}
};
模板
类语法:公共qi::语法
{公众:
qi::规则m_sStart;
模板