pycparser 2.23__tar.gz → 3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. {pycparser-2.23 → pycparser-3.0}/MANIFEST.in +0 -4
  2. pycparser-3.0/PKG-INFO +244 -0
  3. {pycparser-2.23 → pycparser-3.0}/README.rst +14 -22
  4. {pycparser-2.23 → pycparser-3.0}/examples/c-to-c.py +5 -6
  5. {pycparser-2.23 → pycparser-3.0}/examples/c_json.py +65 -50
  6. pycparser-3.0/examples/cdecl.py +201 -0
  7. {pycparser-2.23 → pycparser-3.0}/examples/construct_ast_from_scratch.py +23 -16
  8. pycparser-3.0/examples/dump_ast.py +32 -0
  9. {pycparser-2.23 → pycparser-3.0}/examples/explore_ast.py +20 -20
  10. {pycparser-2.23 → pycparser-3.0}/examples/func_calls.py +12 -11
  11. {pycparser-2.23 → pycparser-3.0}/examples/func_defs.py +9 -10
  12. {pycparser-2.23 → pycparser-3.0}/examples/func_defs_add_param.py +20 -19
  13. {pycparser-2.23 → pycparser-3.0}/examples/rewrite_ast.py +4 -4
  14. {pycparser-2.23 → pycparser-3.0}/examples/serialize_ast.py +9 -8
  15. {pycparser-2.23 → pycparser-3.0}/examples/using_cpp_libc.py +8 -8
  16. {pycparser-2.23 → pycparser-3.0}/examples/using_gcc_E_libc.py +11 -8
  17. pycparser-3.0/pycparser/__init__.py +99 -0
  18. {pycparser-2.23 → pycparser-3.0}/pycparser/_ast_gen.py +106 -87
  19. pycparser-3.0/pycparser/ast_transforms.py +174 -0
  20. {pycparser-2.23 → pycparser-3.0}/pycparser/c_ast.py +450 -234
  21. pycparser-3.0/pycparser/c_generator.py +573 -0
  22. pycparser-3.0/pycparser/c_lexer.py +706 -0
  23. pycparser-3.0/pycparser/c_parser.py +2376 -0
  24. pycparser-3.0/pycparser.egg-info/PKG-INFO +244 -0
  25. {pycparser-2.23 → pycparser-3.0}/pycparser.egg-info/SOURCES.txt +1 -9
  26. pycparser-3.0/pyproject.toml +38 -0
  27. pycparser-3.0/setup.py +3 -0
  28. pycparser-3.0/tests/test_c_ast.py +136 -0
  29. {pycparser-2.23 → pycparser-3.0}/tests/test_c_generator.py +191 -178
  30. pycparser-3.0/tests/test_c_lexer.py +581 -0
  31. pycparser-3.0/tests/test_c_parser.py +3747 -0
  32. {pycparser-2.23 → pycparser-3.0}/tests/test_examples.py +11 -7
  33. pycparser-3.0/tests/test_general.py +87 -0
  34. {pycparser-2.23 → pycparser-3.0}/tests/test_util.py +16 -14
  35. pycparser-2.23/CHANGES +0 -288
  36. pycparser-2.23/PKG-INFO +0 -28
  37. pycparser-2.23/examples/cdecl.py +0 -198
  38. pycparser-2.23/examples/dump_ast.py +0 -29
  39. pycparser-2.23/pycparser/__init__.py +0 -93
  40. pycparser-2.23/pycparser/_build_tables.py +0 -40
  41. pycparser-2.23/pycparser/ast_transforms.py +0 -164
  42. pycparser-2.23/pycparser/c_generator.py +0 -502
  43. pycparser-2.23/pycparser/c_lexer.py +0 -569
  44. pycparser-2.23/pycparser/c_parser.py +0 -1973
  45. pycparser-2.23/pycparser/lextab.py +0 -10
  46. pycparser-2.23/pycparser/ply/__init__.py +0 -5
  47. pycparser-2.23/pycparser/ply/cpp.py +0 -905
  48. pycparser-2.23/pycparser/ply/ctokens.py +0 -133
  49. pycparser-2.23/pycparser/ply/lex.py +0 -1099
  50. pycparser-2.23/pycparser/ply/yacc.py +0 -3494
  51. pycparser-2.23/pycparser/ply/ygen.py +0 -74
  52. pycparser-2.23/pycparser/plyparser.py +0 -133
  53. pycparser-2.23/pycparser/yacctab.py +0 -374
  54. pycparser-2.23/pycparser.egg-info/PKG-INFO +0 -28
  55. pycparser-2.23/setup.py +0 -67
  56. pycparser-2.23/tests/test_c_ast.py +0 -148
  57. pycparser-2.23/tests/test_c_lexer.py +0 -506
  58. pycparser-2.23/tests/test_c_parser.py +0 -2562
  59. pycparser-2.23/tests/test_general.py +0 -67
  60. {pycparser-2.23 → pycparser-3.0}/LICENSE +0 -0
  61. {pycparser-2.23 → pycparser-3.0}/examples/c_files/basic.c +0 -0
  62. {pycparser-2.23 → pycparser-3.0}/examples/c_files/funky.c +0 -0
  63. {pycparser-2.23 → pycparser-3.0}/examples/c_files/hash.c +0 -0
  64. {pycparser-2.23 → pycparser-3.0}/examples/c_files/memmgr.c +0 -0
  65. {pycparser-2.23 → pycparser-3.0}/examples/c_files/memmgr.h +0 -0
  66. {pycparser-2.23 → pycparser-3.0}/examples/c_files/pragmas.c +0 -0
  67. {pycparser-2.23 → pycparser-3.0}/examples/c_files/year.c +0 -0
  68. {pycparser-2.23 → pycparser-3.0}/pycparser/_c_ast.cfg +0 -0
  69. {pycparser-2.23 → pycparser-3.0}/pycparser.egg-info/dependency_links.txt +0 -0
  70. {pycparser-2.23 → pycparser-3.0}/pycparser.egg-info/top_level.txt +0 -0
  71. {pycparser-2.23 → pycparser-3.0}/setup.cfg +0 -0
  72. {pycparser-2.23 → pycparser-3.0}/tests/__init__.py +0 -0
  73. {pycparser-2.23 → pycparser-3.0}/tests/c_files/c11.c +0 -0
  74. {pycparser-2.23 → pycparser-3.0}/tests/c_files/cppd_with_stdio_h.c +0 -0
  75. {pycparser-2.23 → pycparser-3.0}/tests/c_files/empty.h +0 -0
  76. {pycparser-2.23 → pycparser-3.0}/tests/c_files/example_c_file.c +0 -0
  77. {pycparser-2.23 → pycparser-3.0}/tests/c_files/hdir/9/inc.h +0 -0
  78. {pycparser-2.23 → pycparser-3.0}/tests/c_files/memmgr.c +0 -0
  79. {pycparser-2.23 → pycparser-3.0}/tests/c_files/memmgr.h +0 -0
  80. {pycparser-2.23 → pycparser-3.0}/tests/c_files/memmgr_with_h.c +0 -0
  81. {pycparser-2.23 → pycparser-3.0}/tests/c_files/simplemain.c +0 -0
  82. {pycparser-2.23 → pycparser-3.0}/tests/c_files/year.c +0 -0
  83. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/X11/Intrinsic.h +0 -0
  84. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/X11/Xlib.h +0 -0
  85. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/X11/_X11_fake_defines.h +0 -0
  86. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/X11/_X11_fake_typedefs.h +0 -0
  87. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/_ansi.h +0 -0
  88. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/_fake_defines.h +0 -0
  89. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/_fake_typedefs.h +0 -0
  90. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/_syslist.h +0 -0
  91. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/aio.h +0 -0
  92. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/alloca.h +0 -0
  93. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/ar.h +0 -0
  94. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/argz.h +0 -0
  95. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/arpa/inet.h +0 -0
  96. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/asm-generic/int-ll64.h +0 -0
  97. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/assert.h +0 -0
  98. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/complex.h +0 -0
  99. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/cpio.h +0 -0
  100. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/ctype.h +0 -0
  101. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/dirent.h +0 -0
  102. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/dlfcn.h +0 -0
  103. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/emmintrin.h +0 -0
  104. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/endian.h +0 -0
  105. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/envz.h +0 -0
  106. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/errno.h +0 -0
  107. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/fastmath.h +0 -0
  108. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/fcntl.h +0 -0
  109. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/features.h +0 -0
  110. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/fenv.h +0 -0
  111. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/float.h +0 -0
  112. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/fmtmsg.h +0 -0
  113. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/fnmatch.h +0 -0
  114. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/ftw.h +0 -0
  115. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/getopt.h +0 -0
  116. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/glob.h +0 -0
  117. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/grp.h +0 -0
  118. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/iconv.h +0 -0
  119. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/ieeefp.h +0 -0
  120. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/immintrin.h +0 -0
  121. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/inttypes.h +0 -0
  122. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/iso646.h +0 -0
  123. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/langinfo.h +0 -0
  124. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/libgen.h +0 -0
  125. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/libintl.h +0 -0
  126. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/limits.h +0 -0
  127. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/linux/socket.h +0 -0
  128. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/linux/version.h +0 -0
  129. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/locale.h +0 -0
  130. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/malloc.h +0 -0
  131. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/math.h +0 -0
  132. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/mir_toolkit/client_types.h +0 -0
  133. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/monetary.h +0 -0
  134. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/mqueue.h +0 -0
  135. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/ndbm.h +0 -0
  136. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/net/if.h +0 -0
  137. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/netdb.h +0 -0
  138. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/netinet/in.h +0 -0
  139. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/netinet/tcp.h +0 -0
  140. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/newlib.h +0 -0
  141. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/nl_types.h +0 -0
  142. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/openssl/err.h +0 -0
  143. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/openssl/evp.h +0 -0
  144. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/openssl/hmac.h +0 -0
  145. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/openssl/ssl.h +0 -0
  146. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/openssl/x509v3.h +0 -0
  147. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/paths.h +0 -0
  148. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/poll.h +0 -0
  149. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/process.h +0 -0
  150. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/pthread.h +0 -0
  151. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/pwd.h +0 -0
  152. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/reent.h +0 -0
  153. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/regdef.h +0 -0
  154. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/regex.h +0 -0
  155. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sched.h +0 -0
  156. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/search.h +0 -0
  157. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/semaphore.h +0 -0
  158. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/setjmp.h +0 -0
  159. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/signal.h +0 -0
  160. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/smmintrin.h +0 -0
  161. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/spawn.h +0 -0
  162. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdalign.h +0 -0
  163. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdarg.h +0 -0
  164. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdatomic.h +0 -0
  165. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdbool.h +0 -0
  166. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stddef.h +0 -0
  167. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdint.h +0 -0
  168. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdio.h +0 -0
  169. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdlib.h +0 -0
  170. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stdnoreturn.h +0 -0
  171. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/string.h +0 -0
  172. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/strings.h +0 -0
  173. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/stropts.h +0 -0
  174. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/ioctl.h +0 -0
  175. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/ipc.h +0 -0
  176. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/mman.h +0 -0
  177. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/msg.h +0 -0
  178. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/poll.h +0 -0
  179. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/resource.h +0 -0
  180. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/select.h +0 -0
  181. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/sem.h +0 -0
  182. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/shm.h +0 -0
  183. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/socket.h +0 -0
  184. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/stat.h +0 -0
  185. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/statvfs.h +0 -0
  186. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/sysctl.h +0 -0
  187. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/time.h +0 -0
  188. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/times.h +0 -0
  189. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/types.h +0 -0
  190. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/uio.h +0 -0
  191. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/un.h +0 -0
  192. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/utsname.h +0 -0
  193. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/sys/wait.h +0 -0
  194. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/syslog.h +0 -0
  195. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/tar.h +0 -0
  196. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/termios.h +0 -0
  197. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/tgmath.h +0 -0
  198. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/threads.h +0 -0
  199. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/time.h +0 -0
  200. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/trace.h +0 -0
  201. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/ulimit.h +0 -0
  202. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/unctrl.h +0 -0
  203. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/unistd.h +0 -0
  204. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/utime.h +0 -0
  205. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/utmp.h +0 -0
  206. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/utmpx.h +0 -0
  207. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/wchar.h +0 -0
  208. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/wctype.h +0 -0
  209. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/wordexp.h +0 -0
  210. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/xcb/xcb.h +0 -0
  211. {pycparser-2.23 → pycparser-3.0}/utils/fake_libc_include/zlib.h +0 -0
