blob: e885e40b1ba491d7a8520155c6cb3e8681727f5a [file] [log] [blame]
eli.benderskyfe5c2bb2010-12-04 17:38:11 +02001#-----------------------------------------------------------------
2# pycparser: cdecl.py
3#
Eli Bendersky27797e82013-09-25 06:30:17 -07004# Example of the CDECL tool using pycparser. CDECL "explains" C type
5# declarations in plain English.
eli.benderskyfe5c2bb2010-12-04 17:38:11 +02006#
Eli Bendersky27797e82013-09-25 06:30:17 -07007# The AST generated by pycparser from the given declaration is traversed
8# recursively to build the explanation. Note that the declaration must be a
9# valid external declaration in C. All the types used in it must be defined with
10# typedef, or parsing will fail. The definition can be arbitrary - pycparser
11# doesn't really care what the type is defined to be, only that it's a type.
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020012#
13# For example:
14#
15# 'typedef int Node; const Node* (*ar)[10];'
16# =>
17# ar is a pointer to array[10] of pointer to const Node
18#
Eli Bendersky27797e82013-09-25 06:30:17 -070019# Copyright (C) 2008-2013, Eli Bendersky
eli.bendersky84a6a632011-04-29 09:00:43 +030020# License: BSD
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020021#-----------------------------------------------------------------
22import sys
23
24# This is not required if you've installed pycparser into
25# your site-packages/ with setup.py
26#
Benf86dea12012-02-03 06:24:55 +020027sys.path.extend(['.', '..'])
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020028
29from pycparser import c_parser, c_ast
30
31
Eli Bendersky3921e8e2010-05-21 09:05:39 +030032def explain_c_declaration(c_decl):
Eli Bendersky27797e82013-09-25 06:30:17 -070033 """ Parses the declaration in c_decl and returns a text
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020034 explanation as a string.
Eli Bendersky27797e82013-09-25 06:30:17 -070035
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020036 The last external node of the string is used, to allow
Eli Bendersky3921e8e2010-05-21 09:05:39 +030037 earlier typedefs for used types.
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020038 """
39 parser = c_parser.CParser()
Eli Bendersky27797e82013-09-25 06:30:17 -070040
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020041 try:
42 node = parser.parse(c_decl, filename='<stdin>')
43 except c_parser.ParseError:
44 e = sys.exc_info()[1]
45 return "Parse error:" + str(e)
46
Eli Bendersky27797e82013-09-25 06:30:17 -070047 if (not isinstance(node, c_ast.FileAST) or
48 not isinstance(node.ext[-1], c_ast.Decl)
49 ):
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020050 return "Not a valid declaration"
51
52 return _explain_decl_node(node.ext[-1])
53
54
Eli Bendersky3921e8e2010-05-21 09:05:39 +030055def _explain_decl_node(decl_node):
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020056 """ Receives a c_ast.Decl note and returns its explanation in
Eli Bendersky3921e8e2010-05-21 09:05:39 +030057 English.
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020058 """
59 #~ print decl_node.show()
60 storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else ''
Eli Bendersky27797e82013-09-25 06:30:17 -070061
62 return (decl_node.name +
63 " is a " +
64 storage +
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020065 _explain_type(decl_node.type))
66
67
Eli Bendersky3921e8e2010-05-21 09:05:39 +030068def _explain_type(decl):
69 """ Recursively explains a type decl node
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020070 """
71 typ = type(decl)
Eli Bendersky27797e82013-09-25 06:30:17 -070072
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020073 if typ == c_ast.TypeDecl:
74 quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
75 return quals + _explain_type(decl.type)
76 elif typ == c_ast.Typename or typ == c_ast.Decl:
77 return _explain_type(decl.type)
78 elif typ == c_ast.IdentifierType:
79 return ' '.join(decl.names)
80 elif typ == c_ast.PtrDecl:
81 quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
82 return quals + 'pointer to ' + _explain_type(decl.type)
83 elif typ == c_ast.ArrayDecl:
84 arr = 'array'
85 if decl.dim: arr += '[%s]' % decl.dim.value
Eli Bendersky27797e82013-09-25 06:30:17 -070086
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020087 return arr + " of " + _explain_type(decl.type)
Eli Bendersky27797e82013-09-25 06:30:17 -070088
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020089 elif typ == c_ast.FuncDecl:
90 if decl.args:
91 params = [_explain_type(param) for param in decl.args.params]
92 args = ', '.join(params)
93 else:
94 args = ''
Eli Bendersky27797e82013-09-25 06:30:17 -070095
eli.benderskyfe5c2bb2010-12-04 17:38:11 +020096 return ('function(%s) returning ' % (args) +
97 _explain_type(decl.type))
98
99
100if __name__ == "__main__":
101 if len(sys.argv) > 1:
102 c_decl = sys.argv[1]
103 else:
104 c_decl = "char *(*(**foo[][8])())[];"
105
106 print("Explaining the declaration: " + c_decl + "\n")
Eli Bendersky27797e82013-09-25 06:30:17 -0700107 print(explain_c_declaration(c_decl) + "\n")
eli.benderskyfe5c2bb2010-12-04 17:38:11 +0200108