diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:15:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:15:05 +0000 |
commit | 46651ce6fe013220ed397add242004d764fc0153 (patch) | |
tree | 6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/interfaces/ecpg/preproc/check_rules.pl | |
parent | Initial commit. (diff) | |
download | postgresql-14-upstream.tar.xz postgresql-14-upstream.zip |
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/ecpg/preproc/check_rules.pl')
-rw-r--r-- | src/interfaces/ecpg/preproc/check_rules.pl | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/preproc/check_rules.pl b/src/interfaces/ecpg/preproc/check_rules.pl new file mode 100644 index 0000000..c0b5d19 --- /dev/null +++ b/src/interfaces/ecpg/preproc/check_rules.pl @@ -0,0 +1,191 @@ +#!/usr/bin/perl +# src/interfaces/ecpg/preproc/check_rules.pl +# test parser generator for ecpg +# call with backend grammar as stdin +# +# Copyright (c) 2009-2021, PostgreSQL Global Development Group +# +# Written by Michael Meskes <meskes@postgresql.org> +# Andy Colson <andy@squeakycode.net> +# +# Placed under the same license as PostgreSQL. +# +# Command line: [-v] [path only to ecpg.addons] [full filename of gram.y] +# -v enables verbose mode... show's some stats... thought it might be interesting +# +# This script loads rule names from gram.y and sets $found{rule} = 1 for each. +# Then it checks to make sure each rule in ecpg.addons was found in gram.y + +use strict; +use warnings; +no warnings 'uninitialized'; + +my $verbose = 0; +if ($ARGV[0] eq '-v') +{ + $verbose = shift; +} +my $path = shift || '.'; +my $parser = shift || '../../../backend/parser/gram.y'; + +my $filename = $path . "/ecpg.addons"; +if ($verbose) +{ + print "parser: $parser\n"; + print "addons: $filename\n"; +} + +my %replace_line = ( + 'ExecuteStmtEXECUTEnameexecute_param_clause' => + 'EXECUTE prepared_name execute_param_clause execute_rest', + + 'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data' + => 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest', + + 'ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data' + => 'CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest', + + 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' => + 'PREPARE prepared_name prep_type_clause AS PreparableStmt'); + +my $block = ''; +my $yaccmode = 0; +my $in_rule = 0; +my $brace_indent = 0; +my (@arr, %found); +my $comment = 0; +my $non_term_id = ''; +my $cc = 0; + +open my $parser_fh, '<', $parser or die $!; +while (<$parser_fh>) +{ + if (/^%%/) + { + $yaccmode++; + } + + if ($yaccmode != 1) + { + next; + } + + chomp; # strip record separator + + next if ($_ eq ''); + + # Make sure any braces are split + s/{/ { /g; + s/}/ } /g; + + # Any comments are split + s|\/\*| /* |g; + s|\*\/| */ |g; + + # Now split the line into individual fields + my $n = (@arr = split(' ')); + + # Go through each field in turn + for (my $fieldIndexer = 0; $fieldIndexer < $n; $fieldIndexer++) + { + if ($arr[$fieldIndexer] eq '*/' && $comment) + { + $comment = 0; + next; + } + elsif ($comment) + { + next; + } + elsif ($arr[$fieldIndexer] eq '/*') + { + + # start of a multiline comment + $comment = 1; + next; + } + elsif ($arr[$fieldIndexer] eq '//') + { + next; + } + elsif ($arr[$fieldIndexer] eq '}') + { + $brace_indent--; + next; + } + elsif ($arr[$fieldIndexer] eq '{') + { + $brace_indent++; + next; + } + + if ($brace_indent > 0) + { + next; + } + + if ($arr[$fieldIndexer] eq ';' || $arr[$fieldIndexer] eq '|') + { + $block = $non_term_id . $block; + if ($replace_line{$block}) + { + $block = $non_term_id . $replace_line{$block}; + $block =~ tr/ |//d; + } + $found{$block} = 1; + $cc++; + $block = ''; + $in_rule = 0 if $arr[$fieldIndexer] eq ';'; + } + elsif (($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:') + || $arr[ $fieldIndexer + 1 ] eq ':') + { + die "unterminated rule at grammar line $.\n" + if $in_rule; + $in_rule = 1; + $non_term_id = $arr[$fieldIndexer]; + $non_term_id =~ tr/://d; + } + else + { + $block = $block . $arr[$fieldIndexer]; + } + } +} + +die "unterminated rule at end of grammar\n" + if $in_rule; + +close $parser_fh; +if ($verbose) +{ + print "$cc rules loaded\n"; +} + +my $ret = 0; +$cc = 0; + +open my $ecpg_fh, '<', $filename or die $!; +while (<$ecpg_fh>) +{ + if (!/^ECPG:/) + { + next; + } + + my @Fld = split(' ', $_, 3); + $cc++; + if (not exists $found{ $Fld[1] }) + { + print $Fld[1], " is not used for building parser!\n"; + $ret = 1; + } +} +close $ecpg_fh; + +if ($verbose) +{ + print "$cc rules checked\n"; +} + +exit $ret; |