本文介绍了抽象语法树的迭代更新与提升精神的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个工作提升精神解析器和在想是否有可能做一个抽象语法树的迭代更新与提升精神?
我有一个结构类似:
结构AST; TYPEDEF提振::变体LT;提高:: recursive_wrapper< AST> >节点; 结构AST
{
的std ::矢量<&INT GT;值;
的std ::矢量<节点>儿童;
};
这是由使用的解析:
BOOL R = phrase_parse(开始,结束,语法,空间,AST);
有可能做的抽象语法树的迭代更新与提升精神?我还没有发现任何这文件,但我想,如果解析器语义动作可以在一个已经存在的AST的push_back。有没有人试过这种?
这将允许解析如下:
BOOL R = phrase_parse(开始,结束,语法,空间,AST); //初步分析//第二解析将给予一定的事件/定时器/ IO /东西后状态调用BOOL R = phrase_parse(开始,结束,语法,空间,AST); //额外的解析,这将更新现有的AST
解决方案
您如何知道哪些节点要合并?或者,你总是在根级别增加(移植)?在这种情况下,你为什么不只是另一种分析和合并的元素移动到现有的AST?
AST&安培;运算符+ =(AST&安培;&安培;其他){
的std ::移动(other.value.begin(),other.value.end(),back_inserter(值));
的std ::移动(other.children.begin(),other.children.end(),back_inserter(儿童));
返回*这一点;
}
演示时间
让我们来设计我可以为这个AST想到的最简单的语法:
开始='{'>> - (int_%',')GT;> ';' >> - (起始%',')GT;> };
的注意我甚至没有让;
可选。好吧。样品。练习的读者。 ☡你知道演练的
我们实现了平凡函数 AST解析(这楼它升)
,然后我们可以简单地合并的AST:
INT的main(){
AST合并;
对于(标准::字符串常量和放大器;输入:{
{1,2,3; {4; {9,8;}},{5,6;}},
{10,20,30; {40 {90,80;}},{50,60;}},
})
{
合并+ =解析(input.begin(),input.end());
性病::法院LT&;< 合并+<<输入<< - >中与所述;&下;合并<< \\ n;
}
}
骨节病>
//#定义BOOST_SPIRIT_DEBUG
#包括LT&;升压/融合/调整/ struct.hpp>
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ karma.hpp>命名空间补气=的boost ::精神::补气;
命名空间因缘=的boost ::精神::人缘;结构AST;// typedef的提振:: make_recursive_variant<提高:: recursive_wrapper< AST> > ::类型的节点;
TYPEDEF提振::变体LT;提高:: recursive_wrapper< AST> >节点;结构AST {
的std ::矢量<&INT GT;值;
的std ::矢量<节点>儿童; 邮票;运算符+ =(AST&安培;&安培;其他){
的std ::移动(other.value.begin(),other.value.end(),back_inserter(值));
的std ::移动(other.children.begin(),other.children.end(),back_inserter(儿童));
返回*这一点;
}
};BOOST_FUSION_ADAPT_STRUCT(AST,
(性病::矢量<&INT GT;,值)
(性病::矢量<节点>,子女)
)模板< TYPENAME它,类型名船长=补气::空间类型>
语法结构:补气::语法<它,AST(),船长>
{
语法():语法:: base_type(开始){
使用命名空间补气;
启动='{'>> - (int_%',')GT;> ';' >> - (起始%',')GT;> };
BOOST_SPIRIT_DEBUG_NODES((开始));
}
私人的:
齐::规则<它,AST(),船长>开始;
};//输出:
静态内联的std :: ostream的&放大器;运营商所述;≤(性病:: ostream的&放大器;操作系统,AST常量&放大器; 5){
使用命名空间因缘;
治<的boost ::精神:: ostream_iterator,AST()> - [R;
R ='{'<< - (int_%',')所述;&下; ';' << - ((R | EPS)%',')所述;&下; };
返回OS<<格式(R,ⅴ);
}模板< TYPENAME它> AST解析(这楼它升)
{
AST解析; 静态语法<它> G;
布尔OK =齐:: phrase_parse(F,L,G,补气::空间分析); 如果(OK!||(F!= 1)){
性病::法院LT&;< 解析失败\\ n;
性病::法院LT&;< 剩余未解析:'<<标准::字符串(F,L)LT;< '\\ n;
出口(255);
} 返回解析;
}诠释主(){
AST合并;
对于(标准::字符串常量和放大器;输入:{
{1,2,3; {4; {9,8;}},{5,6;}},
{10,20,30; {40 {90,80;}},{50,60;}},
})
{
合并+ =解析(input.begin(),input.end());
性病::法院LT&;< 合并+<<输入<< - >中与所述;&下;合并<< \\ n;
}
}
当然,它打印:
合并+ {1,2,3; {4; {9,8;}},{5,6;}} - GT; {1,2,3; {4; {9,8;}},{5,6;}}
合并+ {10,20,30; {40 {90,80;}},{50,60;}} - GT; {1,2,3,10,20,30; {4; {9,8;}},{5,6;},{40; {90,80;}},{50,60;}}
更新
在此 - 微不足道的 - 例如,你可以只集合绑定到解析调用的属性。同样的事情会发生,而不移动元素所需运算符+ =
通话,因为规则将被写入自动追加的到绑定容器的属性。
So the following is a slightly shorter way to write the same:
// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
struct ast;
//typedef boost::make_recursive_variant<boost::recursive_wrapper<ast> >::type node;
typedef boost::variant<boost::recursive_wrapper<ast> > node;
struct ast {
std::vector<int> value;
std::vector<node> children;
};
BOOST_FUSION_ADAPT_STRUCT(ast,
(std::vector<int>,value)
(std::vector<node>,children)
)
template <typename It, typename Skipper = qi::space_type>
struct grammar : qi::grammar<It, ast(), Skipper>
{
grammar() : grammar::base_type(start) {
using namespace qi;
start = '{' >> -(int_ % ',') >> ';' >> -(start % ',') >> '}';
BOOST_SPIRIT_DEBUG_NODES((start));
}
private:
qi::rule<It, ast(), Skipper> start;
};
// for output:
static inline std::ostream& operator<<(std::ostream& os, ast const& v) {
using namespace karma;
rule<boost::spirit::ostream_iterator, ast()> r;
r = '{' << -(int_ % ',') << ';' << -((r|eps) % ',') << '}';
return os << format(r, v);
}
template <typename It> void parse(It f, It l, ast& into)
{
static grammar<It> g;
bool ok = qi::phrase_parse(f,l,g,qi::space,into);
if (!ok || (f!=l)) {
std::cout << "Parse failure\n";
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
exit(255);
}
}
int main() {
ast merged;
for(std::string const& input : {
"{1 ,2 ,3 ;{4 ;{9 , 8 ;}},{5 ,6 ;}}",
"{10,20,30;{40;{90, 80;}},{50,60;}}",
})
{
parse(input.begin(), input.end(), merged);
std::cout << "merged + " << input << " --> " << merged << "\n";
}
}
Still prints
这篇关于抽象语法树的迭代更新与提升精神的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!