about summary refs log tree commit diff homepage
path: root/stp/AST/genkinds.pl
blob: 672481ad2edb0064e5a91f30b47ff7234d3e9baf (plain) (blame)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/perl -w

#AUTHORS: Vijay Ganesh, David L. Dill BEGIN DATE: November, 2005
#LICENSE: Please view LICENSE file in the home dir of this Program
#given a file containing kind names, one per line produces .h and .cpp
#files for the kinds.

#globals
@kindnames = ();
$minkids = 0;
$maxkids = 0;
@cat_bits = ();
@category_names = ();
%cat_index = ();

$now = localtime time;

sub read_kind_defs {
    open(KFILE, "< ASTKind.kinds") || die "Cannot open .kinds file: $!\n";
    @kindlines = <KFILE>;
    close(KFILE)
}

# create lists of things indexed by kinds.
sub split_fields {
    my $kind_cat_bits;
    # matches anything with three whitespace-delimited alphanumeric fields,
    # followed by rest of line.  Automatically ignores lines beginning with '#' and blank lines.
    for (@kindlines) {
	if (/Categories:\s+(.*)/) {
	    @category_names = split(/\s+/, $1);
	    $i = 0;
	    for (@category_names) {
		$cat_index{$_} = $i++;
		# print "cat_index{$_} = $i\n";
	    }
	}
	elsif (/^(\w+)\s+(\w+)\s+(\w+|-)\s+(.*)/) {
	    push(@kindnames, $1);
	    push(@minkids, $2);
	    push(@maxkids, $3);
	    @kind_cats = split(/\s+/, $4);
	    # build a bit vector of categories.
	    $kind_cat_bits = 0;
	    for (@kind_cats) {
		$kind_cat_bits |= (1 << int($cat_index{$_}));
	    }
	    push(@cat_bits, $kind_cat_bits); 
	}
    }
}

sub gen_h_file {
    open(HFILE, "> ASTKind.h") || die "Cannot open .h file: $!\n";

    print HFILE 
	"// -*- c++ -*-\n",
	"#ifndef TESTKINDS_H\n",
	"#define TESTKINDS_H\n",
	"// Generated automatically by genkinds.pl from ASTKind.kinds $now.\n",
	"// Do not edit\n",
	"namespace BEEV {\n  typedef enum {\n";

    for (@kindnames) {
	print HFILE "    $_,\n";
    }

    print HFILE 
	"} Kind;\n\n",
	"extern unsigned char _kind_categories[];\n\n";

    # For category named "cat", generate functions "bool is_cat_kind(k);"


    for (@category_names) {
	my $catname = $_;
	my $kind_cat_bit = (1 << int($cat_index{$catname}));
	print HFILE "inline bool is_", $catname, "_kind(Kind k) { return (_kind_categories[k] & $kind_cat_bit); }\n\n"
    }

    print HFILE
	"extern const char *_kind_names[];\n\n",
	"/** Prints symbolic name of kind */\n",
	"inline ostream& operator<<(ostream &os, const Kind &kind) { os << _kind_names[kind]; return os; }\n",
	"\n\n",
	"}  // end namespace\n",
	"\n\n#endif\n";

    close(HFILE);
}

# generate the .cpp file

sub gen_cpp_file {
    open(CPPFILE, "> ASTKind.cpp") || die "Cannot open .h file: $!\n";

    print CPPFILE
	"// Generated automatically by genkinds.h from ASTKind.kinds $now.\n",
	"// Do not edit\n",
	"namespace BEEV {\n",
	"const char * _kind_names[] =  {\n";
    for (@kindnames) {
	print CPPFILE "   \"$_\",\n";
    }
    print CPPFILE "};\n\n";

    # category bits
    print CPPFILE
	"unsigned char _kind_categories[] = {\n";
    for (@cat_bits) {
	print CPPFILE "   $_,\n";
    }
    print CPPFILE 
	"};\n",
	"\n}  // end namespace\n";

    close(CPPFILE);
}

&read_kind_defs;
&split_fields;
&gen_h_file;
&gen_cpp_file;