Path: blob/main_old/src/compiler/generate_parser_tools.py
1693 views
#!/usr/bin/python31# Copyright 2019 The ANGLE Project Authors. All rights reserved.2# Use of this source code is governed by a BSD-style license that can be3# found in the LICENSE file.4#5# generate_parser_tools.py:6# Common functionality to call flex and bison to generate lexer and parser of7# the translator and preprocessor.89import os10import platform11import subprocess12import sys1314is_linux = platform.system() == 'Linux'15is_windows = platform.system() == 'Windows'161718def get_tool_path_platform(tool_name, platform):19exe_path = os.path.join(sys.path[0], '..', '..', '..', 'tools', 'flex-bison', platform)2021return os.path.join(exe_path, tool_name)222324def get_tool_path(tool_name):25if is_linux:26platform = 'linux'27ext = ''28else:29assert (is_windows)30platform = 'windows'31ext = '.exe'3233return get_tool_path_platform(tool_name + ext, platform)343536def get_tool_file_sha1s():37files = [38get_tool_path_platform('flex', 'linux'),39get_tool_path_platform('bison', 'linux'),40get_tool_path_platform('flex.exe', 'windows'),41get_tool_path_platform('bison.exe', 'windows'),42get_tool_path_platform('m4.exe', 'windows')43]4445files += [46get_tool_path_platform(dll, 'windows')47for dll in ['msys-2.0.dll', 'msys-iconv-2.dll', 'msys-intl-8.dll']48]4950return [f + '.sha1' for f in files]515253def run_flex(basename):54flex = get_tool_path('flex')55input_file = basename + '.l'56output_source = basename + '_lex_autogen.cpp'5758flex_args = [flex, '--noline', '--nounistd', '--outfile=' + output_source, input_file]5960flex_env = os.environ.copy()61if is_windows:62flex_env['M4'] = get_tool_path_platform('m4.exe', 'windows')6364process = subprocess.Popen(flex_args, env=flex_env, cwd=sys.path[0])65process.communicate()66if process.returncode != 0:67return process.returncode6869# Patch flex output for 64-bit. The patch is simple enough that we could do a string70# replacement. More importantly, the location of the line of code that needs to be substituted71# can vary based on flex version, and the string substitution will find the correct place72# automatically.7374patch_in = """\n\t\tYY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),\n\t\t\tyyg->yy_n_chars, num_to_read );"""75patch_out = """76yy_size_t ret = 0;77YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),78ret, num_to_read );79yyg->yy_n_chars = static_cast<int>(ret);"""8081with open(output_source, 'r') as flex_output:82output = flex_output.read()8384# If flex's output changes such that this line no longer exists, the patch needs to be85# updated, or possibly removed.86assert (output.find(patch_in) != -1)8788patched = output.replace(patch_in, patch_out)8990# Remove all tab characters from output. WebKit does not allow any tab characters in source91# files.92patched = patched.replace('\t', ' ')9394with open(output_source, 'w') as flex_output_patched:95flex_output_patched.write(patched)9697return 09899100def run_bison(basename, generate_header):101bison = get_tool_path('bison')102input_file = basename + '.y'103output_header = basename + '_tab_autogen.h'104output_source = basename + '_tab_autogen.cpp'105106bison_args = [bison, '--no-lines', '--skeleton=yacc.c']107if generate_header:108bison_args += ['--defines=' + output_header]109bison_args += ['--output=' + output_source, input_file]110111bison_env = os.environ.copy()112bison_env['BISON_PKGDATADIR'] = get_tool_path_platform('', 'third_party')113if is_windows:114bison_env['M4'] = get_tool_path_platform('m4.exe', 'windows')115116process = subprocess.Popen(bison_args, env=bison_env, cwd=sys.path[0])117process.communicate()118return process.returncode119120121def get_input_files(basename):122files = [basename + '.l', basename + '.y']123return [os.path.join(sys.path[0], f) for f in files]124125126def get_output_files(basename, generate_header):127optional_header = [basename + '_tab_autogen.h'] if generate_header else []128files = [basename + '_lex_autogen.cpp', basename + '_tab_autogen.cpp'] + optional_header129return [os.path.join(sys.path[0], f) for f in files]130131132def generate_parser(basename, generate_header):133# Handle inputs/outputs for run_code_generation.py's auto_script134if len(sys.argv) > 1:135if sys.argv[1] == 'inputs':136inputs = get_tool_file_sha1s()137inputs += get_input_files(basename)138current_file = __file__139if current_file.endswith('.pyc'):140current_file = current_file[:-1]141inputs += [current_file]142print(','.join(inputs))143if sys.argv[1] == 'outputs':144print(','.join(get_output_files(basename, generate_header)))145return 0146147# Call flex and bison to generate the lexer and parser.148flex_result = run_flex(basename)149if flex_result != 0:150print('Failed to run flex. Error %s' % str(flex_result))151return 1152153bison_result = run_bison(basename, generate_header)154if bison_result != 0:155print('Failed to run bison. Error %s' % str(bison_result))156return 2157158return 0159160161