@@ -6,7 +6,3 @@ include README.*
6
6
  include LICENSE
7
7
  include CHANGES
8
8
  include setup.*
9
- exclude setup.pyc
10
-
11
- recursive-exclude tests yacctab.* lextab.*
12
- recursive-exclude examples yacctab.* lextab.*
pycparser-3.0/PKG-INFO ADDED
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycparser
3
+ Version: 3.0
4
+ Summary: C parser in Python
5
+ Author-email: Eli Bendersky <eliben@gmail.com>
6
+ Maintainer-email: Eli Bendersky <eliben@gmail.com>
7
+ License-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/eliben/pycparser
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/x-rst
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ ===============
22
+ pycparser v3.00
23
+ ===============
24
+
25
+
26
+ .. image:: https://github.com/eliben/pycparser/workflows/pycparser-tests/badge.svg
27
+ :align: center
28
+ :target: https://github.com/eliben/pycparser/actions
29
+
30
+ ----
31
+
32
+ .. contents::
33
+ :backlinks: none
34
+
35
+ .. sectnum::
36
+
37
+ Introduction
38
+ ============
39
+
40
+ What is pycparser?
41
+ ------------------
42
+
43
+ **pycparser** is a parser for the C language, written in pure Python. It is a
44
+ module designed to be easily integrated into applications that need to parse
45
+ C source code.
46
+
47
+ What is it good for?
48
+ --------------------
49
+
50
+ Anything that needs C code to be parsed. The following are some uses for
51
+ **pycparser**, taken from real user reports:
52
+
53
+ * C code obfuscator
54
+ * Front-end for various specialized C compilers
55
+ * Static code checker
56
+ * Automatic unit-test discovery
57
+ * Adding specialized extensions to the C language
58
+
59
+ One of the most popular uses of **pycparser** is in the `cffi
60
+ <https://cffi.readthedocs.io/en/latest/>`_ library, which uses it to parse the
61
+ declarations of C functions and types in order to auto-generate FFIs.
62
+
63
+ **pycparser** is unique in the sense that it's written in pure Python - a very
64
+ high level language that's easy to experiment with and tweak. To people familiar
65
+ with Lex and Yacc, **pycparser**'s code will be simple to understand. It also
66
+ has no external dependencies (except for a Python interpreter), making it very
67
+ simple to install and deploy.
68
+
69
+ Which version of C does pycparser support?
70
+ ------------------------------------------
71
+
72
+ **pycparser** aims to support the full C99 language (according to the standard
73
+ ISO/IEC 9899). Some features from C11 are also supported, and patches to support
74
+ more are welcome.
75
+
76
+ **pycparser** supports very few GCC extensions, but it's fairly easy to set
77
+ things up so that it parses code with a lot of GCC-isms successfully. See the
78
+ `FAQ <https://github.com/eliben/pycparser/wiki/FAQ>`_ for more details.
79
+
80
+ What grammar does pycparser follow?
81
+ -----------------------------------
82
+
83
+ **pycparser** very closely follows the C grammar provided in Annex A of the C99
84
+ standard (ISO/IEC 9899).
85
+
86
+ How is pycparser licensed?
87
+ --------------------------
88
+
89
+ `BSD license <https://github.com/eliben/pycparser/blob/master/LICENSE>`_.
90
+
91
+ Contact details
92
+ ---------------
93
+
94
+ For reporting problems with **pycparser** or submitting feature requests, please
95
+ open an `issue <https://github.com/eliben/pycparser/issues>`_, or submit a
96
+ pull request.
97
+
98
+
99
+ Installing
100
+ ==========
101
+
102
+ Prerequisites
103
+ -------------
104
+
105
+ **pycparser** is being tested with modern versions of Python on
106
+ Linux, macOS and Windows. See `the CI dashboard <https://github.com/eliben/pycparser/actions/workflows/ci.yml>`__
107
+ for details.
108
+
109
+ **pycparser** has no external dependencies.
110
+
111
+ Installation process
112
+ --------------------
113
+
114
+ The recommended way to install **pycparser** is with ``pip``::
115
+
116
+ > pip install pycparser
117
+
118
+ Using
119
+ =====
120
+
121
+ Interaction with the C preprocessor
122
+ -----------------------------------
123
+
124
+ In order to be compilable, C code must be preprocessed by the C preprocessor -
125
+ ``cpp``. A compatible ``cpp`` handles preprocessing directives like ``#include`` and
126
+ ``#define``, removes comments, and performs other minor tasks that prepare the C
127
+ code for compilation.
128
+
129
+ For all but the most trivial snippets of C code **pycparser**, like a C
130
+ compiler, must receive preprocessed C code in order to function correctly. If
131
+ you import the top-level ``parse_file`` function from the **pycparser** package,
132
+ it will interact with ``cpp`` for you, as long as it's in your PATH, or you
133
+ provide a path to it.
134
+
135
+ Note also that you can use ``gcc -E`` or ``clang -E`` instead of ``cpp``. See
136
+ the ``using_gcc_E_libc.py`` example for more details. Windows users can download
137
+ and install a binary build of Clang for Windows `from this website
138
+ <http://llvm.org/releases/download.html>`_.
139
+
140
+ What about the standard C library headers?
141
+ ------------------------------------------
142
+
143
+ C code almost always ``#include``\s various header files from the standard C
144
+ library, like ``stdio.h``. While (with some effort) **pycparser** can be made to
145
+ parse the standard headers from any C compiler, it's much simpler to use the
146
+ provided "fake" standard includes for C11 in ``utils/fake_libc_include``. These
147
+ are standard C header files that contain only the bare necessities to allow
148
+ valid parsing of the files that use them. As a bonus, since they're minimal, it
149
+ can significantly improve the performance of parsing large C files.
150
+
151
+ The key point to understand here is that **pycparser** doesn't really care about
152
+ the semantics of types. It only needs to know whether some token encountered in
153
+ the source is a previously defined type. This is essential in order to be able
154
+ to parse C correctly.
155
+
156
+ See `this blog post
157
+ <https://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers>`_
158
+ for more details.
159
+
160
+ Note that the fake headers are not included in the ``pip`` package nor installed
161
+ via the package build (`#224 <https://github.com/eliben/pycparser/issues/224>`_).
162
+
163
+ Basic usage
164
+ -----------
165
+
166
+ Take a look at the |examples|_ directory of the distribution for a few examples
167
+ of using **pycparser**. These should be enough to get you started. Please note
168
+ that most realistic C code samples would require running the C preprocessor
169
+ before passing the code to **pycparser**; see the previous sections for more
170
+ details.
171
+
172
+ .. |examples| replace:: ``examples``
173
+ .. _examples: examples
174
+
175
+
176
+ Advanced usage
177
+ --------------
178
+
179
+ The public interface of **pycparser** is well documented with comments in
180
+ ``pycparser/c_parser.py``. For a detailed overview of the various AST nodes
181
+ created by the parser, see ``pycparser/_c_ast.cfg``.
182
+
183
+ There's also a `FAQ available here <https://github.com/eliben/pycparser/wiki/FAQ>`_.
184
+ In any case, you can always drop me an `email <eliben@gmail.com>`_ for help.
185
+
186
+
187
+ Modifying
188
+ =========
189
+
190
+ There are a few points to keep in mind when modifying **pycparser**:
191
+
192
+ * The code for **pycparser**'s AST nodes is automatically generated from a
193
+ configuration file - ``_c_ast.cfg``, by ``_ast_gen.py``. If you modify the AST
194
+ configuration, make sure to re-generate the code. This can be done by running
195
+ the ``_ast_gen.py`` script (from the repository root or the
196
+ ``pycparser`` directory).
197
+ * Read the docstring in the constructor of the ``CParser`` class for details
198
+ on configuration and compatibility arguments.
199
+
200
+
201
+ Package contents
202
+ ================
203
+
204
+ Once you unzip the ``pycparser`` package, you'll see the following files and
205
+ directories:
206
+
207
+ README.rst:
208
+ This README file.
209
+
210
+ LICENSE:
211
+ The pycparser license
212
+
213
+ setup.py:
214
+ Legacy installation script (build metadata lives in ``pyproject.toml``).
215
+
216
+ pyproject.toml:
217
+ Package metadata and build configuration.
218
+
219
+ examples/:
220
+ A directory with some examples of using **pycparser**
221
+
222
+ pycparser/:
223
+ The **pycparser** module source code.
224
+
225
+ tests/:
226
+ Unit tests.
227
+
228
+ utils/fake_libc_include:
229
+ Minimal standard C library include files that should allow to parse any C code.
230
+ Note that these headers now include C11 code, so they may not work when the
231
+ preprocessor is configured to an earlier C standard (like ``-std=c99``).
232
+
233
+ utils/internal/:
234
+ Internal utilities for my own use. You probably don't need them.
235
+
236
+
237
+ Contributors
238
+ ============
239
+
240
+ Some people have contributed to **pycparser** by opening issues on bugs they've
241
+ found and/or submitting patches. The list of contributors is in the CONTRIBUTORS
242
+ file in the source distribution. After **pycparser** moved to Github I stopped
243
+ updating this list because Github does a much better job at tracking
244
+ contributions.
@@ -1,5 +1,5 @@
1
1
  ===============
