#!/usr/bin/env python3.8 """Find the maximum amount of nesting for an expression that can be parsed without causing a parse error. Starting at the INITIAL_NESTING_DEPTH, an expression containing n parenthesis around a 0 is generated then tested with both the C and Python parsers. We continue incrementing the number of parenthesis by 10 until both parsers have failed. As soon as a single parser fails, we stop testing that parser. The grammar file, initial nesting size, and amount by which the nested size is incremented on each success can be controlled by changing the GRAMMAR_FILE, INITIAL_NESTING_DEPTH, or NESTED_INCR_AMT variables. Usage: python -m scripts.find_max_nesting """ import sys import ast GRAMMAR_FILE = "data/python.gram" INITIAL_NESTING_DEPTH = 10 NESTED_INCR_AMT = 10 FAIL = "\033[91m" ENDC = "\033[0m" def check_nested_expr(nesting_depth: int) -> bool: expr = f"{'(' * nesting_depth}0{')' * nesting_depth}" try: ast.parse(expr) print(f"Nesting depth of {nesting_depth} is successful") return True except Exception as err: print(f"{FAIL}(Failed with nesting depth of {nesting_depth}{ENDC}") print(f"{FAIL}\t{err}{ENDC}") return False def main() -> None: print(f"Testing {GRAMMAR_FILE} starting at nesting depth of {INITIAL_NESTING_DEPTH}...") nesting_depth = INITIAL_NESTING_DEPTH succeeded = True while succeeded: expr = f"{'(' * nesting_depth}0{')' * nesting_depth}" if succeeded: succeeded = check_nested_expr(nesting_depth) nesting_depth += NESTED_INCR_AMT sys.exit(1) if __name__ == "__main__": main()