Eli Bendersky | a1da7fd | 2012-07-06 15:48:57 +0300 | [diff] [blame] | 1 | import sys |
| 2 | from pycparser.c_ast import * |
| 3 | from pycparser.c_parser import CParser, Coord, ParseError |
| 4 | from pycparser.c_lexer import CLexer |
| 5 | |
| 6 | |
| 7 | def expand_decl(decl): |
| 8 | """ Converts the declaration into a nested list. |
| 9 | """ |
| 10 | typ = type(decl) |
| 11 | |
| 12 | if typ == TypeDecl: |
| 13 | return ['TypeDecl', expand_decl(decl.type)] |
| 14 | elif typ == IdentifierType: |
| 15 | return ['IdentifierType', decl.names] |
| 16 | elif typ == ID: |
| 17 | return ['ID', decl.name] |
| 18 | elif typ in [Struct, Union]: |
| 19 | decls = [expand_decl(d) for d in decl.decls or []] |
| 20 | return [typ.__name__, decl.name, decls] |
| 21 | else: |
| 22 | nested = expand_decl(decl.type) |
| 23 | |
| 24 | if typ == Decl: |
| 25 | if decl.quals: |
| 26 | return ['Decl', decl.quals, decl.name, nested] |
| 27 | else: |
| 28 | return ['Decl', decl.name, nested] |
| 29 | elif typ == Typename: # for function parameters |
| 30 | if decl.quals: |
| 31 | return ['Typename', decl.quals, nested] |
| 32 | else: |
| 33 | return ['Typename', nested] |
| 34 | elif typ == ArrayDecl: |
| 35 | dimval = decl.dim.value if decl.dim else '' |
| 36 | return ['ArrayDecl', dimval, nested] |
| 37 | elif typ == PtrDecl: |
| 38 | return ['PtrDecl', nested] |
| 39 | elif typ == Typedef: |
| 40 | return ['Typedef', decl.name, nested] |
| 41 | elif typ == FuncDecl: |
| 42 | if decl.args: |
| 43 | params = [expand_decl(param) for param in decl.args.params] |
| 44 | else: |
| 45 | params = [] |
| 46 | return ['FuncDecl', params, nested] |
| 47 | |
| 48 | #----------------------------------------------------------------- |
| 49 | class NodeVisitor(object): |
eli.bendersky | 724b1cc | 2011-03-05 10:45:08 +0200 | [diff] [blame] | 50 | def __init__(self): |
Eli Bendersky | a1da7fd | 2012-07-06 15:48:57 +0300 | [diff] [blame] | 51 | self.current_parent = None |
| 52 | |
| 53 | def visit(self, node): |
| 54 | """ Visit a node. |
| 55 | """ |
| 56 | method = 'visit_' + node.__class__.__name__ |
| 57 | visitor = getattr(self, method, self.generic_visit) |
| 58 | return visitor(node) |
| 59 | |
eli.bendersky | 3b52ac0 | 2011-03-18 06:32:23 +0200 | [diff] [blame] | 60 | def visit_FuncCall(self, node): |
Eli Bendersky | a1da7fd | 2012-07-06 15:48:57 +0300 | [diff] [blame] | 61 | print("Visiting FuncCall") |
| 62 | print(node.show()) |
| 63 | print('---- parent ----') |
| 64 | print(self.current_parent.show()) |
| 65 | |
| 66 | def generic_visit(self, node): |
| 67 | """ Called if no explicit visitor function exists for a |
| 68 | node. Implements preorder visiting of the node. |
| 69 | """ |
| 70 | oldparent = self.current_parent |
| 71 | self.current_parent = node |
| 72 | for c in node.children(): |
| 73 | self.visit(c) |
| 74 | self.current_parent = oldparent |
| 75 | |
| 76 | |
| 77 | if __name__ == "__main__": |
| 78 | source_code = ''' |
| 79 | ''' |
| 80 | |
| 81 | |
| 82 | #--------------- Lexing |
eli.bendersky | 38165b7 | 2011-02-04 08:13:39 +0200 | [diff] [blame] | 83 | #~ def errfoo(msg, a, b): |
Eli Bendersky | a1da7fd | 2012-07-06 15:48:57 +0300 | [diff] [blame] | 84 | #~ printme(msg) |
| 85 | #~ sys.exit() |
| 86 | #~ clex = CLexer(errfoo, lambda t: False) |
| 87 | #~ clex.build() |
| 88 | #~ clex.input(source_code) |
| 89 | |
| 90 | #~ while 1: |
| 91 | #~ tok = clex.token() |
| 92 | #~ if not tok: break |
| 93 | |
| 94 | #~ printme([tok.value, tok.type, tok.lineno, clex.filename, tok.lexpos]) |
| 95 | |
| 96 | #--------------- Parsing |
| 97 | source_code = r''' |
| 98 | typedef int int8_t; |
Eli Bendersky | 645e260 | 2012-12-25 06:21:08 -0800 | [diff] [blame] | 99 | int boo, 8sd; |
Eli Bendersky | a1da7fd | 2012-07-06 15:48:57 +0300 | [diff] [blame] | 100 | |
| 101 | |
Even | 13ad219 | 2011-11-06 16:02:43 +0100 | [diff] [blame] | 102 | ''' |
Eli Bendersky | a1da7fd | 2012-07-06 15:48:57 +0300 | [diff] [blame] | 103 | |
| 104 | parser = CParser(lex_optimize=False, yacc_optimize=False, yacc_debug=True) |
| 105 | ast = parser.parse(source_code, filename='zz') |
| 106 | ast.show(showcoord=False, attrnames=True, nodenames=True) |
| 107 | #~ nv=NodeVisitor() |
| 108 | #~ nv.visit(ast) |
| 109 | |
| 110 | print('-- done --') |
| 111 | |