typhoon-hil / cparser

C parser writen in Python
MIT License
12 stars 3 forks source link

Parser breaks on directives, expects integer #2

Closed dargueta closed 3 years ago

dargueta commented 5 years ago

Something appears to be wrong with the grammar, because directives cause syntax errors. To reproduce:

>>> parser = cparser.CParser()                                                                                                                                                                                     

>>> tree = parser.parse('#ifndef SOMETHING\n')                                                                                                                                                  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/dargueta/.local/lib/python3.7/site-packages/cparser/parser.py", line 137, in parse
    results = self._glr.parse(code)
  File "/home/dargueta/.local/lib/python3.7/site-packages/parglare/glr.py", line 193, in parse
    for h in last_heads_for_reduce}))
parglare.exceptions.ParseError: Error at 1:1:"#*ifndef SOM" => Expected: int_const but found <KEYWORD(ifndef)> or <id(ifndef)>

Error at 1:1:"#*ifndef SOM" => Expected: int_const but found <KEYWORD(ifndef)> or <id(ifndef)>

I also tried it with #define, #endif, #undef and it failed with the same kind of error. The problem seems to be here in the grammar:

line_directive              : "#" int_const string
                            | "#" int_const string int_const
                            | "#" int_const string int_const int_const
                            ;

Environment:

alensuljkanovic commented 5 years ago

Hi, cparser is currently not able to parse C code with preprocessing directives. In order to mitigate this, you must call preprocessor and then parse preprocessed C code.

However, rule line_directive was indeed buggy, and I fixed that on fix_preprocessing branch. Here's an example how you can parse C code with preprocessor directives:


from cparser import CParser
from cparser.parser import preprocess_file
import tempfile

code = """
#include <stdio.h>

#ifndef CUSTOM_PI
#define CUSTOM_PI 3.14159265358979323846
#endif

int main() {
    float a = CUSTOM_PI;
    return 0;
}
"""

cparser = CParser()
with tempfile.NamedTemporaryFile("w+", suffix=".c") as f:
    f.write(code)
    f.flush()

    pp_code = preprocess_file(f.name, cpp_path="cpp")
    ast = cparser.parse(pp_code)

Another example can be found examples.