Clangã®python bindingsã使ã
ç ç©¶å ¨ç¶é²ã¾ãªãã®ã«æéã ãã¯éãã¦ããï¼ ããã§ãã£ã¨ç°å¢æ§ç¯ãã¦ããæ°ãããâ¦ï¼
ç°å¢æ§ç¯
clang ASTã®æ å ±ã欲ããã£ãã®ã§ï¼python bindingsã使ããã¨ãããã¾ãã¤ã¾ãã¾ããï¼ æãã¦ããã£ãã®ãã¡ã¢ï¼
homebrewã§llvmã¤ã³ã¹ãã¼ã«ï¼
% brew install llvm --with-clang --with-python
ãã®å ´åï¼brewããå ¥ããpythonã使ãã®ã§ï¼pythonãhomebrewã§å ¥ããï¼
% brew install python
python bindingsã使ãããã«ã¯ï¼LD_LIBRARY_PATHãè¨å®ããå¿ è¦ãããï¼
% export LD_LIBRARY_PATH=$(llvm-config --libdir):$LD_LIBRARY_PATH
ï¼ã¡ãªã¿ã«ï¼ã½ã¼ã¹ã³ã¼ãããã³ã³ãã¤ã«ããå ´åã«ã¯PYTHONPATHãè¨å®ããªãã¨ãããªãï¼
ããã§ï¼ç¡äºä½¿ããããã«ãªãã¾ããï¼
åããããµã³ãã«ã¯ããï¼
[main.py]
import sys import clang.cindex from clang.cindex import Index from clang.cindex import Config def print_node_tree(node): print "%s : %s" % (node.kind.name, node.displayname) for child in node.get_children(): print_node_tree(child) index = Index.create() tu = index.parse("test.cpp") print_node_tree(tu.cursor)
libclang の Python binding を使用する 〜導入編〜 - C++でゲームプログラミングãã®ãµã¤ãã®ãåèã«ãã¾ããï¼
Clang's AST
ç¡äºçµæã¯åºåããã¾ãããï¼ãªã«ããã£ã¦ããå ¨ç¶ããããªãâ¦
Clang ASTã®ãã¨ç¥ããªãããå½ç¶ãããã¯ããªãããªï¼ã¨æã£ã¦ããã¥ã¡ã³ããèªã¿ã¾ããï¼
Introduction to the Clang AST — Clang 3.5 documentation
clangã®ASTããã³ãããã«ã¯ï¼-ast-dumpã®ãªãã·ã§ã³ã使ã£ã¦
% clang -Xclang -ast-dump -fsyntax-only sample.c
ã¨ããã°ããï¼
解æããã³ã¼ãã¨åºåçµæã¯ä»¥ä¸ã®ããã«ãªãã¾ããï¼
[sample.c]
int f() { int a = 1; int b = 2; int c = 0; c = a + b; return c; }
[åºåçµæ]
TranslationUnitDecl 0x7fb55b8012c0 <<invalid sloc>> <invalid sloc> |-TypedefDecl 0x7fb55b8017c0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128' |-TypedefDecl 0x7fb55b801820 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128' |-TypedefDecl 0x7fb55b801b70 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]' `-FunctionDecl 0x7fb55b801c10 <a.c:1:1, line:10:1> line:1:5 f 'int ()' `-CompoundStmt 0x7fb55b801fe8 <line:2:1, line:10:1> |-DeclStmt 0x7fb55b801d38 <line:3:2, col:11> | `-VarDecl 0x7fb55b801cc0 <col:2, col:10> col:6 used a 'int' cinit | `-IntegerLiteral 0x7fb55b801d18 <col:10> 'int' 1 |-DeclStmt 0x7fb55b801dd8 <line:4:2, col:11> | `-VarDecl 0x7fb55b801d60 <col:2, col:10> col:6 used b 'int' cinit | `-IntegerLiteral 0x7fb55b801db8 <col:10> 'int' 2 |-DeclStmt 0x7fb55b801e78 <line:5:2, col:11> | `-VarDecl 0x7fb55b801e00 <col:2, col:10> col:6 used c 'int' cinit | `-IntegerLiteral 0x7fb55b801e58 <col:10> 'int' 0 |-BinaryOperator 0x7fb55b801f60 <line:7:2, col:10> 'int' '=' | |-DeclRefExpr 0x7fb55b801e90 <col:2> 'int' lvalue Var 0x7fb55b801e00 'c' 'int' | `-BinaryOperator 0x7fb55b801f38 <col:6, col:10> 'int' '+' | |-ImplicitCastExpr 0x7fb55b801f08 <col:6> 'int' <LValueToRValue> | | `-DeclRefExpr 0x7fb55b801eb8 <col:6> 'int' lvalue Var 0x7fb55b801cc0 'a' 'int' | `-ImplicitCastExpr 0x7fb55b801f20 <col:10> 'int' <LValueToRValue> | `-DeclRefExpr 0x7fb55b801ee0 <col:10> 'int' lvalue Var 0x7fb55b801d60 'b' 'int' `-ReturnStmt 0x7fb55b801fc8 <line:9:2, col:9> `-ImplicitCastExpr 0x7fb55b801fb0 <col:9> 'int' <LValueToRValue> `-DeclRefExpr 0x7fb55b801f88 <col:9> 'int' lvalue Var 0x7fb55b801e00 'c' 'int'
- AST Context
translation unitã®æä¸ä½ã®å®£è¨ã¯å¸¸ã«translation unit declatationã§ï¼ã¦ã¼ã¶ãæ¸ããã³ã¼ãã®æåã®å®£è¨ã¯function declarationï¼
ãã®bodyã¯compound statementã§ï¼ããã«ãã®åãã¼ãã¯declaration statementï¼
æå¾ã«ï¼return statementãããï¼
â»translation unitã¯ï¼ã³ã³ãã¤ã«ã«ãããåºæ¬åä½
- AST Nodes
éè¦ãªASTã®ãã¼ãã¯Typeï¼åï¼ï¼Declï¼å®£è¨ï¼ï¼DeclContextï¼å®£è¨ã³ã³ããã¹ãï¼ï¼Stmtï¼æï¼ï¼
ASTãæ¢ç´¢ããã«ã¯TranslationUnitDeclããã¹ã¿ã¼ããã¦ï¼ããããåèµ·çã«å°éããããã¼ãããã©ãï¼
Clang's ASTã®åºæ¬çãª2ã¤ã®ãã¼ãã¯statement(Stmt)ã¨declatations(Decl)ï¼
Clang's ASTã§ã¯expressions(Expr)ã¯statementã§ãããã¨ã«æ³¨æï¼
ãªãã¨ãªãClang's ASTã®ãã¨ãããã£ããããªæ°ãããâ¦ï¼
python bindings
ã§ï¼python bindingsã£ã¦ã©ããã£ã¦ä½¿ããã ï¼ã¨æã£ã¦èª¿ã¹ãã¨ï¼python bindingsã®ã½ã¼ã¹ã³ã¼ããèªãã°ããã§ããã£ã¦æ¸ãã¦ããã¾ããï¼
ãããããå ´æã¯ï¼
/usr/local/Cellar/llvm/3.5.0_2/lib/python2.7/site-packages/clang/cindex.py
ã§ã3500è¡ãããããã®ã§ï¼ã©ã£ããèªãã°ããã®ãããããªããï¼ãããã§è¦ªåãªè¨äºãæ¢ãã¾ããï¼ããããããã¥ã¡ã³ãã£ã½ããã®ãè¦ã¤ããã¾ããï¼
Parsing C++ in Python with Clang
- Creating the index and parsing the source
index = clang.cindex.Index.create() tu = index.parse(<ãã¡ã¤ã«å>)
1è¡ç®ã®indexã¯translation unitã表ãï¼
2è¡ç®ã®parceã¡ã½ããã¯ãã¡ã¤ã«ãã1ã¤ã®translation unitããã¼ã¹ããï¼
python bindingsã¯Clang C APIã®CXTranslationUnitãªãã¸ã§ã¯ããTranslationUnitã¨ãã¦ããï¼
cursorã¯libclangã®ãã¼ã«ãªãæ¦å¿µã§ï¼ããã¯ãã¼ã¹ãããtranslation unitã®ASTã®ä¸ã®ãã¼ãã表ãï¼
TranslationUnitl.cursorã¯translation unitã®æä¸ä½ã®cursolãè¿ãï¼ããã¯ï¼ASTã®æ¢ç´¢ã®ã¹ã¿ã¼ãå°ç¹ãæä¾ããï¼
- Working with cursors
python bindingsã¯libclangã®cursorãCursorãªãã¸ã§ã¯ãã¨ãã¦ããï¼ Cursorã¯ããããã®ã¢ããªãã¥ã¼ããæã£ã¦ãããï¼ãã®ä¸ã§èå³æ·±ããã®ã¯
- kindï¼cursorãããã¦ããAStã®ãã¼ãã®ç¨®é¡ã®ä¸è¦§
- spellingï¼ãã¼ãã®ã½ã¼ã¹ã³ã¼ãã®åå
- locationï¼ãã¼ãããã¼ã¹ãããã½ã¼ã¹ã³ã¼ãã®å ´æ
- get_childrenï¼åãã¼ã
get_childrenã使ã£ã¦æ¬¡ã®ããã«ãã¦åèµ·çã«ï¼ä¸ãããããã¼ãã®ãã¹ã¦ã®åãã¼ããæ¢ç´¢ãããã¨ãã§ããï¼
for c in node.get_children(): find_typerefs(c, typename)
ã ã ã ããã
ã¨ããããä»ã¾ã§èª¿ã¹ããã¨ã®ã¡ã¢ã§ããï¼
ãªãã ãå°ãã ãããã£ã¦ããæ°ãããï¼ï¼