2
- pycparser v2.23
2
+ pycparser v3.00
3
3
  ===============
4
4
 
5
5
 
@@ -14,7 +14,6 @@ pycparser v2.23
14
14
 
15
15
  .. sectnum::
16
16
 
17
-
18
17
  Introduction
19
18
  ============
20
19
 
@@ -83,18 +82,11 @@ Installing
83
82
  Prerequisites
84
83
  -------------
85
84
 
86
- * **pycparser** was tested with Python 3.8+ on Linux, macOS and Windows.
87
-
88
- * **pycparser** has no external dependencies. The only non-stdlib library it
89
- uses is PLY, which is bundled in ``pycparser/ply``. The current PLY version is
90
- 3.10, retrieved from `<http://www.dabeaz.com/ply/>`_
85
+ **pycparser** is being tested with modern versions of Python on
86
+ Linux, macOS and Windows. See `the CI dashboard <https://github.com/eliben/pycparser/actions/workflows/ci.yml>`__
87
+ for details.
91
88
 
92
- Note that **pycparser** (and PLY) uses docstrings for grammar specifications.
93
- Python installations that strip docstrings (such as when using the Python
94
- ``-OO`` option) will fail to instantiate and use **pycparser**. You can try to
95
- work around this problem by making sure the PLY parsing tables are pre-generated
96
- in normal mode; this isn't an officially supported/tested mode of operation,
97
- though.
89
+ **pycparser** has no external dependencies.
98
90
 
