C parser in Javascript
-
24-07-2021 - |
Question
I'd like to parse C header files in Javascript. Is there any such library available? Otherwise, any tips to help me get started?
Update: My ultimate goal is to automatically build interfaces for node-ffi. The parser doesn't necessarily have to be in Javascript as long as it can spit out a format understandable by Javascript. If it's very hard to develop by myself, I'll probably have to go with an off the shelf solution...?
Solution
You should check out clang.
For a simple command-line invocation, you can try this:
clang -cc1 -ast-dump-xml myfile.h
Or you can build your own tool using clang
reasonably-well-documented parser library, which will build an AST for you, and let you walk it as you see fit (perhaps for output in JSON).
OTHER TIPS
You might start by looking at peg.js which generates javascript code to parse a grammar given as input. Details avalable here https://pegjs.org/
Then yo would need to write or find a grammar for the header files you want to parse.
Well I'll answer my own question since I found something interesting:
http://www.swig.org/Doc2.0/SWIGDocumentation.html#SWIG_nn2
Swig can output an XML representation of C header files that I could then load from Javascript.
For example:
swig -module yaml -xmlout yaml.xml yaml.h
Generates the following file (snippet below for the yaml_token_delete
function):
...
<cdecl id="16015" addr="0x10835d500" >
<attributelist id="16016" addr="0x10835d500" >
<attribute name="name" value="yaml_token_delete" id="16017" addr="0x1082b2d00" />
<attribute name="sym_symtab" value="0x1081007e0" id="16018" addr="0x1081007e0" />
<attribute name="view" value="globalfunctionHandler" id="16019" addr="0x1082b2d00" />
<attribute name="kind" value="function" id="16020" addr="0x1082b2d00" />
<attribute name="sym_name" value="yaml_token_delete" id="16021" addr="0x1082b2d00" />
<attribute name="wrap_parms" value="0x10835d460" id="16022" addr="0x10835d460" />
<attribute name="decl" value="f(p.yaml_token_t)." id="16023" addr="0x1082b2d00" />
<attribute name="tmap_out" value="" id="16024" addr="0x1082b2d00" />
<parmlist id="16025" addr="0x10835d460" >
<parm id="16026">
<attributelist id="16027" addr="0x10835d460" >
<attribute name="tmap_typecheck" value="void *vptr = 0; int res = SWIG_ConvertPtr($input, &vptr, SWIGTYPE_p_yaml_token_s, 0); arg1 = SWIG_CheckState(res);" id="16028" addr="0x1082b2d00" />
<attribute name="tmap_typecheck_match_type" value="p.SWIGTYPE" id="16029" addr="0x1082b2d00" />
<attribute name="tmap_in_match_type" value="p.SWIGTYPE" id="16030" addr="0x1082b2d00" />
<attribute name="tmap_freearg_match_type" value="p.SWIGTYPE" id="16031" addr="0x1082b2d00" />
<attribute name="compactdefargs" value="1" id="16032" addr="0x1082b2d00" />
<attribute name="name" value="token" id="16033" addr="0x1082b2d00" />
<attribute name="emit_input" value="objv[1]" id="16034" addr="0x1082b2d00" />
<attribute name="tmap_typecheck_precedence" value="0" id="16035" addr="0x1082b2d00" />
<attribute name="tmap_in_numinputs" value="1" id="16036" addr="0x1082b2d00" />
<attribute name="tmap_in" value="res1 = SWIG_ConvertPtr(objv[1], &argp1,SWIGTYPE_p_yaml_token_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "$symname" "', argument " "1"" of type '" "yaml_token_t *""'"); } arg1 = (yaml_token_t *)(argp1);" id="16037" addr="0x1082b2d00" />
...