summaryrefslogtreecommitdiff
path: root/defs/id.def
blob: 097e34e405614d16aaa881b9eb9a78c29a7dc803 (plain)
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# -*- mode: ruby; coding: us-ascii -*-
firstline, predefined = __LINE__+1, %[\
  max
  min
  freeze
  nil?
  inspect
  intern
  object_id
  const_added
  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__
  __recursive_key__
  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
  locals
  not                                                   NOT
  and                                                   AND
  or                                                    OR
  div
  divmod
  fdiv
  quo
  name
  nil

  _                                                     UScore

  # MUST be successive
  _1  NUMPARAM_1
  _2  NUMPARAM_2
  _3  NUMPARAM_3
  _4  NUMPARAM_4
  _5  NUMPARAM_5
  _6  NUMPARAM_6
  _7  NUMPARAM_7
  _8  NUMPARAM_8
  _9  NUMPARAM_9

  "/*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
  core#raise
  core#sprintf

  -                                                     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        &.
]

class KeywordError < RuntimeError
  def self.raise(mesg, line)
    super(self, mesg, ["#{__FILE__}:#{line}", *caller])
  end
end

def id2varname(token, prefix = nil)
  if /#/ =~ token
    token = "_#{token.gsub(/\W+/, '_')}"
  else
    token = token.sub(/\?/, 'P')
    token = prefix + token if prefix
    token.sub!(/\A[a-z]/) {$&.upcase}
    token.sub!(/\A\$/, "_G_")
    token.sub!(/\A@@/, "_C_")
    token.sub!(/\A@/, "_I_")
    token.gsub!(/\W+/, "")
  end
  token
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 = id2varname(token || name)
  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,
}