99
91
  Installation process
100
92
  --------------------
@@ -146,7 +138,7 @@ See `this blog post
146
138
  for more details.
147
139
 
148
140
  Note that the fake headers are not included in the ``pip`` package nor installed
149
- via ``setup.py`` (`#224 <https://github.com/eliben/pycparser/issues/224>`_).
141
+ via the package build (`#224 <https://github.com/eliben/pycparser/issues/224>`_).
150
142
 
151
143
  Basic usage
152
144
  -----------
@@ -180,11 +172,10 @@ There are a few points to keep in mind when modifying **pycparser**:
180
172
  * The code for **pycparser**'s AST nodes is automatically generated from a
181
173
  configuration file - ``_c_ast.cfg``, by ``_ast_gen.py``. If you modify the AST
182
174
  configuration, make sure to re-generate the code. This can be done by running
183
- the ``_build_tables.py`` script from the ``pycparser`` directory.
184
- * Make sure you understand the optimized mode of **pycparser** - for that you
185
- must read the docstring in the constructor of the ``CParser`` class. For
186
- development you should create the parser without optimizations, so that it
187
- will regenerate the Yacc and Lex tables when you change the grammar.
175
+ the ``_ast_gen.py`` script (from the repository root or the
176
+ ``pycparser`` directory).
177
+ * Read the docstring in the constructor of the ``CParser`` class for details
178
+ on configuration and compatibility arguments.
188
179
 
