Mercurial > hg > CbC > old > CbC_scripts
view meta_connector/meta_connector.py @ 29:894a300f199f default tip
change default output
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 03 Nov 2015 18:17:48 +0900 |
parents | b9f88346cecd |
children |
line wrap: on
line source
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import argparse import re # parse arguments and return arguments list. def get_args(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="""\ Parse meta connect syntax and create stub. Default output is {input file name}Connected. sample) __code code0(struct Data data1, ...){ goto code1(data1, data2, ...); \t| \tV __code code0(struct Context* context, struct Data data1, ...){ goto meta_code1(context, data1, data2, ..., Code1); """) parser.add_argument('input_file',\ nargs=None,\ type=str,\ help='input file path.') parser.add_argument('-o', dest='output',\ nargs=1,\ type=str,\ metavar='<file>',\ help='write output to <file>') parser.add_argument('--stdout',\ action='store_true',\ default=False,\ help='output to stdout') return parser.parse_args() # parse input file and create meta connection list def parse_meta_syntax(lines,file): comment_out = False caller_name = '' isMetaOrStub = False defaultMetaIsNotExist = True for i,l in enumerate(lines): regexed_l = re.search(r"[a-zA-Z0-9_]+ *\(",l) # get caller code segment name if re.search(r"^ *__code",l) is not None: # code segment declarations. isMetaOrStub = False caller_name = regexed_l.group(0).rstrip('(') args = get_args_from_line(l) if caller_name == 'meta': defaultMetaIsNotExist = False if re.search(r"^ *meta_*|stub$",caller_name) is not None: # meta code segments or stubs isMetaOrStub = True elif not cs_search(lines, caller_name+'_stub'): # normal code segments which do not have a stub. create_stub(file, caller_name, args.strip(',')) if re.search(r"struct Context\* context",l) is None: # add context to arguments list if it didn't have. file.write("/*-- generated by script */\n") file.write('// '+l) file.write('__code {0:s}(struct Context* context{1:s}) {{\n'.format(caller_name, args)) else: file.write(l) elif not isMetaOrStub and regexed_l is not None and re.search(r"^ *goto",l): # code segment transition. callee_name = regexed_l.group(0).rstrip('(') if callee_name == 'start_code' or re.match('meta_|meta$',callee_name): file.write(l) elif re.search(r"\(context", l) is None: connect_meta(file, lines, l, caller_name, callee_name) # file.write("/*-- connected by script */\n") # file.write('// '+l) # meta_name = 'meta_'+caller_name if cs_search(lines, 'meta_'+callee_name) else 'meta' # file.write("goto {0:s}(context{1:s}, {2:s});\n".format(meta_name, args,\ # callee_name.capitalize())) else: file.write(l) else: file.write(l) if defaultMetaIsNotExist: create_default_metacs(file) def create_default_metacs(file): file.write(''' __code meta(struct Context* context, enum Code next) { goto (context->code[next])(context); } ''') def get_args_from_line(line): args = line.split('(')[1].rsplit(')')[0].strip() args = ', ' + args if args else '' return args def create_stub(file, name, args): file.write('''__code {0:s}_stub(struct Context* context) {{ goto {0:s}(context'''.format(name)) for arg in args_str2args_list(args): file.write(', &context->data['+arg.capitalize()+']->'+arg) file.write(');\n}\n') def connect_meta(file, lines, l, caller_name, callee_name): meta_name = 'meta_'+caller_name if cs_search(lines, 'meta_'+caller_name) else 'meta' args = get_args_from_line(l) file.write("/*-- connected by script */\n") file.write('// '+l) file.write("goto {0:s}(context".format(meta_name)) for arg in args_str2args_list(args): file.write(', '+arg) file.write(', '+callee_name.capitalize()+');\n') def args_str2args_list(args_str): args_list = [] temporary_list = args_str.split() for i,arg in enumerate(temporary_list): if re.search(r"context,*", arg) is not None: continue if re.search(r"[a-zA-Z0-9_] *,$", arg) is not None or i == len(temporary_list)-1: args_list.append(arg.strip(',')) return args_list # search meta code segment. # It returns true when cs was found. # Find it : __code meta_'name' def cs_search(lines, name): for l in lines: if re.search(r"^ *__code {0:s}\(".format(name),l) is not None: return True return False def main(): args = get_args() output = sys.stdout try: f = open(args.input_file,'r') except IOError: sys.exit("Error: cannot open file %s" % args.input_file) if not args.stdout: try: filename = args.input_file.split('.')[0]+'Connected.c' output = open(filename,'w') except IOError: sys.exit("Error: cannot open file %s" % filename) if args.output is not None: try: output = open(args.output[0],'w') except IOError: print("cannot open file %s" % args.output) lines = f.readlines() parse_meta_syntax(lines, output) main()