1 # ply: ygen.py 2 # 3 # This is a support program that auto-generates different versions of the YACC parsing 4 # function with different features removed for the purposes of performance. 5 # 6 # Users should edit the method LParser.parsedebug() in yacc.py. The source code 7 # for that method is then used to create the other methods. See the comments in 8 # yacc.py for further details. 9 10 import os.path 11 import shutil 12 13 def get_source_range(lines, tag): 14 srclines = enumerate(lines) 15 start_tag = '#--! %s-start' % tag 16 end_tag = '#--! %s-end' % tag 17 18 for start_index, line in srclines: 19 if line.strip().startswith(start_tag): 20 break 21 22 for end_index, line in srclines: 23 if line.strip().endswith(end_tag): 24 break 25 26 return (start_index + 1, end_index) 27 28 def filter_section(lines, tag): 29 filtered_lines = [] 30 include = True 31 tag_text = '#--! %s' % tag 32 for line in lines: 33 if line.strip().startswith(tag_text): 34 include = not include 35 elif include: 36 filtered_lines.append(line) 37 return filtered_lines 38 39 def main(): 40 dirname = os.path.dirname(__file__) 41 shutil.copy2(os.path.join(dirname, 'yacc.py'), os.path.join(dirname, 'yacc.py.bak')) 42 with open(os.path.join(dirname, 'yacc.py'), 'r') as f: 43 lines = f.readlines() 44 45 parse_start, parse_end = get_source_range(lines, 'parsedebug') 46 parseopt_start, parseopt_end = get_source_range(lines, 'parseopt') 47 parseopt_notrack_start, parseopt_notrack_end = get_source_range(lines, 'parseopt-notrack') 48 49 # Get the original source 50 orig_lines = lines[parse_start:parse_end] 51 52 # Filter the DEBUG sections out 53 parseopt_lines = filter_section(orig_lines, 'DEBUG') 54 55 # Filter the TRACKING sections out 56 parseopt_notrack_lines = filter_section(parseopt_lines, 'TRACKING') 57 58 # Replace the parser source sections with updated versions 59 lines[parseopt_notrack_start:parseopt_notrack_end] = parseopt_notrack_lines 60 lines[parseopt_start:parseopt_end] = parseopt_lines 61 62 lines = [line.rstrip()+'\n' for line in lines] 63 with open(os.path.join(dirname, 'yacc.py'), 'w') as f: 64 f.writelines(lines) 65 66 print('Updated yacc.py') 67 68 if __name__ == '__main__': 69 main() 70 71 72 73 74 75