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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
# -*- mode: ruby; coding: us-ascii -*-
firstline, predefined = __LINE__+1, %[\
max
min
freeze
inspect
intern
object_id
const_missing
method_missing MethodMissing
method_added
singleton_method_added
method_removed
singleton_method_removed
method_undefined
singleton_method_undefined
length
size
gets
succ
each
proc
lambda
send
__send__
__attached__
initialize
initialize_copy
initialize_clone
initialize_dup
to_int
to_ary
to_str
to_sym
to_hash
to_proc
to_io
to_a
to_s
to_i
to_f
to_r
bt
bt_locations
call
mesg
exception
not NOT
and AND
or OR
_ UScore
"/*NULL*/" NULL
empty?
eql?
respond_to? Respond_to
respond_to_missing? Respond_to_missing
<IFUNC>
<CFUNC>
core#set_method_alias
core#set_variable_alias
core#undef_method
core#define_method
core#define_singleton_method
core#set_postexe
core#hash_merge_ptr
core#hash_merge_kwd
- debug#created_info
$_ LASTLINE
$~ BACKREF
$! ERROR_INFO
]
# VM ID OP Parser Token
token_ops = %[\
Dot2 .. DOT2
Dot3 ... DOT3
BDot2 .. BDOT2
BDot3 ... BDOT3
UPlus +@ UPLUS
UMinus -@ UMINUS
Pow ** POW
Cmp <=> CMP
PLUS +
MINUS -
MULT *
DIV /
MOD %
LTLT << LSHFT
GTGT >> RSHFT
LT <
LE <= LEQ
GT >
GE >= GEQ
Eq == EQ
Eqq === EQQ
Neq != NEQ
Not !
And &
Or |
Backquote `
EqTilde =~ MATCH
NeqTilde !~ NMATCH
AREF []
ASET []=
COLON2 ::
ANDOP &&
OROP ||
ANDDOT &.
METHREF .:
]
class KeywordError < RuntimeError
def self.raise(mesg, line)
super(self, mesg, ["#{__FILE__}:#{line}", *caller])
end
end
predefined_ids = {}
preserved_ids = []
local_ids = []
instance_ids = []
global_ids = []
const_ids = []
class_ids = []
attrset_ids = []
token_op_ids = []
names = {}
predefined.split(/^/).each_with_index do |line, num|
next if /^#/ =~ line
line.sub!(/\s+#.*/, '')
name, token = line.split
next unless name
token ||= name
if /#/ =~ token
token = "_#{token.gsub(/\W+/, '_')}"
else
token = token.sub(/\?/, 'P').sub(/\A[a-z]/) {$&.upcase}
token.sub!(/\A\$/, "_G_")
token.sub!(/\A@@/, "_C_")
token.sub!(/\A@/, "_I_")
token.gsub!(/\W+/, "")
end
if name == '-'
preserved_ids << token
next
end
if prev = names[name]
KeywordError.raise("#{name} is already registered at line #{prev+firstline}", firstline+num)
end
if prev = predefined_ids[token]
KeywordError.raise("#{token} is already used for #{prev} at line #{names[prev]+firstline}", firstline+num)
end
names[name] = num
case name
when /\A[A-Z]\w*\z/; const_ids
when /\A(?!\d)\w+\z/; local_ids
when /\A\$(?:\d+|(?!\d)\w+|\W)\z/; global_ids
when /\A@@(?!\d)\w+\z/; class_ids
when /\A@(?!\d)\w+\z/; instance_ids
when /\A((?!\d)\w+)=\z/; attrset_ids
else preserved_ids
end << token
predefined_ids[token] = name
end
token_ops.split(/^/).each do |line|
next if /^#/ =~ line
line.sub!(/\s+#.*/, '')
id, op, token = line.split
next unless id and op
token ||= (id unless /\A\W\z/ =~ op)
token_op_ids << [id, op, token]
end
{
"LOCAL" => local_ids,
"INSTANCE" => instance_ids,
"GLOBAL" => global_ids,
"CONST" => const_ids,
"CLASS" => class_ids,
"ATTRSET" => attrset_ids,
:preserved => preserved_ids,
:predefined => predefined_ids,
:token_op => token_op_ids,
}
|