-
Notifications
You must be signed in to change notification settings - Fork 21
/
mkparse
74 lines (53 loc) · 1.56 KB
/
mkparse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/local/bin/perl
# $Id: mkparse,v 1.2 2002/03/25 07:39:46 gbarr Exp $
my($source,$dest) = @ARGV;
system qw(byacc -P),$source;
open(OUT, ">$dest") or die "Cannot open $dest: $!\n";
open(IN, "cpp y.tab.pl|");
%var = ();
%seen = ();
%state = ();
while(<IN>) {
# In perl the stack size is not a problem
next if /YYSTACKSIZE/;
next if /^# \d+ "(.*?)"/ and $1 ne "parser.y";
# Replace variables with constant subs
if(s/^\$([A-Z][A-Z_0-9]*)\s*=\s*(\d+)\s*;/sub const$1 () { $2 }/) {
$var{$1} = "const" . $1 . "()";
}
s/
(\$([A-Z][A-Z_0-9]*))
/
exists $var{$2} ? $var{$2} : $1
/xeg;
# Comment out the id line
s/^(?=\$yysccsid)/#/;
# Use my variables
s/^(\@yy\w+\s+=)/my $1/;
# Make yyparse return $$ for the top terminal
if (/^sub yyparse/ .. /^\}\s*#\s*yyparse/) {
s/\breturn\(1\)/return undef/;
s/\breturn\(0\)/return \$yyvs[\$yyvsp]/;
}
# Are we inside the switch statement ?
my $ln = /^\s+switch:/ .. /^\s+\$yyssp -= \$yym;/;
# Change all the if statements in the switch to labels
if ( $ln ) {
s/^if \(\$yyn == (\d+)\s*\)/State$1:/ and $state{"State$1"} = '';
}
# fix an uninit bug
s/^(\s*)(?=\$yycheck\[\$yyn\]\s+==)/$1\$yyn <= \$#yycheck && /;
print OUT;
# Print the goto for the switch
print OUT <<'ESQ' if $ln == 2;
my $label = "State$yyn";
goto $label if exists $yystate{$label};
last switch;
ESQ
}
# output table with names of labels that exist
my $states = '%yystate = (\'' . join("','",%state) . "');\n";
$states =~ s/(.{60,75},)/$1\n/g;
print OUT $states,"\n1;\n";
close OUT;
close IN;