189
180
 
190
181
  Package contents
@@ -200,7 +191,10 @@ LICENSE:
200
191
  The pycparser license
201
192
 
202
193
  setup.py:
203
- Installation script
194
+ Legacy installation script (build metadata lives in ``pyproject.toml``).
195
+
196
+ pyproject.toml:
197
+ Package metadata and build configuration.
204
198
 
205
199
  examples/:
206
200
  A directory with some examples of using **pycparser**
@@ -228,5 +222,3 @@ found and/or submitting patches. The list of contributors is in the CONTRIBUTORS
228
222
  file in the source distribution. After **pycparser** moved to Github I stopped
229
223
  updating this list because Github does a much better job at tracking
230
224
  contributions.
231
-
232
-
@@ -1,4 +1,4 @@
1
- #------------------------------------------------------------------------------
1
+ # ------------------------------------------------------------------------------
2
2
  # pycparser: c-to-c.py
3
3
  #
4
4
  # Example of using pycparser.c_generator, serving as a simplistic translator
@@ -6,19 +6,18 @@
6
6
  #
7
7
  # Eli Bendersky [https://eli.thegreenplace.net/]
8
8
  # License: BSD
9
- #------------------------------------------------------------------------------
9
+ # ------------------------------------------------------------------------------
10
10
  import sys
