eli.bendersky | d5ba345 | 2011-02-18 21:32:47 +0200 | [diff] [blame^] | 1 | #----------------------------------------------------------------- |
| 2 | # pycparser: c-to-c.py |
| 3 | # |
| 4 | # Example of |
| 5 | # |
| 6 | # Copyright (C) 2008-2011, Eli Bendersky |
| 7 | # License: LGPL |
| 8 | #----------------------------------------------------------------- |
| 9 | from __future__ import print_function |
| 10 | import sys |
| 11 | |
| 12 | # This is not required if you've installed pycparser into |
| 13 | # your site-packages/ with setup.py |
| 14 | # |
| 15 | sys.path.insert(0, '..') |
| 16 | |
| 17 | from pycparser import c_parser, c_ast, parse_file |
| 18 | |
| 19 | |
| 20 | class CGenerator(c_ast.NodeVisitor): |
| 21 | def __init__(self): |
| 22 | self.output = '' |
| 23 | |
| 24 | def out(self, s): |
| 25 | self.output += s |
| 26 | |
| 27 | def visit_Constant(self, n): |
| 28 | self.out(n.value) |
| 29 | |
| 30 | def visit_ID(self, n): |
| 31 | self.out(n.name) |
| 32 | |
| 33 | def visit_IdentifierType(self, n): |
| 34 | self.out(' '.join(n.names) + ' ') |
| 35 | |
| 36 | def visit_TypeDecl(self, n): |
| 37 | self.generic_visit(n) |
| 38 | if n.declname: self.out(n.declname) |
| 39 | |
| 40 | def visit_PtrDecl(self, n): |
| 41 | self.out('*') |
| 42 | self.visit(n.type) |
| 43 | |
| 44 | def _generate_decl(self, n): |
| 45 | """ Generation from a Decl node. |
| 46 | """ |
| 47 | if n.funcspec: self.out(' '.join(n.funcspec) + ' ') |
| 48 | if n.storage: self.out(' '.join(n.storage) + ' ') |
| 49 | self._generate_type(n.type) |
| 50 | |
| 51 | def _generate_type(self, n, modifiers=[]): |
| 52 | """ Recursive generation from a type node. n is the type node. |
| 53 | modifiers collects the PtrDecl and ArrayDecl modifiers encountered |
| 54 | on the way down to a TypeDecl, to allow proper generation from it. |
| 55 | """ |
| 56 | typ = type(n) |
| 57 | #~ print(n, modifiers) |
| 58 | |
| 59 | if typ == c_ast.TypeDecl: |
| 60 | self.out(' '.join(n.quals) + ' ') |
| 61 | self.generic_visit(n) |
| 62 | |
| 63 | nstr = n.declname if n.declname else '' |
| 64 | # Resolve pointer & array modifiers. |
| 65 | # Wrap in parens to distinguish pointer to array syntax |
| 66 | # |
| 67 | for i, modifier in enumerate(modifiers): |
| 68 | if isinstance(modifier, c_ast.ArrayDecl): |
| 69 | if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)): |
| 70 | nstr = '(' + nstr + ')' |
| 71 | nstr += '[' + modifier.dim.value + ']' |
| 72 | elif isinstance(modifier, c_ast.PtrDecl): |
| 73 | nstr = '*' + nstr |
| 74 | self.out(nstr) |
| 75 | elif typ in (c_ast.Typename, c_ast.Decl): |
| 76 | self._generate_decl(n.type) |
| 77 | elif typ == c_ast.IdentifierType: |
| 78 | self.out(' '.join(n.names) + ' ') |
| 79 | elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl): |
| 80 | self._generate_type(n.type, modifiers + [n]) |
| 81 | |
| 82 | |
| 83 | def visit_Decl(self, n): |
| 84 | self._generate_decl(n) |
| 85 | self.out(';\n') |
| 86 | |
| 87 | |
| 88 | def translate_to_c(filename): |
| 89 | ast = parse_file(filename, use_cpp=True) |
| 90 | generator = CGenerator() |
| 91 | generator.visit(ast) |
| 92 | print(generator.output) |
| 93 | |
| 94 | |
| 95 | if __name__ == "__main__": |
| 96 | if len(sys.argv) > 1: |
| 97 | translate_to_c(sys.argv[1]) |
| 98 | else: |
| 99 | src = r''' |
| 100 | static const int (**c[9])[2] = t; |
| 101 | ''' |
| 102 | parser = c_parser.CParser() |
| 103 | ast = parser.parse(src) |
| 104 | ast.show() |
| 105 | generator = CGenerator() |
| 106 | generator.visit(ast) |
| 107 | print(generator.output) |
| 108 | |
| 109 | |
| 110 | print("Please provide a filename as argument") |