import os
import Parser, Lexer

def Generate(parser, bison, lexer, filename):
    from BisonGen import Common

    outfile = Common.CreateFile(filename, format='c')
    write = outfile.write

    write('#include "Python.h"\n')
    write('#include "structmember.h"\n')
    write('\n')
    write('#define PROJECT_NAME "%s"\n' % parser.project)
    write('#define PARSER_NAME "%s"\n' % parser.name)
    write('\n')

    write('/* modules required for action routines */\n')
    for (package, module) in parser.imports:
        write('static PyObject *%s;\n' % module)

    # write out the state tables
    Parser.OutputTables(bison, outfile)
    Lexer.OutputTables(lexer, outfile)

    # write out the template file, adding the actions as appropriate
    dirname = os.path.dirname(__file__)
    template = open(os.path.join(dirname, 'Simple.c'))
    for line in template.readlines():
        if line == '$$parser\n':
            # Place parser actions here
            Parser.OutputActions(parser, bison, outfile)
        elif line == '$$lexer\n':
            # Place lexer actions here
            Lexer.OutputActions(parser, lexer, outfile)
        else:
            write(line)
    template.close()

    # write out the module initialization function
    module_name = parser.name + 'c'
    write('DL_EXPORT(void) init%s(void) {\n' % module_name)
    write('  PyObject *module;\n')
    write('\n')
    write('  if (PyType_Ready(&Parser_Type) < 0) return;\n')
    write('\n')
    write('  module = Py_InitModule("%s", module_methods);\n' % module_name)
    write('  if (module == NULL) return;\n')
    write('\n')
    write('  Py_INCREF(&Parser_Type);\n')
    write('  PyModule_AddObject(module, "%s",\n' % parser.name)
    write('                     (PyObject *) &Parser_Type);\n')
    write('  Py_INCREF(&Parser_Type);\n')
    write('  PyModule_AddObject(module, "new",\n')
    write('                     (PyObject *) &Parser_Type);\n')
    write('\n')

    # process the imports
    if parser.imports:
        write('  /* import the modules required for action routines */\n')
        for (package, module) in parser.imports:
            if package:
                import_stmt = IMPORT_FROM
            else:
                import_stmt = IMPORT_NAME
            write(import_stmt % {'package':package, 'module':module})
            write('\n')

    write('}\n')

    outfile.close()
    return

IMPORT_FROM = """  /* from %(package)s import %(module)s */
  %(module)s = import_from("%(package)s", "%(module)s");
  if (%(module)s == NULL) return;
"""

IMPORT_NAME = """  /* import %(module)s */
  %(module)s = PyImport_ImportModule("%(module)s");
  if (%(module)s == NULL) return;
"""