11
11
 
12
12
  # This is not required if you've installed pycparser into
13
13
  # your site-packages/ with setup.py
14
- sys.path.extend(['.', '..'])
14
+ sys.path.extend([".", ".."])
15
15
 
16
16
  from pycparser import parse_file, c_generator
17
17
 
18
18
 
19
- def translate_to_c(filename):
20
- """ Simply use the c_generator module to emit a parsed AST.
21
- """
19
+ def translate_to_c(filename: str) -> None:
20
+ """Simply use the c_generator module to emit a parsed AST."""
22
21
  ast = parse_file(filename, use_cpp=True)
23
22
  generator = c_generator.CGenerator()
24
23
  print(generator.visit(ast))
@@ -1,4 +1,4 @@
1
- #------------------------------------------------------------------------------
1
+ # ------------------------------------------------------------------------------
2
2
  # pycparser: c_json.py
3
3
  #
4
4
  # by Michael White (@mypalmike)
@@ -33,38 +33,48 @@
33
33
  # ]
34
34
  # }
35
35
  # }
36
- #------------------------------------------------------------------------------
36
+ # ------------------------------------------------------------------------------
37
37
  import json
38
38
  import sys
39
39
  import re
40
+ from typing import Any, Callable, Dict, Optional, Set, TypeVar
40
41
 
