1#!/usr/bin/env python3.8 2"""Find the maximum amount of nesting for an expression that can be parsed 3without causing a parse error. 4 5Starting at the INITIAL_NESTING_DEPTH, an expression containing n parenthesis 6around a 0 is generated then tested with both the C and Python parsers. We 7continue incrementing the number of parenthesis by 10 until both parsers have 8failed. As soon as a single parser fails, we stop testing that parser. 9 10The grammar file, initial nesting size, and amount by which the nested size is 11incremented on each success can be controlled by changing the GRAMMAR_FILE, 12INITIAL_NESTING_DEPTH, or NESTED_INCR_AMT variables. 13 14Usage: python -m scripts.find_max_nesting 15""" 16import sys 17 18from _peg_parser import parse_string 19 20GRAMMAR_FILE = "data/python.gram" 21INITIAL_NESTING_DEPTH = 10 22NESTED_INCR_AMT = 10 23 24 25FAIL = "\033[91m" 26ENDC = "\033[0m" 27 28 29def check_nested_expr(nesting_depth: int) -> bool: 30 expr = f"{'(' * nesting_depth}0{')' * nesting_depth}" 31 32 try: 33 parse_string(expr) 34 print(f"Nesting depth of {nesting_depth} is successful") 35 return True 36 except Exception as err: 37 print(f"{FAIL}(Failed with nesting depth of {nesting_depth}{ENDC}") 38 print(f"{FAIL}\t{err}{ENDC}") 39 return False 40 41 42def main() -> None: 43 print(f"Testing {GRAMMAR_FILE} starting at nesting depth of {INITIAL_NESTING_DEPTH}...") 44 45 nesting_depth = INITIAL_NESTING_DEPTH 46 succeeded = True 47 while succeeded: 48 expr = f"{'(' * nesting_depth}0{')' * nesting_depth}" 49 if succeeded: 50 succeeded = check_nested_expr(nesting_depth) 51 nesting_depth += NESTED_INCR_AMT 52 53 sys.exit(1) 54 55 56if __name__ == "__main__": 57 main() 58