initial import from SVN
diff --git a/examples/cdecl.py b/examples/cdecl.py new file mode 100644 index 0000000..1db5149 --- /dev/null +++ b/examples/cdecl.py
@@ -0,0 +1,108 @@ +#----------------------------------------------------------------- +# pycparser: cdecl.py +# +# Example of the CDECL tool using pycparser. CDECL "explains" +# C type declarations in plain English. +# +# The AST generated by pycparser from the given declaration is +# traversed recursively to build the explanation. +# Note that the declaration must be a valid external declaration +# in C. All the types used in it must be defined with typedef, +# or parsing will fail. The definition can be arbitrary, it isn't +# really used - by pycparser must know which tokens are types. +# +# For example: +# +# 'typedef int Node; const Node* (*ar)[10];' +# => +# ar is a pointer to array[10] of pointer to const Node +# +# Copyright (C) 2008, Eli Bendersky +# License: LGPL +#----------------------------------------------------------------- +import sys + +# This is not required if you've installed pycparser into +# your site-packages/ with setup.py +# +sys.path.insert(0, '..') + +from pycparser import c_parser, c_ast +from pycparser.portability import printme + + +def explain_c_declaration(c_decl): + """ Parses the declaration in c_decl and returns a text + explanation as a string. + + The last external node of the string is used, to allow + earlier typedefs for used types. + """ + parser = c_parser.CParser() + + try: + node = parser.parse(c_decl, filename='<stdin>') + except c_parser.ParseError: + e = sys.exc_info()[1] + return "Parse error:" + str(e) + + if ( not isinstance(node, c_ast.FileAST) or + not isinstance(node.ext[-1], c_ast.Decl)): + return "Not a valid declaration" + + return _explain_decl_node(node.ext[-1]) + + +def _explain_decl_node(decl_node): + """ Receives a c_ast.Decl note and returns its explanation in + English. + """ + #~ print decl_node.show() + storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else '' + + return (decl_node.name + + " is a " + + storage + + _explain_type(decl_node.type)) + + +def _explain_type(decl): + """ Recursively explains a type decl node + """ + typ = type(decl) + + if typ == c_ast.TypeDecl: + quals = ' '.join(decl.quals) + ' ' if decl.quals else '' + return quals + _explain_type(decl.type) + elif typ == c_ast.Typename or typ == c_ast.Decl: + return _explain_type(decl.type) + elif typ == c_ast.IdentifierType: + return ' '.join(decl.names) + elif typ == c_ast.PtrDecl: + quals = ' '.join(decl.quals) + ' ' if decl.quals else '' + return quals + 'pointer to ' + _explain_type(decl.type) + elif typ == c_ast.ArrayDecl: + arr = 'array' + if decl.dim: arr += '[%s]' % decl.dim.value + + return arr + " of " + _explain_type(decl.type) + + elif typ == c_ast.FuncDecl: + if decl.args: + params = [_explain_type(param) for param in decl.args.params] + args = ', '.join(params) + else: + args = '' + + return ('function(%s) returning ' % (args) + + _explain_type(decl.type)) + + +if __name__ == "__main__": + if len(sys.argv) > 1: + c_decl = sys.argv[1] + else: + c_decl = "char *(*(**foo[][8])())[];" + + printme(["Explaining the declaration:", c_decl]) + printme(["\n", explain_c_declaration(c_decl)])