Implementation of a C pre-processor in Python or JavaScript?

grrussel picture grrussel · Dec 4, 2010 · Viewed 7.9k times · Source

Is there a known implementation of the C pre-processor tool implemented either in Python or JavaScript? I am looking for a way to robustly pre-process C (and C like) source code and want to be able to process, for example, conditional compilation and macros without invoking an external CPP tool or native code library. Another potential use case is pre-processing within a web application, within the web browser.

So far, I have found implementations in Java, Perl, and of course, C and C again. It may be plausible to use one of the C to JavaScript compilers now becoming available.

The PLY (Python Lex and Yacc) tools include a cpp implemented in Python.

Answer

Evan Plaice picture Evan Plaice · Mar 16, 2011

Check out pypreprocessor

It can also be found on PYPI (Python Package Index) so it can be downloaded directly using pip.

If you're looking to use #define and #ifdef statements to do simple conditional compilation it should meet your needs. You can either run it as a standalone script and specify an input file (that can be in any language) to process or you can import it as a python module and use it to self-consume python source.

pypreprocessor does not support:

  • macro replacement
  • logical operations (Ie. || &&)
  • mathematical operations (Ie. + - * /)
  • multiline preprocessor directives

It's a tool designed specifically for conditional compilation, not metaprogramming.

Here's an example of how to process a C file using pypreprocessor as a standalone script:

from pypreprocessor import pypreprocessor

pypreprocessor.defines.append('debug')
pypreprocessor.input = 'input_file.c'
pypreprocessor.output = 'output_file.c'
pypreprocessor.removeMeta = True

pypreprocessor.parse()

The implementation is pretty simple.

defines.append('debug'):

Has the same effect as adding a '#define debug' directive to the file. This is just a convenient way to set defines.

pypreprocessor.input = 'input_file.c':

Sets the file you want to process.

pypreprocessor.output = 'output_file.c':

Sets where the file is output to.

pypreprocessor.removeMeta = True:

Removes all of the preprocessor directives found in the file. This includes all #define, #ifdef, #undefine, #else, etc. from the source file. This is useful for creating a 'clean' production version of the source minus all of the conditional code and directives that aren't used. This step is also completely optional. If you don't add this any code that doesn't fall within a defined condition will automatically be commented out.

For example:

#define debug

#ifdef debug
print('this will appear in the postprocessed code')
#else
#print('this will be commented out in the postprocessed code')
#endif

If you need macro replacement to, for instance, change source from one language to another pyprocessor doesn't support this yet. In theory, it wouldn't take much work to add but the lexer would need to be extended first to skip keywords that appear within text strings.

SideNote: It's also compatible with both python2x and python3k.

Disclaimer: I'm the author of pypreprocessor.