"""Parsing grammars and functions for data and configuration files. """ from . import g from pyparsing import * lside = Literal('(*').suppress().setParseAction( lambda s, l, t: lineno(l, s)).setResultsName('start_line') rside = Literal('*)').suppress() delim = Literal('*').suppress() endfunc = Literal('***').suppress().setParseAction( lambda s, l, t: lineno(l, s)).setResultsName('delimiter_line') period = Literal('.').suppress() equals = Literal('=').suppress() semicolon = Literal(';').suppress() colon = Literal(':').suppress() comma = Literal(',').suppress() comment_mark = Literal('#').suppress() list_header = Literal('List').suppress() postlist_header = Literal('Postlist').suppress() definition_header = Literal('Definition').suppress() function_header = Literal('Functions').suppress() imports_header = Literal('Imports').suppress() _def = Literal('def') list_lside = Literal('[').suppress() list_rside = Literal(']').suppress() dict_lside = Literal('{').suppress() dict_rside = Literal('}').suppress() qs = QuotedString('"', '\\', multiline=1, unquoteResults=0) qs |= QuotedString("'", '\\', multiline=1, unquoteResults=0) tqs = QuotedString('"""', multiline=1, unquoteResults=0) comment = comment_mark + Optional(restOfLine) varname = Word(alphas, alphas + '_').setResultsName('name') nested_var = Combine(varname + ZeroOrMore('.' + varname)) _nested_var = lambda s, l, t: map(str, t) nested_var.setParseAction(_nested_var) number = Combine(Optional(Word('+-', exact=1)) + Word(nums) + Optional('.' + Word(nums))) _number = lambda s, l, t: [float(x) if '.' in x else int(x) for x in t] number.setParseAction(_number) python_list = Forward() python_dict = Forward() varvalue = tqs | qs | nested_var | number | python_list | python_dict python_list << ( list_lside + Group(ZeroOrMore(varvalue + comma) + Optional(varvalue)) + list_rside) _python_list = lambda s, l, t: ['[%s]' % ', '.join(map(str, x)) for x in t] python_list.setParseAction(_python_list) python_dict << ( dict_lside + Dict(ZeroOrMore(Group( varvalue + colon + varvalue + comma)) + Optional(Group( varvalue + colon + varvalue))) + dict_rside) _python_dict = lambda s, l, t: '{%s}' % ( ', '.join('%s: %s' % y for y in t.items())) python_dict.setParseAction(_python_dict) var_def = OneOrMore(varname + equals) + varvalue def _multi_var_def(s, l, t): value = t.pop() return [ParseResults([x, value]) for x in t] var_def.setParseAction(_multi_var_def) _list_def = Group(ZeroOrMore(varvalue + comma) + Optional(varvalue)) _list_def.setParseAction(_python_list) list_def = ( lside + list_header + delim + varname + delim + _list_def.setResultsName('contents') + rside) list_def = list_def.setResultsName('list') _postlist_def = Group(ZeroOrMore(varvalue + comma) + Optional(varvalue)) _postlist_def.setParseAction(_python_list) postlist_def = ( lside + postlist_header + delim + varname + delim + _list_def.setResultsName('pcontents') + rside) postlist_def = postlist_def.setResultsName('postlist') _definition_def = Dict(OneOrMore(var_def + semicolon)) definition_def = ( lside + definition_header + delim + varname + delim + _definition_def.setResultsName('properties') + rside) definition_def = definition_def.setResultsName('definition') _function_def = OneOrMore(Group( Combine(_def + SkipTo(endfunc)).setResultsName('funcbody') + endfunc)) function_def = ( lside + function_header + delim + Group(ZeroOrMore(varname + comma) + varname).setResultsName('names') + delim + _function_def.setResultsName('function') + rside) function_def = function_def.setResultsName('functions') imports_def = ( lside + imports_header + delim + SkipTo(rside, include=1).setResultsName('imports')) datafile = ZeroOrMore(Group( list_def | definition_def | function_def | postlist_def | imports_def)) datafile = datafile.setResultsName('datafile') + StringEnd() datafile.ignore(comment) functionfile = Dict(ZeroOrMore(Group(function_def))) conf_def = ( varname.setResultsName('key') + equals + varvalue.setResultsName('value') + semicolon) configfile = ZeroOrMore(Group(conf_def)).setResultsName('data') + StringEnd() configfile.ignore(comment) import os.path DATADIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') def gen_module(module, subclass, instantiate=1): module_file = os.path.join(DATADIR, '%s.py' % module) data_file = os.path.join(DATADIR, '%s.dat' % module) if os.path.exists(module_file): if os.path.getmtime(data_file) < os.path.getmtime(module_file): return print '. Generating %s.py...' % module def check_cache(name): if name not in cache: cache[name] = ['class %s%s(%s):' % ( 'g' if instantiate else '', name, subclass )] cache, lists, postlists, code, imports = {}, [], [], [], [] for item in datafile.parseFile(data_file): name = item.name if item.contents: lists.append('# line %d' % item.start_line) contents = ', '.join(item.contents) lists.append('%s = %s' % (name, contents)) if item.pcontents: postlists.append('# line %d' % item.start_line) contents = ', '.join(item.pcontents) postlists.append('%s = %s' % (name, contents)) elif item.properties: check_cache(name) cache[name].append('\t# line %d' % item.start_line) cache[name].append('\tdef xinit(self):') for k, v in item.properties.items(): cache[name].append('\t\tself.%s = %s' % (k, v)) elif item.function: for name in item.names: check_cache(name) for func in item.function: cache[name].append('\t# line %d' % func.delimiter_line) cache[name].extend('\t' + line for line in func.funcbody.split('\n')) elif item.imports: imports.append('# line %d' % item.start_line) imports.append(item.imports) for k, v in sorted(cache.iteritems()): code.extend(v) if instantiate: code.append('%s = g%s()' % (k, k)) code = imports + lists + code + postlists code.append("one_of_everything = [%s]" % ', '.join(cache)) st = open(module_file, 'w') st.write('\n'.join(code)) st.close() def load_config(): data = configfile.parseFile('tunnelhack.cfg') g.config = dict((str(k), eval(str(v))) for k, v in data)