3 #################################################################
5 # check_bison_recursion.pl -- check for right recursion in Bison grammars
7 # The standard way to parse list constructs in Bison grammars is via left
8 # recursion, wherein a nonterminal symbol has itself as the first symbol
9 # in one of its expansion rules. It is also possible to parse a list via
10 # right recursion, wherein a nonterminal symbol has itself as the last
11 # symbol of an expansion; but that's a bad way to write it because a long
12 # enough list will result in parser stack overflow. Since Bison doesn't
13 # have any built-in way to warn about use of right recursion, we use this
14 # script when we want to check for the problem.
16 # To use: run bison with the -v switch, then feed the produced y.output
17 # file to this script.
19 # Copyright (c) 2011-2023, PostgreSQL Global Development Group
21 # src/tools/check_bison_recursion.pl
22 #################################################################
29 # must retain this across input lines
32 # We parse the input and emit warnings on the fly.
40 # We only care about the "Grammar" part of the input.
51 if (m/^\s*(\d+)\s+(\S+):\s+(.*)$/)
54 # first rule for nonterminal
56 $cur_nonterminal = $2;
59 elsif (m/^\s*(\d+)\s+\|\s+(.*)$/)
62 # additional rule for nonterminal
68 # Process rule if we found one
69 if (defined $rule_number)
73 $rhs =~ s
|^/\* empty \*/$||;
74 my @rhs = split '\s', $rhs;
75 print "Rule $rule_number: $cur_nonterminal := @rhs\n" if $debug;
77 # We complain if the nonterminal appears as the last RHS element
78 # but not elsewhere, since "expr := expr + expr" is reasonable
79 my $lastrhs = pop @rhs;
81 && $cur_nonterminal eq $lastrhs
82 && !grep { $cur_nonterminal eq $_ } @rhs)
85 "Right recursion in rule $rule_number: $cur_nonterminal := $rhs\n";