Newer
Older
Import / research / enums / EnumsGen.py
#!/usr/bin/python

import re
import sys

def comment_remover(text):
    def replacer(match):
        s = match.group(0)
        if s.startswith('/') or s.startswith('#'):
            return " " # note: a space and not an empty string
        else:
            return s
    pattern = re.compile(r'//.*?$|#.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE)
    return re.sub(pattern, replacer, text)

if len(sys.argv) < 3:
    print('Usage: ' + sys.argv[0] + ' INFILE OUTFILE\n')
    sys.exit(-1)

input = open(sys.argv[1], "r")
with input:
    uncommented = comment_remover(input.read())
    for char in '><\':|][!~*./()+-"{};,=':
        tmp_str = ' ' + char + ' '
        uncommented = tmp_str.join(uncommented.split(char))
    uncommented_lines = uncommented.split('\n')

lines = list()
for line in uncommented_lines:
    lines += re.split(' ', line.strip())
while "" in lines:
    lines.remove("")

# lines now contains the preprocessed input - comments and preprocessor tokens stipped, and then tokenized
# lines is a list of tokens, we now scan for enums

output = open(sys.argv[2], "w")
with output:
    def write_header():
        output.write('// This code is generated, DO NOT EDIT.\n')
        output.write('// Instead, edit ' + sys.argv[1] + ' and rerun ' + sys.argv[0] + '\n')
        output.write('\n')
        output.write('#pragma once\n')
        output.write('\n')
        output.write('#include "EnumMapping.hpp"\n')
    def write_prolog(enum):
        output.write('\n')
        output.write('// ' + enum + '\n')
        # output.write('template <>\n')
        # output.write('const enum_map<' + enum + '>& enum_mapping()\n')
        # output.write('const enum_map& enum_mapping(' + enum + ' e = static_cast<' + enum + '>(0))\n')
        output.write('const enum_map& enum_mapping(' + enum + ')\n')
        output.write('{\n')
        # output.write('    static enum_map<' + enum + '> mapping("' + enum + '");\n')
        output.write('    static enum_map mapping("' + enum + '");\n')
        output.write('    if (!mapping.inited)\n')
        output.write('    {\n')
    def write_entry(enum, line):
        output.write('        mapping.addMapping(' + enum + '::' + line + ', "' + line + '");\n')
    def write_epilog():
        output.write('        mapping.inited = true;\n')
        output.write('    }\n')
        output.write('    return mapping;\n')
        output.write('}\n')
        output.write('RegisterEnum register_' + enum + '("' + enum + '", enum_mapping(static_cast<' + enum + '>(0)));\n')
    def write_footer():
        output.write('\n')
    enum = '???'
    state = 0  # not inside an enum
    write_header()
    for line in lines:
        # output.write('-' + line + '-\n')
        if state == 0:
            if line.startswith('"'):
                state = 6
            elif line == 'enum':
                state = 1
        elif state == 1:
            if line == '{':
                enum = 'anonymous'
                state = 3
            elif line != 'class':
                enum = line
                state = 2
            else:
                continue
            write_prolog(enum)
        elif state == 2:
            if line == '{':
                state = 3
        elif state == 3:
            if line == '}':
                write_epilog()
                state = 0
            else:
                write_entry(enum, line)
                state = 4
        elif state == 4:
            if line.startswith('"'):
                state = 5
            elif line == '}':
                write_epilog()
                state = 0
            elif line == ',':
                state = 3
        elif state == 5:
            if line.endswith('"'):
                state = 4
        elif state == 6:
            if line.endswith('"'):
                state = 0
    write_footer()