41
42
  # This is not required if you've installed pycparser into
42
43
  # your site-packages/ with setup.py
43
- sys.path.extend(['.', '..'])
44
+ sys.path.extend([".", ".."])
44
45
 
45
46
  from pycparser import parse_file, c_ast
46
- from pycparser.plyparser import Coord
47
+ from pycparser.c_parser import Coord
47
48
 
48
49
 
49
- RE_CHILD_ARRAY = re.compile(r'(.*)\[(.*)\]')
50
- RE_INTERNAL_ATTR = re.compile('__.*__')
50
+ RE_CHILD_ARRAY = re.compile(r"(.*)\[(.*)\]")
51
+ RE_INTERNAL_ATTR = re.compile("__.*__")
51
52
 
52
53
 
53
54
  class CJsonError(Exception):
54
55
  pass
55
56
 
56
57
 
57
- def memodict(fn):
58
- """ Fast memoization decorator for a function taking a single argument """
59
- class memodict(dict):
60
- def __missing__(self, key):
61
- ret = self[key] = fn(key)
62
- return ret
63
- return memodict().__getitem__
58
+ _T = TypeVar("_T")
59
+ _R = TypeVar("_R")
60
+
61
+
62
+ def memodict(fn: Callable[[_T], _R]) -> Callable[[_T], _R]:
63
+ """Fast memoization decorator for a function taking a single argument"""
64
+ cache: Dict[_T, _R] = {}
65
+
66
+ def memoized(arg: _T) -> _R:
67
+ if arg in cache:
68
+ return cache[arg]
69
+ result = fn(arg)
70
+ cache[arg] = result
71
+ return result
72
+
73
+ return memoized
64
74
 
65
75
 
66
76
  @memodict
