• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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