My favorites | Sign in
Project Logo
                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#-----------------------------------------------------------------
# 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


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:
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])())[];"

print "Explaining the declaration:", c_decl
print "\n", explain_c_declaration(c_decl)
Show details Hide details

Change log

r59 by eliben on Nov 08, 2008   Diff
1) Added new example (still empty)
2) Fixed import paths in test_c_ast and
test_c_lexer
Go to: 
Project members, sign in to write a code review

Older revisions

r58 by eliben on Nov 08, 2008   Diff
1. Added _build_tables.py that builds
the parse/lex tables inside the
pycparser/ library directory
2. Allow passing lextab and yacctab
table names to CParser
r56 by eliben on Oct 18, 2008   Diff
Completed the cdecl.py example
r54 by eliben on Oct 17, 2008   Diff
Created examples directory
cdecl.py - c declaration explanation
using pycparser

** BUG!!!!! ? showing in current run
...
All revisions of this file

File info

Size: 3367 bytes, 106 lines
Hosted by Google Code