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