67
- def child_attrs_of(klass):
77
+ def child_attrs_of(klass: type[c_ast.Node]) -> Set[str]:
68
78
  """
69
79
  Given a Node class, get a set of child attrs.
70
80
  Memoized to avoid highly repetitive string manipulation
@@ -75,14 +85,14 @@ def child_attrs_of(klass):
75
85
  return all_attrs - non_child_attrs
76
86
 
77
87
 
78
- def to_dict(node):
79
- """ Recursively convert an ast into dict representation. """
88
+ def to_dict(node: c_ast.Node) -> Dict[str, Any]:
89
+ """Recursively convert an ast into dict representation."""
80
90
  klass = node.__class__
81
91
 
82
- result = {}
92
+ result: Dict[str, Any] = {}
83
93
 
84
94
  # Metadata
85
- result['_nodetype'] = klass.__name__
95
+ result["_nodetype"] = klass.__name__
86
96
 
87
97
  # Local node attributes
88
98
  for attr in klass.attr_names:
@@ -90,9 +100,9 @@ def to_dict(node):
90
100
 
91
101
  # Coord object
92
102
  if node.coord:
93
- result['coord'] = str(node.coord)
103
+ result["coord"] = str(node.coord)
94
104
  else:
95
- result['coord'] = None
105
+ result["coord"] = None
96
106
 
97
107
  # Child attributes
98
108
  for child_name, child in node.children():
@@ -104,9 +114,12 @@ def to_dict(node):
104
114
  # arrays come in order, so we verify and append.
105
115
  result[array_name] = result.get(array_name, [])
106
116
  if array_index != len(result[array_name]):
107
- raise CJsonError('Internal ast error. Array {} out of order. '
108
- 'Expected index {}, got {}'.format(
109
- array_name, len(result[array_name]), array_index))
117
+ raise CJsonError(
118
+ "Internal ast error. Array {} out of order. "
119
+ "Expected index {}, got {}".format(
120
+ array_name, len(result[array_name]), array_index
121
+ )
122
+ )
110
123
  result[array_name].append(to_dict(child))
111
124
  else:
112
125
  result[child_name] = to_dict(child)
@@ -119,53 +132,55 @@ def to_dict(node):
119
132
  return result
120
133
 
121
134
 
122
- def to_json(node, **kwargs):
123
- """ Convert ast node to json string """
135
+ def to_json(node: c_ast.Node, **kwargs: Any) -> str:
136
+ """Convert ast node to json string"""
124
137
  return json.dumps(to_dict(node), **kwargs)
125
138
 
126
139
 
127
- def file_to_dict(filename):
128
- """ Load C file into dict representation of ast """
140
+ def file_to_dict(filename: str) -> Dict[str, Any]:
141
+ """Load C file into dict representation of ast"""
129
142
  ast = parse_file(filename, use_cpp=True)
130
143
  return to_dict(ast)
131
144
 
132
145
 
133
- def file_to_json(filename, **kwargs):
134
- """ Load C file into json string representation of ast """
146
+ def file_to_json(filename: str, **kwargs: Any) -> str:
147
+ """Load C file into json string representation of ast"""
135
148
  ast = parse_file(filename, use_cpp=True)
136
149
  return to_json(ast, **kwargs)
137
150
 
138
151
 
139
- def _parse_coord(coord_str):
140
- """ Parse coord string (file:line[:column]) into Coord object. """
152
+ def _parse_coord(coord_str: Optional[str]) -> Optional[Coord]:
153
+ """Parse coord string (file:line[:column]) into Coord object."""
141
154
  if coord_str is None:
142
155
  return None
143
156
 
144
- vals = coord_str.split(':')
145
- vals.extend([None] * 3)
157
+ vals = coord_str.split(":")
158
+ vals.extend(["", "", ""])
146
159
  filename, line, column = vals[:3]
147
- return Coord(filename, line, column)
160
+ line_num = int(line) if line else 0
161
+ column_num = int(column) if column else None
162
+ return Coord(filename, line_num, column_num)
148
163
 
149
164
 
150
- def _convert_to_obj(value):
165
+ def _convert_to_obj(value: Any) -> Any:
151
166
  """
152
167
  Convert an object in the dict representation into an object.
153
168
  Note: Mutually recursive with from_dict.
154
169
 
155
170
  """
156
- value_type = type(value)
157
- if value_type == dict:
158
- return from_dict(value)
159
- elif value_type == list:
160
- return [_convert_to_obj(item) for item in value]
161
- else:
162
- # String
163
- return value
171
+ match value:
172
+ case dict():
173
+ return from_dict(value)
174
+ case list():
175
+ return [_convert_to_obj(item) for item in value]
176
+ case _:
177
+ # String
178
+ return value
164
179
 
165
180
 
166
- def from_dict(node_dict):
167
- """ Recursively build an ast from dict representation """
168
- class_name = node_dict.pop('_nodetype')
181
+ def from_dict(node_dict: Dict[str, Any]) -> c_ast.Node:
182
+ """Recursively build an ast from dict representation"""
183
+ class_name = node_dict.pop("_nodetype")
169
184
 
170
185
  klass = getattr(c_ast, class_name)
171
186
 
@@ -173,7 +188,7 @@ def from_dict(node_dict):
173
188
  # to node constructors.
174
189
  objs = {}
175
190
  for key, value in node_dict.items():
176
- if key == 'coord':
191
+ if key == "coord":
177
192
  objs[key] = _parse_coord(value)
178
193
  else:
179
194
  objs[key] = _convert_to_obj(value)
@@ -183,12 +198,12 @@ def from_dict(node_dict):
183
198
  return klass(**objs)
184
199
 
185
200
 
186
- def from_json(ast_json):
187
- """ Build an ast from json string representation """
201
+ def from_json(ast_json: str) -> c_ast.Node:
202
+ """Build an ast from json string representation"""
188
203
  return from_dict(json.loads(ast_json))
189
204
 
190
205
 
191
- #------------------------------------------------------------------------------
206
+ # ------------------------------------------------------------------------------
192
207
  if __name__ == "__main__":
193
208
  if len(sys.argv) > 1:
194
209
  # Some test code...