#!./perl -w

# How to generate the logic of the lookup table Perl_keyword() in toke.c

use strict;
package Toke;
use vars qw(@ISA %types);
require ExtUtils::Constant::Base;
@ISA = 'ExtUtils::Constant::Base';

%types = (pos => "KEY_", neg => "-KEY_");

# We're allowing scalar references to produce evil customisation.
sub valid_type {
  defined $types{$_[1]} or ref $_[1];
}


# This might actually be a return statement
sub assignment_clause_for_type {
  my ($self, $args, $value) = @_;
  my ($type, $item) = @{$args}{qw(type item)};
  my $comment = '';
  $comment = " /* Weight $item->{weight} */" if defined $item->{weight};
  return "return $types{$type}$value;$comment" if $types{$type};
  "$$type$value;$comment";
}

sub return_statement_for_notfound {
  "return 0;"
}

# Ditch the default "const"
sub C_constant_name_param_definition {
  "char *" . $_[0]->name_param;
}

sub C_constant_return_type {
  "I32";
}


sub C_constant_prefix_param {
  "aTHX_ ";
}

sub C_constant_prefix_param_defintion {
  "pTHX_ ";
}

sub C_constant_namelen_param_definition {
  'I32 ' . $_[0] -> C_constant_namelen_param;
}

package main;

my @pos = qw(__DATA__ __END__ AUTOLOAD BEGIN CHECK DESTROY do delete defined
	     END else eval elsif exists for format foreach grep goto glob INIT
	     if last local m my map next no our pos print printf package
	     prototype q qr qq qw qx redo return require s scalar sort split
	     study sub tr tie tied use undef until untie unless while y);

my @neg = qw(__FILE__ __LINE__ __PACKAGE__ and abs alarm atan2 accept bless
	     bind binmode CORE cmp chr cos chop close chdir chomp chmod chown
	     crypt chroot caller connect closedir continue die dump dbmopen
	     dbmclose eq eof err exp exit exec each endgrent endpwent
	     endnetent endhostent endservent endprotoent fork fcntl flock
	     fileno formline getppid getpgrp getpwent getpwnam getpwuid
	     getpeername getprotoent getpriority getprotobyname
	     getprotobynumber gethostbyname gethostbyaddr gethostent
	     getnetbyname getnetbyaddr getnetent getservbyname getservbyport
	     getservent getsockname getsockopt getgrent getgrnam getgrgid
	     getlogin getc gt ge gmtime hex int index ioctl join keys kill lt
	     le lc log link lock lstat length listen lcfirst localtime mkdir
	     msgctl msgget msgrcv msgsnd ne not or ord oct open opendir pop
	     push pack pipe quotemeta ref read rand recv rmdir reset rename
	     rindex reverse readdir readlink readline readpipe rewinddir seek
	     send semop select semctl semget setpgrp seekdir setpwent setgrent
	     setnetent setsockopt sethostent setservent setpriority
	     setprotoent shift shmctl shmget shmread shmwrite shutdown sin
	     sleep socket socketpair sprintf splice sqrt srand stat substr
	     system symlink syscall sysopen sysread sysseek syswrite tell time
	     times telldir truncate uc utime umask unpack unlink unshift
	     ucfirst values vec warn wait write waitpid wantarray x xor);

my %frequencies = (map {/(.*):\t(.*)/} <DATA>);

my @names;
push @names, map {{name=>$_, type=>"pos", weight=>$frequencies{$_}}} @pos;
push @names, map {{name=>$_, type=>"neg", weight=>$frequencies{$_}}} @neg;
push @names, {name=>'elseif', type=>\"", value=><<'EOC'};
/* This is somewhat hacky.  */
if(ckWARN_d(WARN_SYNTAX))
  Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "elseif should be elsif");
break;
EOC

print Toke->C_constant ({subname=>'Perl_keyword', breakout=>~0}, @names);

__DATA__
my:	3785925
if:	2482605
sub:	2053554
return:	1401629
unless:	913955
shift:	904125
eq:	797065
defined:	694277
use:	686081
else:	527806
qw:	415641
or:	405163
s:	403691
require:	375220
ref:	347102
elsif:	322365
undef:	311156
and:	284867
foreach:	281720
local:	262973
push:	256975
package:	245661
print:	220904
our:	194417
die:	192203
length:	163975
next:	153355
m:	148776
caller:	148457
exists:	145939
eval:	136977
keys:	131427
join:	130820
substr:	121344
while:	120305
for:	118158
map:	115207
ne:	112906
__END__:	112636
vec:	110566
goto:	109258
do:	96004
last:	95078
split:	93678
warn:	91372
grep:	75912
delete:	74966
sprintf:	72704
q:	69076
bless:	62111
no:	61989
not:	55868
qq:	55149
index:	51465
CORE:	47391
pop:	46933
close:	44077
scalar:	43953
wantarray:	43024
open:	39060
x:	38549
lc:	38487
__PACKAGE__:	36767
stat:	36702
unshift:	36504
sort:	36394
chr:	35654
time:	32168
qr:	28519
splice:	25143
BEGIN:	24125
tr:	22665
chomp:	22337
ord:	22221
chdir:	20317
unlink:	18616
int:	18549
chmod:	18455
each:	18414
uc:	16961
pack:	14491
lstat:	13859
binmode:	12301
select:	12209
closedir:	11986
readdir:	11716
reverse:	10571
chop:	10172
tie:	10131
values:	10110
tied:	9749
read:	9434
opendir:	9007
fileno:	8591
exit:	8262
localtime:	7993
unpack:	7849
abs:	7767
printf:	6874
cmp:	6808
ge:	5666
pos:	5503
redo:	5219
rindex:	5005
rename:	4918
syswrite:	4437
system:	4326
lock:	4210
oct:	4195
le:	4052
gmtime:	4040
utime:	3849
sysread:	3729
hex:	3629
END:	3565
quotemeta:	3120
mkdir:	2951
continue:	2925
AUTOLOAD:	2713
tell:	2578
write:	2525
rmdir:	2493
seek:	2174
glob:	2172
study:	1933
rand:	1824
format:	1735
umask:	1658
eof:	1618
prototype:	1602
readlink:	1537
truncate:	1351
fcntl:	1257
sysopen:	1230
ucfirst:	1012
getc:	981
gethostbyname:	970
ioctl:	967
formline:	959
gt:	897
__FILE__:	888
until:	818
sqrt:	766
getprotobyname:	755
sysseek:	721
getpeername:	713
getpwuid:	681
xor:	619
y:	567
syscall:	560
CHECK:	538
connect:	526
err:	522
sleep:	519
sin:	499
send:	496
getpwnam:	483
cos:	447
exec:	429
link:	425
exp:	423
untie:	420
INIT:	418
waitpid:	414
__DATA__:	395
symlink:	386
kill:	382
setsockopt:	356
atan2:	350
pipe:	344
lt:	335
fork:	327
times:	310
getservbyname:	299
telldir:	294
bind:	290
dump:	274
flock:	260
recv:	250
getsockopt:	243
getsockname:	235
accept:	233
getprotobynumber:	232
rewinddir:	218
__LINE__:	209
qx:	177
lcfirst:	165
getlogin:	158
reset:	127
gethostbyaddr:	68
getgrgid:	67
srand:	41
chown:	34
seekdir:	20
readline:	19
semctl:	17
getpwent:	12
getgrnam:	11
getppid:	10
crypt:	8
DESTROY:	7
getpriority:	5
getservent:	4
gethostent:	3
setpriority:	2
setnetent:	1
