Last active
February 1, 2023 21:02
-
-
Save stucotso/76f602a267be052ec19686c38a783f65 to your computer and use it in GitHub Desktop.
Raylib header preprocessor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pycparser import parse_file, c_ast | |
import os | |
class ast: | |
def __init__(self, children=[], params=[], line=0): | |
self.children = children | |
self.params = params | |
self.line = line | |
def expand(self, flags, nest): | |
return "".join([i.expand(flags, nest+1) for i in self.children]) | |
def dump(self, nest=0): | |
ret = ("\t"* nest) + self.__class__.__name__ + "\n" | |
for i in self.children: | |
ret += i.dump(nest+1) | |
return ret | |
class ifdef(ast): | |
def evaluate(self, flags): | |
func = self.params[0].strip() | |
negate = False | |
if func == "#ifndef": negate=True | |
key = self.params[1].strip() | |
test = key in flags.keys() and flags[key] != "" | |
if negate: return not test | |
return test | |
def expand(self, flags, nest): | |
result = "" | |
if self.evaluate(flags):# | |
for i in self.children: | |
child = i.expand(flags, nest+1) | |
if child.strip().split(" ")[0].strip() != "#endif": | |
result += child | |
return result | |
class text(ast): | |
def expand(self, flags, nest): return self.params[0] | |
class Preprocessor(): | |
def __init__(self, flags): | |
self.index = 0 | |
self.flags = flags | |
def preprocessLine(self, lines, parent): | |
if self.index >= len(lines): | |
self.index = -1 | |
return text(line=-1, params=[""]) | |
line = lines[self.index] | |
directive = None | |
if line.strip().startswith("#"): | |
directive = line.strip().split(" ") | |
if directive[0].strip() in ["#ifdef", "#ifndef", "#if"]: | |
self.index += 1 | |
newparent = ifdef(params=directive, line=self.index, children=[]) | |
parent.children.append(newparent) | |
self.preprocessLines(lines, newparent) | |
return newparent | |
self.index += 1 | |
result = text(line=self.index, params=[line]) | |
parent.children.append(result) | |
return result | |
def preprocessLines(self, lines, parent): | |
while self.index >= 0: | |
item = self.preprocessLine(lines, parent) | |
if item.line == -1 or item.params[0].strip() == "#endif" or item.params[0].split(" ")[0] == "#endif": | |
return | |
def preprocessFile(self, f): | |
print ("Preproccessing file:", f) | |
file = open(f, 'r') | |
lines = file.readlines() | |
self.index = 0 | |
result = ast(children=[]) | |
self.preprocessLines(lines, result) | |
if self.index < len(lines) and self.index >=0: raise Exception("error parsing, failed at: " + str(self.index)) | |
return result.expand(self.flags, 0)#self.expand(result.children) | |
headers = [ | |
"../../deps/raylib/src/raylib.h", | |
"../../deps/raylib/src/raymath.h", | |
"../../deps/raygui/src/raygui.h" | |
] | |
params = [ | |
"-d RLAPI", | |
"-d RMAPI", | |
"-d RAYGUIAPI" | |
] | |
def preprocess(): | |
os.system("mkdir tmp") | |
for i in headers: | |
fname = i.split("/")[-1] | |
output = Preprocessor({}).preprocessFile(i) | |
print (output) | |
outHeader = "tmp/" + fname + ".preprocessed" | |
open(outHeader, "w").write(output) | |
def runparser(): | |
os.system("gcc ../../deps/raylib/parser/raylib_parser.c") | |
idx = 0 | |
for i in headers: | |
fname = i.split("/")[-1] | |
os.system("a.exe --input ./tmp/{}.preprocessed --output ./tmp/{}.json --format JSON {}".format(fname, fname, params[idx])) | |
idx += 1 | |
preprocess() | |
runparser() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment