#!/bin/python3 import argparse import os from glob import glob import subprocess def run_input_cases(program, verbose, output=False, tests_dir="."): input_files = glob(os.path.join(tests_dir, "*.in")) if len(input_files) < 1: return os.system(program) for input_file in input_files: print(f"Running {input_file}") end_command = f"{program} < {input_file}" with open(input_file, 'r') as f: input_data = f.read() out_file = input_file.replace(".in", ".out") expected_output = None if os.path.exists(out_file): with open(out_file, 'r') as f: expected_output = f.read() result = subprocess.run(end_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) program_output = result.stdout if verbose and not output: print("Input:") print(input_data) print("") if expected_output is not None: print("Expected output:") print(expected_output) print("") print("Program output:") print(program_output.strip()) print("") if output: if expected_output is not None: # Compare the outputs if program_output == expected_output: print("✅") else: print("❌") print("Expected output:") print(expected_output.strip()) print("Program output:") print(program_output.strip()) else: print("Expected output file not found; cannot compare outputs.") if not verbose: print("Program output:") print(program_output.strip()) else: if not verbose: print(program_output.strip()) print("-----------") return def python_compile(file_name, verbose=False, tests_dir="."): run_input_cases("python3 " + file_name, verbose, tests_dir=tests_dir) return def java_compile(file_name, maven=False, verbose=False, tests_dir="."): if maven: os.system("mvn clean verify") os.system("java -jar target/*.jar") return os.system("javac " + file_name) run_input_cases("java " + file_name[:file_name.rfind(".")], verbose, tests_dir=tests_dir) return def c_compile(file_name, verbose=False, output=False, tests_dir="."): # Style the code in Meijster's way os.system("astyle -A2s2cxgk3W3xbj " + file_name) os.system("gcc -Wall -pedantic --std=c99 -g -o program -lm -Wno-unused-result " + file_name) run_input_cases("./program", verbose, output, tests_dir=tests_dir) return def main(): SUPPORTED_LANGS = [".c", ".py", ".java"] parser = argparse.ArgumentParser( prog='UCompiler', description='Compiles based on language', epilog='LOL') parser.add_argument("filename", metavar="", type=str, help="File to compile") parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Prints input and output") parser.add_argument("-a", "--alternative", action="store_true", default=False, help="Uses alternative compiler to compile") parser.add_argument("-o", "--output", action="store_true", default=False, help="Checks diff for each .in file with .out file") parser.add_argument("-t", "--tests", metavar="", type=str, help="Directory to run tests") args = parser.parse_args() file_name = args.filename file_ext = file_name[file_name.rfind("."):] if file_ext not in SUPPORTED_LANGS: print("Unsupported language") return # Use the specified tests directory or default to current directory tests_dir = args.tests if args.tests else "." if file_ext == ".c": c_compile(file_name, args.verbose, args.output, tests_dir=tests_dir) elif file_ext == ".py": python_compile(file_name, args.verbose, tests_dir=tests_dir) elif file_ext == ".java": java_compile(file_name, args.alternative, args.verbose, tests_dir=tests_dir) return if __name__ == "__main__": main()