当前位置: 首页 > news >正文

网站开发 网页设计北京师范大学出版社快速做网站教程

网站开发 网页设计北京师范大学出版社,快速做网站教程,建筑设计公司名字起名大全,wordpress目录导航主题原文 用LibTooling和LibASTMatchers构建工具 这里展示如何基于Clang的LibTooling构建有用的源到源翻译工具.基础 步骤0:取Clang 因为Clang是LLVM项目的一部分,因此你需要先下载LLVM的源码.Clang和LLVM都在同一个git仓库中,在不同的目录下.更多见入门指南. cd ~/clang-llvm…原文 用LibTooling和LibASTMatchers构建工具 这里展示如何基于Clang的LibTooling构建有用的源到源翻译工具.基础 步骤0:取Clang 因为Clang是LLVM项目的一部分,因此你需要先下载LLVM的源码.Clang和LLVM都在同一个git仓库中,在不同的目录下.更多见入门指南. cd ~/clang-llvm git clone https://github.com/llvm/llvm-project.git接着,要取CMake构建系统和Ninja构建工具. cd ~/clang-llvm git clone https://github.com/martine/ninja.git cd ninja git checkout release ./bootstrap.py sudo cp ninja /usr/bin/ cd ~/clang-llvm git clone git://cmake.org/stage/cmake.git cd cmake git checkout next ./bootstrap make sudo make install好.现在构建Clang! cd ~/clang-llvm mkdir build cd build cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTSclang;clang-tools-extra -DLLVM_BUILD_TESTSON # 允许测试,默认关闭. ninja ninja check # Test LLVM only. ninja clang-test # Test Clang only. ninja install好,可以了.所有测试都应通过. 最后,想设置Clang为它自己的编译器. cd ~/clang-llvm/build cmake ../llvm第二个命令打开配置Clang的GUI.你需要设置CMAKE_CXX_COMPILER项.按t打开高级模式.向下滚动到CMAKE_CXX_COMPILER,并设置它为/usr/bin/clang,或安装位置. 按c配置,然后按g生成CMake的文件. 最后,最后一次运行ninja,你就完成了. 步骤1:创建ClangTool 创建最简单的ClangTool:语法检查器.虽然已有clang-check了. 首先,为工具创建新目录,并告诉CMake它存在.因为这不会是核心clang工具,它将在clang-tools-extra仓库中. cd ~/clang-llvm mkdir clang-tools-extra/loop-convert echo add_subdirectory(loop-convert) clang-tools-extra/CMakeLists.txt vim clang-tools-extra/loop-convert/CMakeLists.txtCMakeLists.txt应包含以下内容: set(LLVM_LINK_COMPONENTS support) add_clang_executable(loop-convertLoopConvert.cpp) target_link_libraries(loop-convertPRIVATEclangASTclangASTMatchersclangBasicclangFrontendclangSerializationclangTooling)完成后,Ninja可编译此工具.编译!在clang-tools-extra/loop-convert/LoopConvert.cpp中放置以下内容. 不同部件见LibTooling文档. //声明clang::SyntaxOnlyAction. #include clang/Frontend/FrontendActions.h #include clang/Tooling/CommonOptionsParser.h #include clang/Tooling/Tooling.h //声明llvm::cl::extrahelp. #include llvm/Support/CommandLine.h using namespace clang::tooling; using namespace llvm; //对所有命令行选项,自定义分类,这样只显示他们. static llvm::cl::OptionCategory MyToolCategory(my-tool options);//CommonOptionsParser用与编译数据库和输入文件相关的常见命令行选项的说明声明HelpMessage. //在所有工具中都有此帮助消息.static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); //之后可添加此特定工具的帮助消息. static cl::extrahelp MoreHelp(\nMore help text...\n); int main(int argc, const char **argv) {auto ExpectedParser CommonOptionsParser::create(argc, argv, MyToolCategory);if (!ExpectedParser) {//对不支持的选项,优雅失败.llvm::errs() ExpectedParser.takeError();return 1;}CommonOptionsParser OptionsParser ExpectedParser.get();ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());return Tool.run(newFrontendActionFactoryclang::SyntaxOnlyAction().get()); }就这样!可通过从build目录运行ninja来编译新工具. cd ~/clang-llvm/build ninja现在应可在源文件上运行在~/clang-llvm/build/bin中的语法检查器.试试! echo int main() { return 0; } test.cpp bin/loop-convert test.cpp --注意指定源文件后的两个破折号.在破折号之后传递编译器附加选项,而不是从编译数据库中加载它们,现在不需要选项. Intermezzo:学习AST匹配器基础 Clang最近推出了,提供简单,强大且简洁方式来描述AST中的指定模式的ASTMatcher库. 按宏和模板提供支持的DSL实现匹配器(见ASTMatchers.h,这里),它提供了函数式语言常见的代数数据类型的感觉. 如,假设只想检查二元符号.有个叫binaryOperator的匹配器可完成: binaryOperator(hasOperatorName(), hasLHS(integerLiteral(equals(0))))它会与左侧正好是0字面的加式匹配.不会与其他形式的0(如\0或NULL)匹配,但它与到0的扩展宏匹配. 匹配器也不会匹配调用重载符号,因为有个单独的operatorCallExpr匹配器来处理重载符号. 有个AST匹配器来匹配AST的所有不同节点,缩小匹配器以仅匹配指定条件的AST节点,及从一个AST节点取到另一个AST节点的遍历匹配器. AST匹配器的完整列表 所有名词匹配器都描述了AST中的可绑定实体,以便找到匹配项时可引用它们.为此,只需在这些匹配器上调用bind方法,如: variable(hasType(isInteger())).bind(intvar)第2步:使用AST匹配器 好的,使用匹配器.先定义一个抓按零定义初化的新变量的所有语句的匹配器.从匹配所有for循环开始: forStmt()接着,要在循环的第一部分,指定声明单个变量,以便可扩展匹配器到 forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl()))))最后,可添加把变量初化为零的条件. forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))))))很容易阅读和理解匹配器定义(“匹配,init部分声明了一个按0字面初化的变量的循环”),但很难确定每个部分都是必要的. 注意,此匹配器不会匹配,初化为\0,0.0,NULL或除0整数之外的零的变量的循环. 最后一步是给匹配器取个名字,并绑定ForStmt,因为想用它干活: StatementMatcher LoopMatcher forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0)))))))).bind(forLoop);定义了匹配器后,要添加更多助手来运行它们.匹配器与MatchCallback配对,并用MatchFinder对象注册,然后从ClangTool运行. 添加以下内容到LoopConvert.cpp: #include clang/ASTMatchers/ASTMatchers.h #include clang/ASTMatchers/ASTMatchFinder.h using namespace clang; using namespace clang::ast_matchers; StatementMatcher LoopMatcher forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0)))))))).bind(forLoop); class LoopPrinter : public MatchFinder::MatchCallback { public :virtual void run(const MatchFinder::MatchResult Result) {if (const ForStmt *FS Result.Nodes.getNodeAsclang::ForStmt(forLoop))FS-dump();} };并将main()更改为: int main(int argc, const char **argv) {auto ExpectedParser CommonOptionsParser::create(argc, argv, MyToolCategory);if (!ExpectedParser) {//对不支持的选项,优雅失败.llvm::errs() ExpectedParser.takeError();return 1;}CommonOptionsParser OptionsParser ExpectedParser.get();ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());LoopPrinter Printer;MatchFinder Finder;Finder.addMatcher(LoopMatcher, Printer);return Tool.run(newFrontendActionFactory(Finder).get()); }现在,应该可重新编译,并运行代码以发现for循环.创建包含几个示例的新文件,并测试新手工作品: cd ~/clang-llvm/llvm/llvm_build/ ninja loop-convert vim ~/test-files/simple-loops.cc bin/loop-convert ~/test-files/simple-loops.cc步骤3.5:更复杂的匹配器 简单匹配器可发现for循环,但仍需要过滤掉更多循环.可用一些巧妙选择的匹配器来完成很大一部分剩余工作,但先要决定想要允许的属性. 如何表征可转换为基于区间语法的数组上的循环?大小为N的数组,基于区间的循环: 1,从0索引开始 2,连续迭代 3,在N-1索引处结束 已检查了 (1),因此还要添加的只是检查循环条件,以确保循环的索引变量与N比较,并再次检查确保增量步骤只是递增相同变量. (2)的匹配器很简单:要求在init部分,声明相同变量的前增量或后增量. 可惜,不能写此匹配器.匹配器不包含比较两个任意AST节点,并确定是否相等的逻辑,因此最好就是匹配比允许更多,并额外与回调比较. 就可开始构建该子匹配器.可要求增量步骤是一元增量,如下: hasIncrement(unaryOperator(hasOperatorName()))指定递增内容,引入了Clang的AST的另一个怪癖:因为它们是引用变量声明的表达式,按DeclRefExpr(“声明引用式”)表示变量用法. 要找到引用指定声明的unaryOperator,可简单地给它添加第二个条件: hasIncrement(unaryOperator(hasOperatorName(),hasUnaryOperand(declRefExpr())))此外,可按仅在递增变量为整数时才限制匹配匹配器: hasIncrement(unaryOperator(hasOperatorName(),hasUnaryOperand(declRefExpr(to(varDecl(hasType(isInteger())))))))最后一步是,把标识附加到此变量,以便可在回调中提取它: hasIncrement(unaryOperator(hasOperatorName(),hasUnaryOperand(declRefExpr(to(varDecl(hasType(isInteger())).bind(incrementVariable))))))可添加这段代码到LoopMatcher定义中,并确保配备了新匹配器的程序,只打印出按零初化声明的单个变量的循环,并有由某个变量的一元增量组成的增量步骤. 现在,只需要添加一个匹配器,来检查for循环的条件变量部分是否与数组大小比较.只有一个问题:如果不查看循环主体,则不知道正在迭代的数组! 再次限制为,在匹配器中得到近似想要结果,在回调中填写细节.因此,从如下开始: hasCondition(binaryOperator(hasOperatorName()))确保左侧是引用变量,且右侧有整数类型. hasCondition(binaryOperator(hasOperatorName(),hasLHS(declRefExpr(to(varDecl(hasType(isInteger()))))),hasRHS(expr(hasType(isInteger())))))为什么?因为它不管用.在test-files/simple.cpp中提供的三个循环中,没有一个有匹配条件.快速查看第一个由上一个循环转换迭代生成的for循环的AST转储,展示了答案: (ForStmt 0x173b240(DeclStmt 0x173afc80x173af50 int i (IntegerLiteral 0x173afa8 int 0))(BinaryOperator 0x173b060 _Bool (ImplicitCastExpr 0x173b030 int(DeclRefExpr 0x173afe0 int lvalue Var 0x173af50 i int))(ImplicitCastExpr 0x173b048 int(DeclRefExpr 0x173b008 const int lvalue Var 0x170fa80 N const int)))(UnaryOperator 0x173b0b0 int lvalue prefix (DeclRefExpr 0x173b088 int lvalue Var 0x173af50 i int))(CompoundStatement ...已知道声明和增量都匹配,否则就不会转储该循环.原因在小于符号的第一个操作数(即LHS)的隐式转换,即引用i的式中,有个L值到R值的转换. 好的是,匹配器库,以ignoringParenImpCast提供了此问题方法,告诉匹配器,在继续匹配前,忽略隐式转换和括号. 调整条件符号,恢复期望匹配. hasCondition(binaryOperator(hasOperatorName(),hasLHS(ignoringParenImpCasts(declRefExpr(to(varDecl(hasType(isInteger())))))),hasRHS(expr(hasType(isInteger())))))在把绑定添加到想抓的式中,并把标识串提取到变量中后,完成了数组第2步. 步骤4:提取匹配的节点 目前,匹配器回调,还不是很有趣:它只是转储循环的AST.有时,需要更改输入源码.接着,使用上一步中绑定的节点. MatchFinder::run()回调带MatchFinder::MatchResult参数.感兴趣的是它的Context和Nodes成员. 即,Clang使用ASTContext类,来表示AST的环境信息,但最重要的是多个操作需要ASTContext*参数. 更直接有用的是匹配节点的集合,及如何提取它们. 因为绑定了三个(由ConditionVarName,InitVarName和IncrementVarName标识)变量,因此可用getNodeAs()成员函数取匹配节点. 在LoopConvert.cpp中添加 #include clang/AST/ASTContext.h更改LoopMatcher为: StatementMatcher LoopMatcher forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0)))).bind(initVarName)))),hasIncrement(unaryOperator(hasOperatorName(),hasUnaryOperand(declRefExpr(to(varDecl(hasType(isInteger())).bind(incVarName)))))),hasCondition(binaryOperator(hasOperatorName(),hasLHS(ignoringParenImpCasts(declRefExpr(to(varDecl(hasType(isInteger())).bind(condVarName))))),hasRHS(expr(hasType(isInteger())))))).bind(forLoop);并将LoopPrinter::run更改为 void LoopPrinter::run(const MatchFinder::MatchResult Result) {ASTContext *Context Result.Context;const ForStmt *FS Result.Nodes.getNodeAsForStmt(forLoop);//不想转换头文件!if (!FS || !Context-getSourceManager().isWrittenInMainFile(FS-getForLoc()))return;const VarDecl *IncVar Result.Nodes.getNodeAsVarDecl(incVarName);const VarDecl *CondVar Result.Nodes.getNodeAsVarDecl(condVarName);const VarDecl *InitVar Result.Nodes.getNodeAsVarDecl(initVarName);if (!areSameVariable(IncVar, CondVar) || !areSameVariable(IncVar, InitVar))return;llvm::outs() 发现可能基于数组的循环.\n; }Clang用每个表示变量声明的变量关联VarDecl.因为每个声明的规范形式按地址都是唯一的,因此只需要确保(VarDecl的基类)ValueDecl不是NULL并比较规范声明. static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {return First Second First-getCanonicalDecl() Second-getCanonicalDecl(); }如果执行到达LoopPrinter::run()的末尾,知道循环壳如下 for (int i 0; i expr(); i) { ... }现在,只打印一条说明发现了个循环的消息. 顺便,尽管Clang已通过提供规范式方法,完成了艰苦工作,测试两个式是否相同,并不是那么简单: static bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) {if (!First || !Second)return false;llvm::FoldingSetNodeID FirstID, SecondID;First-Profile(FirstID, *Context, true);Second-Profile(SecondID, *Context, true);return FirstID SecondID; }此代码依赖两个llvm::FoldingSetNodeID间的比较.如Stmt::Profile()文档所示,Profile()成员函数,根据AST中的节点属性及其子节点的属性构建节点描述. 然后,FoldingSetNodeID按比较式的哈希来用.稍后需要areSameExpr.在添加其他循环到test-files/simple.cpp上,运行新代码前,请试找出哪些是可转换的循环.
http://www.tj-hxxt.cn/news/229331.html

