/PyCParser

C parser and interpreter written in Python with automatic ctypes interface generation

Primary LanguagePythonBSD 2-Clause "Simplified" LicenseBSD-2-Clause

PyCParser

https://github.com/albertz/PyCParser

A C parser and interpreter written in Python. Also includes an automatic ctypes interface generator.

It is looser than the C grammar, i.e. it should support a superset of the C language in general.

Some of the support may a bit incomplete or wrong at this point because I didn't really strictly followed the language specs but rather improved the parser by iteration on real-world source code.

Similar projects

Parsers / ctypes interface generators:

  • Eli Bendersky's pycparser. Complete C99 parser in pure Python. It depends on Python Lex-Yacc (PLY). (I didn't tested it yet. Seems to be the most complete and most professional project. If you don't want a C interpreter, this is probably the project you should use.)
  • pyclibrary (Github fork). Is quite slow and didn't worked that well for me.
  • ctypesgen. Also uses Lex+Yacc.
  • codegen. Uses GCC-XML. See below about the disadvantages of such an aproach.

Interpreters:

  • CInterpreter. Python.
  • CINT. Not in Python. Probably the most famous one.
  • Ch. Not in Python. Is not really free.
  • ups debugger. Not in Python.
  • PicoC. Not in Python. "A very small C interpreter."
  • BIC. Not in Python.

Why this project?

  • Be more flexible. It is much easier now with a hand-written parser to do operations on certain levels of the parsing pipe.
  • I wanted to have some self-contained code which can also easily run on the end-user side. So the end-user can just update the lib and its headers and then some application using this Python lib will automatically use the updated lib. This is not possible if you generated the ctypes interface statically (via some GCC-XML based tool or so).
  • I wanted to implement PySDL and didn't wanted to translate the SDL headers by hand. Also, I didn't wanted to use existing tools to do this to avoid further maintaining work at some later time. See the project for further info.
  • This functionality could be used similarly for many other C libraries.
  • A challenge for myself. Just for fun. :)

Examples

  • PySDL. Also uses the automatic ctypes wrapper and maps it to a Python module.
  • PyCPython. Interpret CPython in Python.
  • PyLua. Interpret Lua in Python.

Also see the tests/test_interpreter.{c,py} 'Hello world' example.

Also try out ./demos/interactive_interpreter.py --debug.

Current state

  • Many simple C programs should be parsed and interpret correctly now.
  • I'm quite sure that function pointer typedefs are handled incorrectly. E.g. typedef void f(); and typedef void (*f)(); are just the same right now. See cpre3_parse_typedef and do some testing if you want to fix this.
  • Many functions from the standard C library are still missing.
  • There might be some bugs. :)
  • C++ isn't supported yet. :)
  • The code style does not conform to PEP8 and standard Python conventions in many places, as it is quite old. Also, it probably should be restructured, as it has grown too much in single files. I'm slowly fixing this.

How does the interpreter work

This is probably a bit unusual. We wrap the most important standard C library functions directly to the native libc, via ctypes. We translate the parsed C code to a equivalent Python AST (via ast), which makes heavy use of ctypes. Then we just run this generated Python code. But we can also dump it. Thus we can compile C code to an equivalent Python program.

demo

--- Albert Zeyer, http://www.az2000.de