相关文章:

  • 怎么做网站外贸123上网
  • 郑州集团网站建设哪家好2019年做网站还有机会吗
  • wordpress建站准备网络广告推广是怎么做的
  • 茶叶包装设计成都抖音seo
  • 胶州做网站的不是搜索网站的是
  • 企业网站建设合同一个网站多个域名的seo优化
  • 有没有专门的销售公司海外seo
  • 物流网站设计与实现专业做网站企业
  • 网站降权了怎么办建分类信息网站
  • 做网站的三个软件网站建设一般满足什么需求
  • 大气产品展示网站源码中国网站优化公司
  • 佳木斯做网站公司精美的php个人网站源码
  • 重庆最便宜的网站建设公司福海网站制作
  • 泸州市建设工程质量监督站网站有自己域名的个人网站
  • 外贸网站镜像网站建设的后如何发布
  • 天津企业seo手机网站优化
  • 西安网站seo 优帮云怎样在内网建设一个网站
  • 企业网站找私人做什河南国控建设集团网站
  • 对于新公司如何让其做网站推广wordpress cdc
  • 温岭高端网站设计哪家好一二三四在线观看视频韩国
  • 简述网站建设的一般步骤网站怎么样排名
  • c 开发商城网站开发如何自己做一个软件
  • 网站怎么建在国外学校网站建设方案模板
  • 网站建设 好沈阳哪家医院人流做得最好
  • 河南省建设工程质量安全监督网站有什么网站可以做海报
  • 站长素材音效wordpress设置静态之后文章打不开
  • 济南网站建设找凌峰建网站需要什么手续
  • 成都企业网站优化服务做网站必须先买域名吗
  • 广州网站设计出名 乐云践新wordpress首页模板制作
  • 网站首页flash模板中国风网站模板下载